[gelöst] Elastic Nodes

Alles rund um die Programmierung mit Qt
Antworten
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

[gelöst] Elastic Nodes

Beitrag von einhorn »

Ich ändere Trolltech-Beispiel "Elastic Nodes", um eine Simulation zu erstellen:

Elastic Nodes Example
http://doc.trolltech.com/4.2/graphicsvi ... nodes.html

Jetzt versuche ich einen Knoten am Punkt hinzuzufügen, exakt wo der Mauszeiger sich befindet.
Aber ein neuer Knoten wird immer an der unteren-rechten Ecke hinzugefügt,
egal an welcher Position sich der Mauszeiger befindet (besonders wenn das Fenster an der unteren-rechten Ecke liegt).
Also ziehe ich einige Offsets ab (800 von der x-Achse beziehungsweise 600 von der y-Achse),
aber es funktioniert nur wenn sich das Fenster im Vollbildmodus befindet.

Was kann man an meine Code verbessern?

Ich habe nur "graphwidget.h" und "graphwidget.cpp" geändert,
und alle andere Dateien sind unberührt.
Bitte siehe die beiliegende Dateien.

Umwelt:
Qt4.2
Kubuntu 6.10

Jeder Vorschlag ist willkommen.
Zuletzt geändert von einhorn am 10. September 2007 15:14, insgesamt 1-mal geändert.
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

welche beiliegenden Dateien?
das nützt nichts wenn du die neben deinen Computer legst...
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

Beitrag von einhorn »

Schade ...
Upload Error: Kann das Attachment ./files/elasticnodestar_117.gz nicht hochladen.

Hier ist die quellcode:

// graphwidget.cpp
#include "graphwidget.h"
#include "edge.h"
#include "node.h"

#include <QDebug>
#include <QGraphicsScene>
#include <QWheelEvent>

#include <math.h>

/* abs ^ */
#include <QContextMenuEvent>
#include <QMenu>

#include <iostream>
using namespace std;
/* abs v */

GraphWidget::GraphWidget()
: timerId(0)
{
QGraphicsScene *scene = new QGraphicsScene(this);
/* abs ^ */
_scene = scene;
/* abs v */
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->setSceneRect(-200, -200, 400, 400);
setScene(scene);
setCacheMode(CacheBackground);
setRenderHint(QPainter::Antialiasing);
setTransformationAnchor(AnchorUnderMouse);
setResizeAnchor(AnchorViewCenter);

Node *node2 = new Node(this);
Node *node4 = new Node(this);
centerNode = new Node(this);
Node *node6 = new Node(this);
Node *node8 = new Node(this);
scene->addItem(node2);
scene->addItem(node4);
scene->addItem(centerNode);
scene->addItem(node6);
scene->addItem(node8);
scene->addItem(new Edge(node2, centerNode));
scene->addItem(new Edge(node4, centerNode));
scene->addItem(new Edge(centerNode, node6));
scene->addItem(new Edge(centerNode, node8));

node2->setPos(0, -50);
node4->setPos(-50, 0);
centerNode->setPos(0, 0);
node6->setPos(50, 0);
node8->setPos(0, 50);

/* abs ^ */
// initialization
numNode = 0;
nodeX = new QVector<Node*>();

for(int i=0; i<numNode; i++)
{
nodeX->append( new Node( this ) );

scene->addItem( nodeX->at(i) );
scene->addItem(new Edge(centerNode, nodeX->at(i)));

nodeX->at(i)->setPos(50+(i*2), 50+(i*2));
}
/* abs ^ */

// scale(0.8, 0.8);
scale(1.0, 1.0);
setMinimumSize(400, 400);
setWindowTitle(tr("Elastic Nodes"));
}

/* abs ^ */
QGraphicsScene *GraphWidget::scene()
{
return _scene;
} // scene()

