Seite 1 von 1
[gelöst] Elastic Nodes
Verfasst: 7. September 2007 14:22
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.
Verfasst: 7. September 2007 14:27
von CaptnChaos
welche beiliegenden Dateien?
das nützt nichts wenn du die neben deinen Computer legst...
Verfasst: 7. September 2007 14:35
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);
}
Verfasst: 7. September 2007 14:37
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
Verfasst: 7. September 2007 14:52
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
Übrigens,
/* abs ^ */
printf("Nicht original\n");
/* abs v */
... bedeutet die Teile, die ich geändert habe.
Verfasst: 7. September 2007 14:59
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.
Verfasst: 7. September 2007 15:50
von einhorn
Code: Alles auswählen
void test()
{
printf("Ja, ich bin einverstanden. Ich mache das nächste mal. Danke schön!\n");
}
[gelöst] Elastic Nodes
Verfasst: 10. September 2007 15:12
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:
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!