PDA

View Full Version : Problem with paint()



Zaxy
12th December 2012, 11:15
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 !

wysota
12th December 2012, 11:24
My impression is that you are trying to draw outside the bounding rect defined by your Node class. As for you main(), I don't know, I haven't seen the code.

Zaxy
12th December 2012, 11:32
Here the code of main.cpp



Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));

QDeclarativeView declarativeView;
qmlRegisterType<Node>("NodeLib", 1, 0, "Node");

ConfigurationModel* p_configModel = ConfigurationModel::GetConfigModelInstance();

p_configModel->addNodeInConfigurationModel(new Node("PanelXXXX", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png"));

Node *p_nodeY = new Node("PanelYYYY", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png");
p_configModel->addNodeInConfigurationModel(p_nodeY);

Node *p_nodeZ = new Node("PanelZZZZ", PLUG_IN, EVALUATION_BLOCK, "./ui-images/cutetube.png");
p_nodeZ->setNodeID("NODE ZZZZ");

p_nodeY->setPosX(100);
p_nodeY->setPosY(100);
p_nodeY->setIsDisplayed(true);

p_nodeZ->setPosX(200);
p_nodeZ->setPosY(200);

p_nodeZ->connectTo(p_nodeY);

p_configModel->addNodeInConfigurationModel(p_nodeZ);

// if the configuration has been changed, you need to call setContextProperty() again to update the QML view

declarativeView.rootContext()->setContextProperty("configModel", p_configModel);

declarativeView.setSource(QUrl::fromLocalFile("qml/ConfigurationView/main.qml"));
declarativeView.show();

return app->exec();
}

wysota
12th December 2012, 11:49
So why would anything point to any of the Node instances you created in main? You're creating a new node instance in your QML file.

Zaxy
12th December 2012, 12:03
Could you please give me some simple example how to fix the issue ?

Added after 4 minutes:

What I thought and wanted is
- create Node instances in main.cpp into the Model
- display these created instances in the QML
- call the paint function of each Node instance

wysota
12th December 2012, 12:08
This doesn't sound like regular QML usage. If you create and expose a set of Node instances in main, then in QML you only use Javascript to manipulate the objects already there, you don't create new ones.

Zaxy
12th December 2012, 13:11
The problem is, when I traced the code, I call the Node:: paint() function, but on an empty Node object.

Actually, I should call the paint() function of the already created Node objects instanciated in the main.cpp

I don't understand why I call it on an empty Node object.

Could you please advise something ?

wysota
12th December 2012, 13:35
I already told you. In your QML file you declare a "Node" element. That's none of the Node instances you create in main. Your Node instances created in main() are silently ignored by QML because they have no geometry and no relation to the items being painted. You can rem out all your main() code related to creating and setting up Node instances and it will not change the behaviour of your QML scene in any way. I understand you'd like each Node created in main() to have a text, icon and all the other stuff you declared in QML but that's not how it works.

Your repeater declaration effectively creates empty nodes unrelated to any data.

Zaxy
12th December 2012, 13:50
Ok, but I got the Node instances properties like iconFilePath and nodeID displayed in QML. Just the paint function is not working.
Otherwise, I got the properties from the model ...

So at some point QML copies these values, but don't call the proper paint fucntion ...

wysota
12th December 2012, 21:10
I don't understand what you mean by "proper" paint function. There is only one paint() method in Node.

Zaxy
13th December 2012, 13:54
Yes, there is only one paint() function in Node.

The problem is that QML creates an object avec le default constructor of type Node. Than it calls its paint function.

But this object hasn't its properties set, like e.g. _parentNodes list et donc my paint function is not working, because I want to draw a line between the current node and any parent node in _parents list.

I thought maybe I could solve the problem by exposing _parents to QML and than draw the lines in the Component.onCompleted() function.
But I don't know the right syntax for that.

I have one question, when you call update() from C++ Qt, is after that the onCompleted() also called ?

Here a proposal for the body of onCompleted, but it doesnt compile, I dont know the right syntax.
Could you please advise me on that issue ?



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
}

Component.onCompleted: {
for (var i=0; i < parentNodes.count; i++)
{
Path: [
// startX: posX,
// startY: posY,
PathLine {
x: parentNodes.get(i).posX
y: parentNodes[i].posY
}
]
}
}
}



Thanks in advance

wysota
13th December 2012, 17:57
The problem is that QML creates an object avec le default constructor of type Node. Than it calls its paint function.

But this object hasn't its properties set, like e.g. _parentNodes list et donc my paint function is not working, because I want to draw a line between the current node and any parent node in _parents list.
Yes, and I already told you why this happens. The nodes QML creates have nothing to do with nodes you create in C++. They are separate entities.


I have one question, when you call update() from C++ Qt, is after that the onCompleted() also called ?
No, onCompleted is called once when the item definition it belongs to is parsed and constructed.


Here a proposal for the body of onCompleted, but it doesnt compile, I dont know the right syntax.
It doesn't compile because you can't mix JavaScript code and QML declarations.


Could you please advise me on that issue ?
Tell me why you want to use QML here at all.

Zaxy
14th December 2012, 11:29
I have to do this graph visualization:
- nodes displayed with some info and an icon
- connections between some nodes are displayed as graphical lines
- onClick on a node, you can do some stuff, like rename the node, hide it, show it etc

So either I do it entirely in C++/Qt or I do it in C++/QML.

I thought, that with QML will be easier to do it and better displayed.

I am doing a feasability study of both approeaches. But maybe it is not so easy to do it in C++ / QML ?

What do you think about that. Is it feasible with QML and would be easier to do it ?

Thanks again

wysota
14th December 2012, 11:38
If you don't feel comfortable with QML and QtQuick and you don't need any fancy animations then I'd advise you to use QGraphicsView instead. It will feel much more natural.

Zaxy
14th December 2012, 12:04
Ok, and do you think that graph visualization is feasible in QML ?

I don´t really need fancy animation, just an .png file representing the node, and some lines connecting the nodes. The rest should be simple text labels.

wysota
14th December 2012, 12:08
Ok, and do you think that graph visualization is feasible in QML ?
Yes, of course. Inpired by this thread I even implemented a small library for declaring edges in QtQuick 2.0 two days ago.


I don´t really need fancy animation, just an .png file representing the node, and some lines connecting the nodes. The rest should be simple text labels.
QGraphicsPixmapItem, QGraphicsTextItem and QGraphicsLineItem should be perfect for you.