Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Redraw QtGraphicsItem
Qt 6.11 is out! See what's new in the release blog

Redraw QtGraphicsItem

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 2.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ModelTechM Offline
    ModelTechM Offline
    ModelTech
    wrote on last edited by ModelTech
    #1

    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?

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      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.

      1 Reply Last reply
      0
      • ModelTechM Offline
        ModelTechM Offline
        ModelTech
        wrote on last edited by ModelTech
        #3

        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?

        mrjjM 1 Reply Last reply
        0
        • ModelTechM ModelTech

          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?

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @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

          1 Reply Last reply
          0
          • ModelTechM Offline
            ModelTechM Offline
            ModelTech
            wrote on last edited by
            #5

            Great, thanks: I will use update then :)

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved