Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

failed to paint after call update



  • Thanks your guys in advance.

    There's my program

    gui.h:

    #include <QGuiApplication>
    #include <QPainter>
    #include <QtQuick>

    class CGui: public QQuickPaintedItem{
    Q_OBJECT
    public:
    CGui(QQuickItem *parent = 0) : QQuickPaintedItem(parent) { }

    void paint(QPainter *painter);
    void init(QQmlApplicationEngine *engine);
    //void carmove(int, int);
    

    private:
    //QObject *m_carhnd;

    public slots:
    void refresh();

    };

    gui.cpp:

    #include <QDebug>
    #include <QPainter>

    void CGui::init(QQmlApplicationEngine engine)
    {
    QTimer
    timer = new QTimer;
    timer->start(1000);
    connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
    }

    void CGui::paint(QPainter *painter)
    {
    qDebug() << "paint.";
    }

    void CGui::refresh()
    {
    qDebug() << "refresh";
    update();
    }

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>

    #include "gui.h"

    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);

    qmlRegisterType<CGui>("myCGui", 1, 0, "CGui");
    
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    
    CGui gui;
    gui.init(&engine);
    
    return app.exec();
    

    }

    main.qml:

    import QtQuick 2.8
    import QtQuick.Window 2.2
    import myCGui 1.0

    Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"'))
        }
    
        CGui {
            width: Window.width * 0.618
            height: Window.height
    
        }
    
    }
    

    }

    mainForm.yi.qml:

    import QtQuick 2.8

    Rectangle {
    property alias mouseArea: mouseArea
    property alias textEdit: textEdit

    width: 360
    height: 360
    
    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }
    
    TextEdit {
        id: textEdit
        text: qsTr("Enter some text...")
        verticalAlignment: Text.AlignVCenter
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.topMargin: 20
        Rectangle {
            anchors.fill: parent
            anchors.margins: -10
            color: "transparent"
            border.width: 1
        }
    }
    

    }

    It's a simple code, but paint just was called once, could you guys point out where is fishy?


  • Qt Champions 2017

    Does this code compiles ? If yes, do you see your refresh(..) method is repeatedly called ? Can you make the connect statement above the start(..) ?



  • Yes, it has been compiled successfully. connect refresh method to timer timeout signal, it will be called every 1s.


  • Qt Champions 2017

    The code you copied here does not compile. It has many compilation errors.
    Also you said paint is not working. In your program you are doing nothing in paint(..). So what did you expect to happen ? You are creating two object of CGUI. Any reason you have two objects ?

    Currently you program is working the way it is expected to work. What you expected out of this program we don't know.



  • Sorry, I am a qt rookie.

    1. You mentioned I created two objects of CGui, you mean firstly I called qmlRegisterType, next I created CGui gui?

    This is a sample code, what I want to do is to check whether the update is working. If it works, I can do more things. Therefore, I only put qDebug() in paint method to test.

    1. I think the code can be compiled correctly, the compiler didnt show me any errors at least. If you want, please tell me the errors.

  • Moderators

    @Jing-Xu
    I'm not quite sure what you expect to happen, update() shedules a repaint request for next eventcycle.

    your paint function will not be called from that! What is going to be call the the QWidget::paintEvent(QPaintEvent *event) function! That paint function you made will not be called.


    Edit:
    I failed to see that you're subclassing QQuickItem, my post was for QWidget based classes, my bad.

    But, my argument is still valid, instead of paintEvent hower, a updatePaintNode() is sheduled. paint will still not be called.


  • Qt Champions 2017

    Just look compilation issue issues -
    @Jing-Xu said in failed to paint after call update:

    void CGui::init(QQmlApplicationEngine engine)

    Your method expects object. But you are passing the address of object while calling in main.
    gui.init(&engine);

    QTimer timer = new QTimer; // You are create the heap object. But variable is not address.

    I wonder how your application is really compiling.

    Now
    Two objects are created -

    1. CGui gui; // inside main.cpp
      gui.init(&engine);

    2. CGui {
      width: Window.width * 0.618
      height: Window.height
      }

    qmlregistertype will only register the type. It will not create object.

    Question for you -
    What are you expecting from you program ? How are you expecting the program to work ?



  • @J.Hilk
    Hi, thank you for your reply. But I cannot agree with you. I am using qml instead of widget, so it's different. I wonder widget call paintevent method as well as qml call pain method .

    Otherwise, it called paint method once in the first place.

    Moreover, I am gonna learn more about updatePaintNode().



  • @dheerendra

    Exactly, I made these mistakes, my bad. Thanks for pointing out.

    My aim is to draw and show some lines real time. This is the way I can figure out.

    1. If you have more efficient or better way, could you give me some tips or links?

    2. By the way, create two objects may be not that good, could you tell me how to deal with this case?



  • @dheerendra
    Hi,

    I checked this code in my project today,

    void CGui::init(QQmlApplicationEngine engine)
    QTimer
    timer = new QTimer;

    I have no idea why the * symbol is missing.


  • Qt Champions 2017

    @Jing-Xu said in failed to paint after call update:

    QQuickPaintedItem

    Did you get a chance to look at the example in Qt installation directory ?
    quick/customitems/painteditem/textballoon.h



  • @dheerendra

    Hi, I got some inspiration from this code.

    Now, there is my latest code. It works.

    I have another question, how to deliver parameters to CGui class, like coordinates, for drawing lines real time? These parameters come from another cpp source.

    gui.h:

    #ifndef GUI_H
    #define GUI_H
    
    #include <QGuiApplication>
    #include <QPainter>
    #include <QtQuick>
    
    class CGui: public QQuickPaintedItem{
    Q_OBJECT
    public:
        CGui(QQuickItem *parent = 0) : QQuickPaintedItem(parent) { }
    
        void paint(QPainter *painter);
        Q_INVOKABLE void init();
        //void carmove(int, int);
    
    private:
        //QObject *m_carhnd;
    
    public slots:
        void refresh();
    
    };
    
    
    
    
    #endif // GUI_H
    
    

    gui.cpp

    
    #include "gui.h"
    
    #include <QDebug>
    #include <QPainter>
    
    void CGui::init()
    {
        qDebug() << "init";
    
        QTimer* timer = new QTimer;
        timer->start(1000);
        connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
    }
    
    void CGui::paint(QPainter *painter)
    {
        qDebug() << "paint.";
    }
    
    void CGui::refresh()
    {
        qDebug() << "refresh";
        update();
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include "gui.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<CGui>("myCGui", 1, 0, "CGui");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    

    main.qml:

    import QtQuick 2.8
    import QtQuick.Window 2.2
    import myCGui 1.0
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        MainForm {
            anchors.fill: parent
            mouseArea.onClicked: {
                console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"'))
            }
    
            Component.onCompleted: {
                gui.init()
            }
    
            CGui {
                id:gui
                width: Window.width * 0.618
                height: Window.height
    
            }
    
        }
    }
    
    

  • Qt Champions 2017

    Can you do some drawing inside the paint(...) method. First check whether you are able to draw something. Once you make this work, we can try changing some parameters through timer function, redraw. This work can give you idea how to pass parameters from other objects.


Log in to reply