void GraphWidget::contextMenuEvent( QContextMenuEvent *ev )
{
if ( itemAt( ev->pos() ) )
{
QGraphicsView::contextMenuEvent( ev );
}
else
{
QMenu contextMenu;

QAction *addNodeAction = contextMenu.addAction( QObject::tr( "Add Node" ) );
connect( addNodeAction, SIGNAL( triggered() ), this, SLOT( addNode() ) );

contextMenu.exec( ev->globalPos() );
}
}; // contextMenuEvent( QContextMenuEvent* )

void GraphWidget::addNode()
{
int i=0; // this is just a temporal value
nodeX = new QVector<Node*>();

nodeX->append( new Node( this ) );

scene()->addItem( nodeX->at(i) );
// scene()->addItem(new Edge(centerNode, nodeX->at(i)));

// nodeX->at(i)->setPos(50+(i*2), 50+(i*2));
// nodeX->at(i)->setPos( mapFromGlobal (QCursor::pos() ) );
// nodeX->at(i)->setPos( (QCursor::pos()).x(), (QCursor::pos()).y() );
nodeX->at(i)->setPos( (QCursor::pos()).x()-800, (QCursor::pos()).y()-600 );
} // addNode()

void GraphWidget::mousePressEvent( QMouseEvent * ev )
{

if ( ev->modifiers() & Qt::ControlModifier )
{
setDragMode( QGraphicsView::RubberBandDrag );
}

QGraphicsView::mousePressEvent( ev );

}; // mousePressEvent( QMouseEvent* )

void GraphWidget::mouseReleaseEvent( QMouseEvent * ev )
{

QGraphicsView::mouseReleaseEvent( ev );

setDragMode( QGraphicsView::ScrollHandDrag );

}; // mouseReleaseEvent( QMouseEvent* )
/* abs v */

void GraphWidget::itemMoved()
{
if (!timerId)
timerId = startTimer(1000 / 25);
}

void GraphWidget::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
centerNode->moveBy(0, -20);
break;
case Qt::Key_Down:
centerNode->moveBy(0, 20);
break;
case Qt::Key_Left:
centerNode->moveBy(-20, 0);
break;
case Qt::Key_Right:
centerNode->moveBy(20, 0);
break;
case Qt::Key_Plus:
scaleView(1.2);
break;
case Qt::Key_Minus:
scaleView(1 / 1.2);
break;
case Qt::Key_Space:
case Qt::Key_Enter:
foreach (QGraphicsItem *item, scene()->items()) {
if (qgraphicsitem_cast<Node *>(item))
item->setPos(-150 + qrand() % 300, -150 + qrand() % 300);
}
break;
default:
QGraphicsView::keyPressEvent(event);
}
}

void GraphWidget::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);

QList<Node *> nodes;
foreach (QGraphicsItem *item, scene()->items()) {
if (Node *node = qgraphicsitem_cast<Node *>(item))
nodes << node;
}

foreach (Node *node, nodes)
node->calculateForces();

bool itemsMoved = false;
foreach (Node *node, nodes) {
if (node->advance())
itemsMoved = true;
}

if (!itemsMoved) {
killTimer(timerId);
timerId = 0;
}
}

void GraphWidget::wheelEvent(QWheelEvent *event)
{
scaleView(pow((double)2, -event->delta() / 240.0));
}

void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(rect);

// Shadow
QRectF sceneRect = this->sceneRect();
QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
if (rightShadow.intersects(rect) || rightShadow.contains(rect))
painter->fillRect(rightShadow, Qt::darkGray);
if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
painter->fillRect(bottomShadow, Qt::darkGray);

// Fill
QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::lightGray);
painter->fillRect(rect.intersect(sceneRect), gradient);
painter->setBrush(Qt::NoBrush);
painter->drawRect(sceneRect);

// Text
QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
sceneRect.width() - 4, sceneRect.height() - 4);
QString message(tr("Click and drag the nodes around, and zoom with the mouse "
"wheel or the '+' and '-' keys"));

