Problem mit QGraphicItem

Alles rund um die Programmierung mit Qt
Antworten
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Problem mit QGraphicItem

Beitrag von slash-ex »

ich habe eine graphicview und eine scene abgeleitet. in die scene packe ich diese itemklasse.
nun habe ich aber 2 probleme.
1) trotz flag bewegt sich das item nicht. woran liegt das?
2) ich empfange keine mouse-(move)-events, das klappt lediglich beim graphicview, aber ich brauche die position der mouse im view oder der scene...

dann wollte ich noch gerne wissen, wie ich es am besten hinkriege folgende bewegungsfunktion zu implementieren, zum einen kriege ich ja leider keine mouse-events rein, sodass nicht gezeichnet wird^^ und zum andern besteht die frage, ob das bei jedem event upgedatet wird?!

Code: Alles auswählen

BFItem::BFItem(Model *mod, double *zoom_verhaeltnis) {
	setFlags(QGraphicsItem::ItemIsMovable);

	dModel = mod;
...

Code: Alles auswählen

void BFItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
	Q_UNUSED(widget);

	// Painter mit Zoll-Koordinatensystem
	painter->setRenderHint(QPainter::Antialiasing);
	painter->setRenderHint(QPainter::SmoothPixmapTransform);
	//! Painter automatisch so skalieren, dass man mit den "Zoll"werten malt.
	painter->scale(*pixels_per_inch, *pixels_per_inch);
	// Painter mit standard Pixel-Koordinatensystem
	QPainter *px_painter = new QPainter; 
	px_painter->setRenderHint(QPainter::Antialiasing);
	px_painter->setRenderHint(QPainter::SmoothPixmapTransform);	

	QPen pen;

	selected = dModel->selected();
	moving = dModel->moving();
	turning = dModel->turning();

	/*!
		Modelle zeichnen
	*/
	drawRangeCircles(*painter, *px_painter, pen);
	/*!
		Eiheiten zeichnen
	*/
	drawModel(*painter, pen, dModel->position() );
	/*!
		Modelle selektieren
	*/
	drawSelCircles(*painter, *px_painter, pen);
	/*!
		Reichweite anzeigen
	*/
	drawRangeCircles(*painter, *px_painter, pen);
	/*!
		Modelle drehen
	*/
	drawAngelGrid(*painter, *px_painter);

	/*!
		Bewegungsimplementation...
	*/
	std::cout<<"X,Y = "<<mousePos.x()<<"; "<<mousePos.y()<<std::endl;
	if(moving) {
		std::cout<<"MOVING"<<std::endl;

		QPointF vector = dModel->position() - mousePos/(*pixels_per_inch);
		double dist = sqrt ( pow(vector.x(), 2.0) + pow(vector.y(), 2.0) );

		if(dist <= dModel->owner()->movement() ) {
			drawModel(*painter, pen, mousePos/(*pixels_per_inch) );
			painter->drawLine(dModel->position(), mousePos/(*pixels_per_inch));
		}
	}
}
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Was soll der painter-Code? Was hat der mit deinem Problem des nichtbewegens zu tun?

Ich geh davon aus, daß du MouseEvents des Items überlädst. Rufst du die eigentlichen Event-Handler nochmal selbst auf?
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

naja, das flag habe ich nur zum test gesetzt. wenns fertig ist, soll es so sein, dass sich das model nur in einem bestimmten radius bewegen kann, dafür ist der painter-code. wenn ich die maus release, sollen die positionen der modelle auf die aktuell per maus angewählte stelle gesetzt werden.

(man muss sich das so vorstellen: ein model wird immer an bestimmter stelle gezeichnet, und wenn mans bewegen will wird ein transparentes neues modell mit ner verbindungslinie und ein transparenter kreis drumrum gezeichnet. beim loslassen der maus wird der kram wieder ausgeblendet und die position neu gesetzt)

die mouse-events habe ich überladen:

Code: Alles auswählen

void BFItem::mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
	mouseDown = event->pos();
// 	update();
}

void BFItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
	mouseUp = event->pos();
// 	update();
}

void BFItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{
	mousePos = event->pos();
// 	update();
}
ähnlich habe ich sie auch im graphic-view überladen, dort bekomme ich übrigens immer meine events. in der item-klasse wie gesagt nichts, außer beim klicken und da auch immer ein 0,0.

bis aufs überladen habe ich aber nix gemacht.

edit: bekomme auch beim press-event nix ):
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

außerdem bekomme ich bei meinem item-painter auch ständig das hier:
QPainter::setRenderHint: Painter must be active to set rendering hints

wie setze ich so einen painter active?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

