Need some advice: how to draw a line between two objects.
-
Ok thank you, I already thought about that, but it seamed to me a bit "too much" for just drawing a line ^^. But I think that is what I will do (I have already done that for the two "rectangles" that I want to attach, which are no rectangles in fact)
In that case, my class Line should be something like this?:
@
class A : public QDeclarativeItem{ /plenty of code/ };class Line : public QDeclarativeItem{
private:
A* _attachPoint1;
A* _attachPoint2;
public:
Line(A* pt1 = NULL, A* pt2 = NULL);
public slots:
void attachTo(A* pt1, A* pt2);
void changePosition(A* newPosition);
};
@and then I have to connect:
@
connect(_attachPoint1,signal(onPositionChanged(A*)),this,SLOT(changePosition(A*)))void changePosition(A* newPosition){
//Then I change my Line object properties thanks to the coordenates from the passed A object.
}
@But there is no onPositionChanged signal in my class A ... How can I code it?
The position of my A objects changes when it is dragged (setting drag.target in a MouseArea into my object in QML), so, how can connect the fact of being dragged to my Line object?
@
A {
id: myObject
color: "red"
width: 100
height: 100
MouseArea{
id: ma;
anchors.fill : parent;
drag.target: myObject
}
}
@
I mean, when I drag it, the x and y properties of the object change, but how can I catch that changing?thank you again!
-
[quote author="excalibur1491" date="1357123707"]
But there is no onPositionChanged signal in my class A … How can I code it?
The position of my A objects changes when it is dragged (setting drag.target in a MouseArea into my object in QML), so, how can connect the fact of being dragged to my Line object?
[/quote]If I understand you correctly you want to catch when your component is moving, right? If so, you may connect two signals to your slots, for example:
@
connect(item, SIGNAL(xChanged()), SLOT(onXChanged()));
connect(item, SIGNAL(yChanged()), SLOT(onYChanged()));
@In both methods which you set as slot you may get a sender objects and get his X and Y positions. The code for that may looks like:
@void QmlApplicationViewer::onXChanged()
{
QDeclarativeItem* item = sender();if(item != NULL) { qDebug()<<"x: "<<item->x(); }
}
void QmlApplicationViewer::onYChanged()
{
QDeclarativeItem* item = sender();if(item != NULL) { qDebug()<<"y: "<<item->y(); }
}
@I hope this will help you.
-
Hi!
Thanks you a lot! I didn't knew about "sender()" and that "connect".
Ok, so I see more or less how to do the Line object and the two slots.
But I dont really see how to emit those signals because when my object is moved, I'm not even sure that the object itself notices since it's moved with a drag in a MouseArea inside the object. So the object won't emit those signals.
The big difficulty I have is how to emit those signals.
The only way I see is:
@
A{
id: a
MouseArea{
drag.target: a
onPositionChanged:{
if (drag.active){
emit a.onXChanged()
emit a.onYChanged()
}
}
}
}
@Is that ven possible?
There must be a better way to do it, isn't it?Thank you again, you're all being of big help :)
-
The signals xChanged() and yChanged() is a standard signals for QDeclarativeItem objects. So, If your component is a subclass from QDeclarativeItem you can use it like:
@
A{
id: aonXChanged: {
//Some code here
}
onYChanged: {
//Some code here
}
}
@If you need to get information about new position inside QML object. If you need get this information in C++ class which you want to use this signals, you can connect to the signal to some slot insdie you C++ class.
If you want to send a some signal you may use something like this:
@
//<id_of_component>.<signal_name>(<list_of_parameters>);
a.onXChanged(a.x);
@By the way, when you try to set a new position for object with id like 'a' the signal 'onXChanged' will called automatically for current object. So you don't needed call this signal manually.
-
Thank you a lot!
I didn't knew those signals were standard. When I read the documntation of QDeclarativeItem I was looking for somethink like "onPoistionChanged" and I forgot that signals don't appear in the methods list. My bad.Any way, thank you a lot to all of you. I will try to do that then.
-
[quote author="Jens" date="1357046647"]... Note that this works through rasterization so you will loose hardware acceleration and might have significantly higher memory requirements as a tradeoff. [/quote]
Doesn't this use OpenGL accelerated QPainter, which IIRC draws paths by triangulating and drawing hardware accelerated geometry?
On a side note, I myself have done a "mindmap network" style of app and think it will be significantly easier to implement with the trusty old QGraphicsView/Item/scene stack than with QML. Performance was pretty good too.
-
Hi again, I have started coding and it works mor or less, but I have a problem that I don't undestand at all:
I have a line between two rectangles, and when I move them the line moves. The problem is that when I move one of them, the line moves properly, but when I move the other the line becomes "dashed", and ugly... it does not move properlly, and I don't get why since it only happens on one side.Here is the code:
here is the base qml, nothing special abut it:
@
import QtQuick 1.0Rectangle{
color: "white"
width: 500
height: 500Rectangle{
objectName: "rec1"
id: rec1
x: 10
y: 10
width: 100
height: 100
radius: 50;
color: "red"
MouseArea{
id:marec1
anchors.fill: parent
drag.target: rec1
}
}Rectangle{
objectName: "rec2"
id: rec2
x: 200
y: 200
width: 100
height: 100
radius: 50;
color: "blue"MouseArea{ id:marec2 anchors.fill: parent drag.target: rec2 }
}
}
@Now, the Line class:
@#include <QDeclarativeItem>
#include <QPainter>
#include <QPen>
#include <QColor>class Line: public QDeclarativeItem{
Q_OBJECT
private:
QDeclarativeItem* pt1;
QDeclarativeItem* pt2;public:
Line(QDeclarativeItem* pt1 = NULL, QDeclarativeItem* pt2 = NULL);public slots:
void attachPt1(QDeclarativeItem* pt1);
void attachPt2(QDeclarativeItem* pt2);
void paint(QPainter* p, const QStyleOptionGraphicsItem* o = NULL, QWidget* w= NULL);
void _update(); //The aim of this slot is that update() is not a slot, so it only calls update().
};
@The implementation:
@
#include "Line.h"
#include <QTextStream>
#include <QIODevice>Line::Line(QDeclarativeItem* pt1, QDeclarativeItem* pt2):QDeclarativeItem(NULL),pt1(pt1),pt2(pt2){
setFlag(QGraphicsItem::ItemHasNoContents, false);
}void Line::attachPt1(QDeclarativeItem* pt1){
this->pt1 = pt1;
update();
QObject::connect(pt1,SIGNAL(xChanged()),this,SLOT(_update()));
QObject::connect(pt1,SIGNAL(yChanged()),this,SLOT(_update()));
}
void Line::attachPt2(QDeclarativeItem* pt2){
this->pt2 = pt2;
update();
QObject::connect(pt2,SIGNAL(xChanged()),this,SLOT(_update()));
QObject::connect(pt2,SIGNAL(yChanged()),this,SLOT(_update()));
}
void Line::_update(){update();}void Line::paint(QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w){
QTextStream ts (stderr,QIODevice::WriteOnly);
ts << "paint " << pt1<< " " << pt2 << " " <<sender()<< endl;
QPen pen(QColor("red"),2);
p->setPen(pen);
QLine line(pt1->x()+pt1->width()/2,
pt1->y()+pt1->height()/2,
pt2->x()+pt2->width()/2,
pt2->y()+pt2->height()/2);
p->drawLine(line);}
@
When the two extremities are set, the connection is done.
The drawing function only uses a QLine, nothing special about it.Last, the main:
@
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
#include <QDeclarativeItem>
#include <QDeclarativeView>
#include <QString>
#include <QTextStream>
#include <QIODevice>#include "Line.h"
int main(int argc, char* argv[]){
QApplication app(argc, argv);
QTextStream ts(stderr,QIODevice::WriteOnly);qmlRegisterType<Line>("LinesTest", 1,0, "Line");
QDeclarativeView* view = new QDeclarativeView;
view->setSource(QUrl::fromLocalFile("Base.qml";);QDeclarativeEngine* e = view->engine();
QDeclarativeComponent c (e,QUrl("example.qml"));
Line *l = qobject_cast<Line *>(c.create());qWarning() << c.errors();
QDeclarativeItem* r1 = view->rootObject()->findChild<QDeclarativeItem*>("rec1");
QDeclarativeItem* r2 = view->rootObject()->findChild<QDeclarativeItem*>("rec2");l->attachPt1(r1);
l->attachPt2(r2);l->setParentItem(qobject_cast<QDeclarativeItem*>(view->rootObject()));
view->show();return app.exec();
}
@
The example.qml file does not contain anythin special, just this:
@
import LinesTest 1.0
import QtQuick 1.0Line{
smooth: true
//color: "red";
}
@There is nt big code, but I really dont see where the bug comes from. It is the first time I use a QLine class, I hope it is OK.
Thank you again!
-
Any idea, please?
thanks again
-
I didn't review your code at detail but lately I've been doing the same as you (a graph editor) and, while in my case I wanted to find a pure QML+JavaScript solution with Qt 5, I found a Line component example from Nokia, implemented in Qt 4. Maybe you should follow their code:
http://www.developer.nokia.com/Community/Wiki/Creating_a_custom_QML_element_with_Qt -
For taking advantage of the scenegrapgh, you might want to look at this example, which pretty much implements a geometry node for a bezier curve:
http://doc-snapshot.qt-project.org/5.0/qtqml/quick-scenegraph-customgeometry.html
-
Hi, I have already ued this example: http://www.developer.nokia.com/Community/Wiki/Creating_a_custom_QML_element_with_Qt
and it works great.
I thought about the Beziers curve, but I need to have a mousearea covering the line so it would be way more dificult.
Any way, thank you all