QFont font = painter->font();
font.setBold(true);
font.setPointSize(14);
painter->setFont(font);
painter->setPen(Qt::lightGray);
painter->drawText(textRect.translated(2, 2), message);
painter->setPen(Qt::black);
painter->drawText(textRect, message);
}

void GraphWidget::scaleView(qreal scaleFactor)
{
qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;

scale(scaleFactor, scaleFactor);
}
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

Beitrag von einhorn »

Hier ist die andere Quellcode:

// graphwidget.h
#ifndef GRAPHWIDGET_H
#define GRAPHWIDGET_H

#include <QtGui/QGraphicsView>

/* abs ^ */
#include <QVector>
/* abs v */

class Node;

/* abs ^ */
class QContextMenuEvent;
/* abs v */

class GraphWidget : public QGraphicsView
{
Q_OBJECT

public:
GraphWidget();

void itemMoved();

/* abs ^ */
void contextMenuEvent( QContextMenuEvent *ev );
void mouseReleaseEvent( QMouseEvent * ev );
void mousePressEvent( QMouseEvent * ev );

QGraphicsScene *scene();
public slots:
void addNode();
// void addNode( QContextMenuEvent *ev );
/* abs v */
protected:
void keyPressEvent(QKeyEvent *event);
void timerEvent(QTimerEvent *event);
void wheelEvent(QWheelEvent *event);
void drawBackground(QPainter *painter, const QRectF &rect);

void scaleView(qreal scaleFactor);

private:
int timerId;
Node *centerNode;
/* abs ^ */
int numNode;
QVector<Node*> *nodeX;

QGraphicsScene *_scene;
/* abs v */
};

#endif
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

Beitrag von einhorn »

>KernelPanic

Danke schön für Deine schnelle Antwort und es tut mir leid.

>das nützt nichts wenn du die neben deinen Computer legst...

lustig :D

Übrigens,

/* abs ^ */
printf("Nicht original\n");
/* abs v */

... bedeutet die Teile, die ich geändert habe.
CaptnChaos
Beiträge: 605
Registriert: 28. Juni 2007 15:01
Kontaktdaten:

Beitrag von CaptnChaos »

HNGH!
menno... ich will ja net wieder motzen, aber das nächste mal setzt du quellcode in die eigens dafür entwickelte umgebung, ok?

ich schau mir das mal an übers wochenende, vllt kann ich heut abend auch schon was dazu sagen.
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

Beitrag von einhorn »

Code: Alles auswählen

void test()
{
	printf("Ja, ich bin einverstanden. Ich mache das nächste mal. Danke schön!\n");
}
einhorn
Beiträge: 31
Registriert: 4. April 2007 15:15

[gelöst] Elastic Nodes

Beitrag von einhorn »

KernelPanic hat mir die Lösung geschickt
und sie funktioniert perfekt!

Im Fall jemand das gleiche Problem hat,
füge ich hier ein, was er an meine Code verbessert hat.

In graphwidget.h:

Code: Alles auswählen

private:
	QPoint addNodePoint; //rechtsklickposition
In graphwidget.cpp:

Code: Alles auswählen

void GraphWidget::contextMenuEvent( QContextMenuEvent *ev )
{
	if ( itemAt( ev->pos() ) )
	{
		QGraphicsView::contextMenuEvent( ev );
	}
	else
	{
		QMenu contextMenu;
		
		QAction *addNodeAction = contextMenu.addAction( QObject::tr( "Add Node" ) );
		connect( addNodeAction, SIGNAL( triggered() ), this, SLOT( addNode() ) );
		addNodePoint = ev->pos();
		contextMenu.exec( ev->globalPos() );
	}
}; // contextMenuEvent( QContextMenuEvent* )

void GraphWidget::addNode()
{
	int i=0; // this is just a temporal value
	nodeX = new QVector<Node*>();
	nodeX->append( new Node( this ) );
	scene()->addItem( nodeX->at(i) );
	nodeX->at(i)->setPos( mapToScene (addNodePoint) );
} // addNode()
Vielen Dank, KernelPanic!
Antworten