How can I append new rectangle shape to QgraphicView In this code which create rectangle when the button click.But when I click the button second time previously created rectangle removed.I need to do create 2 rectangle when I click the button 2 times.create 3 rectangle when I click the button 3 times
void Widget::on_btnCreateRect_clicked()
{
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
//QBrush redBrush(Qt::red);
QBrush blueBrush(Qt::blue);
QPen blackPen(Qt::black);
blackPen.setWidth(6);
rect = scene->addRect(-10,-10,100,100,blackPen,blueBrush);
rect->setFlag(QGraphicsItem::ItemIsMovable, true);
}
With scene = new QGraphicsScene(this); you create a new scene and add the rectangle to it. The old scene with the previous rectangles exist but is not shown anymore. So instead of creating a new scene use the old one like that: rect = ui->graphicsView->scene()->addRect(-10,-10,100,100,blackPen,blueBrush);. This will also avoid the memory leak you create with new. Here is the corrected code:
void Widget::on_btnCreateRect_clicked()
{
//QBrush redBrush(Qt::red);
QBrush blueBrush(Qt::blue);
QPen blackPen(Qt::black);
blackPen.setWidth(6);
QRect *rect = ui->graphicsView->scene()->addRect(-10,-10,100,100,blackPen,blueBrush);
rect->setFlag(QGraphicsItem::ItemIsMovable, true);
}
Related
I have a QGraphicsItem with an embedded QWidget, this QWidget have a QPushButton in it.
I'm trying to map the center of the QPushButton to the QGraphicsScene coordinates, so for example, I can add a Circle to the center of the QPushButton.
With the help from another post I was able to find the center of the QPushButton, but it doesn't correspond to its actual position in the QGraphicsScene.
What I tried:
Getting the QRect of the button and then its center, finally mapping to the global coordinates of the view.
Getting the QRect of the button, then its center and mapping it to the QGraphicsItem.
Getting the QRect of the button, then its center, mapping it to the QGraphicsItem and than mapping it to the scene.
In general, I tried mapping it to Scene, to Global and to Item but it always looks incorrect. And the farther I move the QGraphicsItem, the less accurate it gets. Here the circle is supposed to be positioned at the center of the "B" button:
Qwidget:
class NodeFrame : public QFrame
{
public:
NodeFrame();
QRect getButtonRect()
{
return layout->itemAt(0)->geometry();
}
private:
QPushButton* button = nullptr;
QHBoxLayout* layout = nullptr;
};
NodeFrame::NodeFrame()
{
setFixedSize(200,80);
// Creates and add a QPushButton to the frame.
// I need the position of this button on the QGraohicsScene
button = new QPushButton("B");
button->setFixedSize(40,20);
layout = new QHBoxLayout();
layout->addWidget(button);
layout->setAlignment(Qt::AlignCenter);
setLayout(layout);
}
QGraphicsItem:
class Node : public QGraphicsItem
{
public:
Node();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRect getButtonRect()
{
return frame->getButtonRect();
}
NodeFrame* frame = nullptr;
};
Node::Node()
{
setFlag(ItemIsMovable);
// Create a GraphicsProxyWidget to insert the nodeFrame into the scene
auto proxyWidget = new QGraphicsProxyWidget(this);
frame = new NodeFrame();
proxyWidget->setWidget(frame);
// Center the widget(frame) at the center of the QGraphicsItem
proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
}
QRectF Node::boundingRect() const
{
return QRectF(-10, -10, 280, 150);
}
void Node::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QPainterPath path;
path.addRoundedRect(boundingRect(), 10, 10);
painter->drawPath(path);
}
main:
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// Create scene and view
auto scene = new QGraphicsScene();
auto view = new QGraphicsView(scene);
view->setMinimumSize(800, 800);
// Create the QGraphicsItem and add it to the scene
auto item = new Node();
scene->addItem(item);
item->setPos(50, 50);
auto btnRect = item->getButtonRect();
auto center = view->mapToGlobal(btnRect.center());
auto circle = new QGraphicsEllipseItem();
circle->setRect(QRectF(center.x(), center.y(), 25, 25));
scene->addItem(circle);
// Show the the view
view->show();
return app.exec();
}
Appreciate any help.
Solved. This was caused by two things:
1: QRectF getButtonRect() was returning layout->itemAt(0)->geometry(), (index 0 being the first and only widget in the layout) but button->frameGeometry() seems to be a more accurate visual representation of the button's geometry.
2: When adding the widget to the graphic item using QGraphicsProxyWidget, I was adjusting the position of the widget inside the graphic item using:
proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
This was changing the position (obviously) of the widget inside the graphic item, so visually it didn't align with the result given by button->frameGeometry().
I am trying to achieve this layout:
where Widget1 is some widget (central widget of QMainWindow) and I want to add second widget Widget2 over it but it should be in left bottom corner of Widget1.
EDIT: my previous description wasn't very useful so I will try to describe it in more details.
I am inheriting QWidget class (class MyClass : public QWidget) and creating my own widget where I in void MyClass ::paintEvent(QPaintEvent *event) draw something on screen.
MyClass is then centralWidget of my QMainWindow.
Now on top of that I want to add smaller widget (Widget2 in image) where I would display some video (here I am not asking how to display video only how to add this Widget2 to my view).
Main thing here is that Widget2 is inside (floating in) Widget1.
EDIT2: Previous code I posted is rubbish.
Use QGridLayout to set the position of the widget:
QGridLayout* layout = new QGridLayout(this);
// 2x2 layout
QWidget* green = new QWidget(this);
green->setStyleSheet("background:green;");
QWidget* yellow = new QWidget(this);
yellow->setStyleSheet("background:yellow;");
QWidget* red = new QWidget(this);
red->setStyleSheet("background:red;");
QWidget* blue = new QWidget(this);
blue->setStyleSheet("background:blue;");
layout->addWidget(green, 0, 0); // Top-Left
layout->addWidget(yellow, 0, 1); // Top-Right
layout->addWidget(red, 1, 0); // Bottom-Left
layout->addWidget(blue, 1, 1); // Bottom-Right
ui->centralWidget->setLayout(layout);
Will give you something like that:
So, custom your own widget using QGridLayout and set the position of your widget inside it.
Set another widget as parent with black background:
QGridLayout* layout = new QGridLayout(this);
// 2x2 layout
QWidget* green = new QWidget(this);
green->setStyleSheet("background:green;");
QWidget* yellow = new QWidget(this);
yellow->setStyleSheet("background:yellow;");
QWidget* red = new QWidget(this);
red->setStyleSheet("background:red;");
QWidget* blue = new QWidget(this);
blue->setStyleSheet("background:blue;");
layout->addWidget(green, 0, 0); // Top-Left
layout->addWidget(yellow, 0, 1); // Top-Right
layout->addWidget(red, 1, 0); // Bottom-Left
layout->addWidget(blue, 1, 1); // Bottom-Right
QWidget* mainWidget = new QWidget(this);
mainWidget->setStyleSheet("background:black;");
mainWidget->setLayout(layout);
QHBoxLayout* centralLayout = new QHBoxLayout(this);
centralLayout->addWidget(mainWidget);
ui->centralWidget->setLayout(centralLayout);
I'm trying to create an interface for myself on Qt and I need a few rectangles over a DICOM image (a magnetic ressonance image), so they need to be some color other than black but I can't find a way to set a brush for the QGraphicsItemGroup I'm using to keep the rectangles organized.
QGraphicsScene lets me add a QRect associated to a QBrush individually with
QgraphicsScene *scene = new QGraphicsScene();
QRectF rect = QRectF(QPoint(1,2),QPoint(3,4));
scene->addRect(rect, QBrush(Qt::red)); // using red as example
but adding each rectangle individually would make it all too messy and probably way slower. I need a way to set a QBrush for the rectangles but using QGraphicsItemGroup to be added to the QGraphicsScene.
Why can you not reimplement QGraphicsItemGroup and inside have a function called:
void ReimplementedQGraphicsItemGroup::SetRectangleBrush(const QBrush& brush)
and inside that function iterate over every rectangle you have added to the group setting the brush
QgraphicsScene *scene = new QGraphicsScene();
ReimplementedQGraphicsItemGroup ReimplGraphicsGroup = new ReimplementedQGraphicsItemGroup()
// First rect
QGraphicsRectItem rect(1,2,3,4);
rect.setBrush(QColor(Qt::red);
ReimplGraphicsGroup->AddRectangle(rect);
// Second rect
QGraphicsRectItem rect2(5,6,7,8);
rect2.setBrush(QColor(Qt::blue);
ReimplGraphicsGroup->AddRectangle(rect2);
// add reimplemented graphics item group to scene
scene->addItem(ReimplGraphicsGroup);
void ReimplementedQGraphicsItemGroup::SetRectangleBrush(const QBrush& brush)
{
foreach (QGraphicsRectItem rect, m_ListRects)
{
rect.setBrush(brush);
}
}
class ReimplementedQGraphicsItemGroup : public QGraphicsItemGroup {
// a member of ReimplementedQGraphicsItemGroup
QList<QGraphicsRectItem> m_ListRects;
}
void ReimplementedQGraphicsItemGroup::AddRectangle(QGraphicsRectItem rect)
{
addToGroup(rect);
m_ListRects.append(rect);
}
I'm trying to draw with QPainter in a QPixmap, put that QPixmap in a QLabel, and that QLabel in a QScrollArea.
Sometimes the painted pixmap is bigger then my ScrollArea allows, but somehow it doesn't scroll to show the rest. What am I doing wrong?
QPixmap *pixmap = new QPixmap(10000,500);
QLabel *labeltime = new QLabel;
QHBoxLayout *layout = new QHBoxLayout;
pixmap->fill(QColor("transparent"));
int currentX = 0;
const int currentY = 220;
const int height = 50; // Coming from some static data initialization
QPainter *painter = new QPainter(pixmap);
QPen pen(Qt::gray, 2);
painter->setPen(pen);
for(int i = 0; i< viewlist.size(); i++)
{
QBrush brush(QColor(viewlist[i].color));
painter->setBrush(brush);
painter->drawRect(currentX, currentY, viewlist[i].length, height);
currentX += viewlist[i].length;
}
labeltime->setPixmap(*pixmap);
layout->addWidget(labeltime);
ui->overview->setLayout(layout);
I know this is a long and weird way to add a pixmap, but I want it to be scrollable, and I can't paint on a QScrollArea. Is there a better way? Or can someone tell me what is wrong?
Thanks
Since you only have one child widget, it is simpler to eliminate your layout. Change these lines:
layout->addWidget(labeltime);
ui->overview->setLayout(layout);
to:
ui->overview->setWidget(labeltime);
Want to place a QPushButton onto a GraphicView... but no button is displayed?
I am creating a new window for each plot. On each plot I want to put some buttons for functionality. I don't know if I should put the view on another type of window... if so how? thx
QGraphicsScene *scene = new QGraphicsScene();
QPixmap image;
image.load(fileInfo.filePath(), 0);
scene->addPixmap(image);
scene->setSceneRect(image.rect());
QGraphicsView *view = new QGraphicsView();
view->setScene(scene);
view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "My Plot"));
view->resize(1000, 1000);
view->show();
QPushButton *m_button6 = new QPushButton("ok", view);
m_button6->setGeometry(QRect(QPoint(50, 50), QSize(50, 50)));
connect(m_button6, SIGNAL(released()), this, SLOT(handleButton5()));
wrap it around QGraphicsWidget.
QGraphicsWidget *pBtn = scene->addWidget(m_button6);
scene->addItem(pBtn)
oh! don't forget:
m_button6->show();
widgets are hidden by default!