QML: Problem with paint() function



  • Hello,

    I have a Node Item specified in C++ and in QML.

    I override the paint method in Node.cpp in the manner to draw a line between two nodes.

    Here the code extraction:

    @
    void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
    QPen pen;
    pen.setColor(Qt::blue);
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(6);
    painter->setPen(pen);
    painter->setRenderHints(QPainter::Antialiasing, true);

    for (QList<Node*>::const_iterator itParent = this->_parents.begin();
         itParent != this->_parents.end();
         ++itParent)
    {
        QPoint startPoint(this->posX(), this->posY());
        QPoint endPoint((*itParent)->posX(), (*itParent)->posY());
    
        painter->drawLine(startPoint, endPoint);
    }
    

    }
    @

    @
    import QtQuick 1.0

    Rectangle {
    width: 500
    height: 500

    Repeater {
        anchors.fill: parent
        model: configModel
        delegate: Node {}
    }
    

    }
    @

    @
    import QtQuick 1.0
    import NodeLib 1.0

    Node {
    id: nodeDelegate
    x: posX
    y: posY
    visible: isDisplayed

    Image{
        id : nodeIcon
        source: iconFilePath
    }
    
    Text {
       anchors.top: nodeIcon.bottom
       text: nodeID
    }
    
    MouseArea {
       anchors.fill: parent
    }
    

    }
    @

    I also do setFlag(ItemHasNoContents, false); in the constructor of Node.cpp

    The problem is I don´t get the line painted. I traced the code and I see that I pass through the paint function, but the this pointer points to an empty object and not to the object that I created in the main.cpp !
    I don´t understand why I don´t call the paint function on the Node objects that I have created in main.cpp

    Any idea ?

    Thanks in advance !


  • Moderators

    Because you instantiate Node object in QML. It just uses your Node cpp class as a base, it has no relation to any nodes you construct in main.cpp.

    Also, you would need to map parent coordinates to item's coords. Coordinates in items are local.



  • How could I make the connection between the empty created classes in QML when paint() is called and my instanciated Node objects in main.cpp. So QML creates three empty Node objects (there are three Nodes in the List Model), call the paint function and them fill them with values from the model ?

    Maybe I can define a copyconstructor in Node.cpp and call inside the paint function or even update() ?

    About the coordinates, no idea how to map them ... Could you please give me some example ?

    Thanks


  • Moderators

    There are methods for mapping in your "base class":http://qt-project.org/doc/qt-4.8/qdeclarativeitem.html#mapFromItem.

    You can send pointers to those "empty" objects back to C++, and then do some magic there, or refactor your code so that it does not need any special data in the constructor. Then you can pass the info you need to pass when the object is completed:
    @
    Component.onCompleted: someInitMethodWrittenInNodeCpp(arguments);
    @

    Or you could get relevant data in C++ code through meta object information (like parent(), findChildren(), setProperty(), getProperty()).



  • I didn't understand the connection between the empty QML Node objects and my instantiated objects in the model (in main.cpp)

    How to make the connection between them, how to load the custom created Node objects in main.cpp into the empty QML objects ?

    Do you have an example or something, pls ?

    Thanks a lot again


  • Moderators

    There is no connection. Model is just a model - a bag full of data that is given to the delegate. Node is instantiated in the Delegate, and it should get the data there - through "standard QML mechanisms":http://qt-project.org/doc/qt-4.8/qdeclarativemodels.html (by parameter name, or by model property).

    No, I don't have any example that is similar enough. I don't think I'm actually helping you that much, seems to me I'm just confusing. Sorry about that.



  • you are helping me, don't worry

    Whan I want is when the QML Node object is created, the Node::paint() function in C++ must be called and draw the line.

    But with debug tracing I found that I pass through the paint() function, but, the this pointer points to an empty C++ Node object.

    So I don't understand, why call the paint() function on empty objects and how to call the paint function on the Node objects, created in the main.cpp


  • Moderators

    My point, to put it short, is this: don't create nay node in main.cpp.

    Prepare Node c++ base class, and QML invocation so that the resulting meta object is fully configured and ready to roll.



  • So QML creates an empty Object of Node class with the no-parameters constructor, calls the paint() function and later it coipes somehow the linked properties from the model ?

    I need to create the Node instances in main.cpp and configure them dynamicly and get updated the QML view. This is idea of the application I am trying to write.


  • Moderators

    [quote author="Zaxy" date="1355317416"]So QML creates an empty Object of Node class with the no-parameters constructor, calls the paint() function and later it coipes somehow the linked properties from the model ?[/quote]

    Almost true. It instantiates the object through meta-object system. Then it assigns the properties you specify to the data read from the model, for every item in the model. Paint is called once everything is ready.

    As I've said, you could create your Nodes in main as you so much desire, but that is going to be much harder way. If I had to do it this way, I would create some null pointers in main.cpp, then, when Nodes report with Component.onCompleted, reassign those pointers to live QML objects. It's not that clean even on paper.



  • I have tried to call update() which should call paint() on Node's onCompleted with the idea that this will draw my line connection. Additionaly, I declared in the Model and Node.h Node.cpp the list _parents as a role, so that in the QML Object I should have that list too.

    @Node {
    id: nodeDelegate
    x: posX
    y: posY
    visible: isDisplayed

    Image{
        id : nodeIcon
        source: iconFilePath
    }
    
    Text {
       anchors.top: nodeIcon.bottom
       text: nodeID
    }
    
    MouseArea {
       anchors.fill: parent
    }
    
    Component.onCompleted: update();
    

    }@

    but still not working ...

    Maybe I could try to draw a line directly in QML getting info for target posX, posY from all nodes in QML property parentNodes, but don't know how to do it (the syntax)

    What do you think ?



  • So, I think that's the idea to do it:

    • declare additional role => parentNodes

    in Node.qml:

    • Component.onCompleted : { draw a line to each instance(its posX and posY) in parentNodes }

    So what I don't know is how to write it syntaxically...

    Do you have an idea ?



  • It should be something like this, but don't know exactly the syntax. Anyway the following example doesn't compile, but logically I want to do that:

    @
    Node {
    id: nodeDelegate
    x: posX
    y: posY
    visible: isDisplayed

    Image{
        id : nodeIcon
        source: iconFilePath
    }
    
    Text {
       anchors.top: nodeIcon.bottom
       text: nodeID
    }
    
    MouseArea {
       anchors.fill: parent
    }
    
    Component.onCompleted: {
        for (var i=0; i < parentNodes.count(); i++)
        {
            Path {
                startX: posX; startY: posY
                PathLine{x: parentNodes[i].posX ; y: parentNodes[i].posY}
            }
        }
    }
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.