Solved Redraw QtGraphicsItem
-
I am trying to make a Graphical Editor with decent Model - View separation. Therefore, I have created a little tryout program as follows (layout is compacted to keep some overview here):
Relevant parts of port.h:
#include <QObject> class Port : public QObject { Q_OBJECT public: Port(const QString &Name = ""); const QString &name(); public slots: void rename(); private: QString Name; };
Relevant parts of port.cc:
#include <QInputDialog> #include "port.h" Port::Port(const QString &N) : QObject() { Name = N; } const QString &Port::name() { return Name; } void Port::rename() { bool Ok; QString Text = QInputDialog::getText(0, tr("Rename Port"), QString(), QLineEdit::Normal, Name, &Ok); if (Ok && !Text.isEmpty()) Name = Text; }
Relevant parts of portdrawing.h:
#include <QCoreApplication> #include <QGraphicsItem> #include <QGraphicsSceneContextMenuEvent> #include <QMenu> #include "port.h" class PortDrawing : public QGraphicsItem { Q_DECLARE_TR_FUNCTIONS(PortDrawing) public: PortDrawing(Port *Port, int XPosition, int YPosition); QRectF boundingRect() const; void paint(QPainter *Painter, const QStyleOptionGraphicsItem *, QWidget *); private: Port *Definition; QRectF textRect() const; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); };
Relevant parts of portdrawing.cc:
#include <QApplication> #include <QFont> #include <QFontMetricsF> #include <QPainter> #include "portdrawing.h" PortDrawing::PortDrawing(Port *P, int X, int Y) { Definition = P; ... } QRectF PortDrawing::boundingRect() const { QRectF Rect = textRect(); // Some code to increase the size of the bounding rect taking into account the graphical parts return Rect; } QRectF PortDrawing::textRect() const { QFontMetricsF Metrics = QFontMetricsF(qApp->font()); QRectF Rect = Metrics.boundingRect(Definition->name()); // Some code to fix the coordinates depending on where the text is located in relation to the graphical parts return Rect; } void PortDrawing::paint(QPainter *Painter, const QStyleOptionGraphicsItem *, QWidget *) { // Some code to draw the graphical parts Painter->drawText(textRect(), Qt::AlignCenter, Definition->name()); } void PortDrawing::contextMenuEvent(QGraphicsSceneContextMenuEvent *Event) { QMenu *Menu = new QMenu(); QAction *Rename = new QAction(tr("Rename"), 0); Menu->addAction(Rename); Menu->popup(Event->screenPos()); QObject::connect(Rename, SIGNAL(triggered()), Definition, SLOT(rename())); }
mainwindow.cpp:
MainWindow::MainWindow(QWidget *Parent) : QMainWindow(Parent) { Port *P = new Port("Test"); PortDrawing *PD = new PortDrawing(P, 50, 50); QGraphicsScene *Scene = new QGraphicsScene(0, 0, 100, 100); Scene->addItem(PD); QGraphicsView *View = new QGraphicsView; View->setScene(Scene); View->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); setCentralWidget(View); }
Now, my question is as follows. When I enter a new name for the port through the QInputDialog, I would like the text of the PortDrawing to be redrawn. When I compiled this with an earlier version of Qt, such updates happened automagically (and I was surprised about that). Now that I have upgraded my Qt version to 5.7.0, this automatic redrawing does not happen anymore. Can anybody give some help on how to make the PortDrawing object to redraw itself after the Name of the Port is changed?
-
hi
silly question but did you try calling update on it?
after you set new text.also, just a note
http://doc.qt.io/qt-5/qtwidgets-graphicsview-diagramscene-example.html
is ok example of editor. -
I tried calling update, but to be honest I actually don't know from were...
Thanks for the pointer to the example, I had found this as well and used some bits of it for my example in combination with some bits of an example in the Qt Book. However, now that I looked at it more closely, I understand that the Port should signal to the MainWindow on successfully renaming it, which then has to call update on the Scene or View.
Edit: After a bit of additional googling, I was able to fix the problem by connecting a signal from Port emitted on successfully renaming it to the update slot of the viewport in the QGraphicsView.
Remaining question is: which slot is better to use: update or repaint?
-
@ModelTech
Hi both repaint and update will work.
update being more polite as it will post a repaint to event queue whereas
repaint will repaints the widget directly by calling paintEvent() immediately.
At least for normal widgets :)
http://doc.qt.io/qt-5/qwidget.html#repaint -
Great, thanks: I will use update then :)