rufst du die eigentlichen Event-Handler nochmal selbst auf?
The default implementation handles basic item interaction, such as selection and moving. If you want to keep the base implementation when reimplementing this function, call QGraphicsItem::mouseMoveEvent() in your reimplementation.
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

Code: Alles auswählen

void BFItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{
	std::cout<<"mouseMoveEvent = "<<event->pos().x()<<"; "<<event->pos().y()<<std::endl;
	mousePos = event->pos();
	update();
	QGraphicsItem::mouseMoveEvent(event);
}
es wird immer noch nix ausgegeben...

und eigentlich müssete man das item nach dem aufruf dieser flags doch bewegen können:
setFlags(ItemIsSelectable | ItemIsMovable);
setAcceptsHoverEvents(true);
setAcceptDrops(true);
jedenfalls dann wenn mouse-events empfangen werden können, aber das werden sie schon default nicht.
vielleicht muss ich ja im graphic-view machen oder in der scene klasse?!

frohes fest!
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Stell doch mal den gesamten Code als tgz-Datei zur Verfügung...
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

das ist echt viel...
aber ich werde mal den gesamten code zum zeichnen offenlegen. das prob war, dass ich erst ein widget mit einer paint-funktion überladen habe und das sau langsam wurde. dann hatte ein freund ein paar klassen zur verwaltung umgekrempelt und ich bin auf graphic-views umgestiegen...

in der board.h steht das reimplementierte view und eine scene abgeleitete klasse und in der item.h steht das graphicitem in dem der mal-kram reingepackt wurde.
ich hoffe du kommst nicht wegen "Model" und "Unit" beziehungen durcheinander, das sind lediglich container-klassen, aber das merkt man schnell...
Dateianhänge
Archiv.7z
(4.55 KiB) 164-mal heruntergeladen
Archiv.tar
(30 KiB) 156-mal heruntergeladen
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Also jetzt nochmal, und zwar zum letzten Mal:
If you want to keep the base implementation when reimplementing this function, call QGraphicsItem::mouseMoveEvent() in your reimplementation.
Das zählt für alle MouseEvents! Auch für die der View!
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

ich glaube ich mache irgendwas falsch... aber selbst ein:

Code: Alles auswählen

void Board::mouseMoveEvent(QMouseEvent *event) {
	mousePos = event->pos();

	QGraphicsView::mouseMoveEvent(event);
}
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ja, du liest nicht: alle
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

ich habe das bei allen gemacht, mir ist klar, dass das recht nervig sein muss wenn jemand nicht sofort weiß, wo man überall den eventhandler aufrufen muss. aber zumindest jetzt sollte das erfüllt sein. jedoch noch ohne fortschritte...
ich habe auch mal in der 40000 demo nachgeschaut, als du mir zu dem aufruf des eventhandlers geraten hattest. dort hatte man das lediglich bei einem mouse-move-event getan. darum habe ich das auch nur für diesem fall gepostet. allerdings habe ichs trotzdem bei allen nochmal probiert..
kurioserweise glaube ich, dass es bei mir schonmal funktioniert hatte, bevor ich meine board-klasse von graphic-view abgeleitet hatte. denn zuerst habe ich es wie in der demo von einer qframe abgeleitet. für meine zwecke ist das aber unbrauchbar.
Dateianhänge
Archiv.tar
(30 KiB) 128-mal heruntergeladen
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

Code: Alles auswählen

class Scene : public QGraphicsScene
{
private:

public:
	Scene(QSizeF rect = QSizeF(72 * 8, 48 * 8), QGraphicsScene *parent = 0) : QGraphicsScene(parent) {
		setSceneRect(0, 0, rect.width(), rect.height() );

		this->setBackgroundBrush(Qt::darkGreen);
	}

protected:
	void mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
		std::cout<<"X,Y = "<<event->pos().x()<<"; "<<event->pos().y()<<std::endl;
		QGraphicsScene::mouseMoveEvent(event);
	}
};
nachdem ich heilig abend überlebt habe, musste ich mal oberes ausprobieren und bekomme diesmal sogar eine ausgabe aber nur "0, 0" egal wo ich die maus hinbewege....

misteriös...
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Naja, das Event hätte ja noch ein paar andere Positionsangaben im Angebot...
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

hmm, ok. damit wäre dann schonmal sicher gestellt, dass das event-system bis zur scene durchkommt. aber ich verstehe immer noch nicht, warum mein item keine events liefert, irgendwas scheint noch zu fehlen. und theoretisch müsste es ja klappen, denn nachdem ich den std.-eventhandler aufrufe, klappts ja bis zur scene. und wenn die beispiele richtig sind, die man im assistant findet, müsste es auch bei mir klappen.
Antworten