Seite 1 von 1
[gelöst] QGraphicsItem nachträglich Farbe ändern
Verfasst: 19. Mai 2007 15:52
von Robzon
Hi Leute,
ich hab mir einer QGraphicsScene ein QGraphicsItem erstellt (über "drawEllipse") vorher habe ich die Farbe über "setBrush" eingestellt.
Nun möchte ich nachträglich die Farbe der Ellipse ändern. Geht das oder wäre es besser das alte Item zu löschen und ein neues mit einer anderen Farbe an der gleichen Stelle zu zeichnen?
Code: Alles auswählen
void MapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->setBrush(Qt::blue);
painter->drawEllipse(-5, -5, 20, 20);
}
So denke ich mir das (funzt aber net):
Code: Alles auswählen
void MapScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent){
QPointF currentOneClickPoint = mouseEvent->buttonDownScenePos(Qt::LeftButton); // Klickposition
QList<QGraphicsItem *> myList = items(); // Liste der Items erstellen
myList[0]->setColor(red);
// ODER
myList[0]->painter->setBrush(Qt::blue);
update(QRectF(-1000,-1000, 3000, 3000));
}
Verfasst: 19. Mai 2007 16:11
von franzf
Ich denke du musst dir als private-member deines GraphicsItem einen QBrush (bzw. eine QColor) speichern. QGraphicsItem hat auch ein mousePressEvent, dieses in deiner abgeleiteten Klasse überschreiben und eine neue Farbe setzen + updaten.
Evtl. vorher überprüfen, ob es wirklich aktuell ausgewählt ist (this->scene()->mouseGrabberItem() == this).
Hoffe das hat geholfen.
Grüße
Franz
Verfasst: 19. Mai 2007 16:44
von franzf
Hier mal ein kleines Beispiel:
myitem.h
Code: Alles auswählen
#ifndef _MYITEM_
#define _MYITEM_
#include <QGraphicsItem>
class MyItem : public QGraphicsItem
{
public:
MyItem( QGraphicsItem *parent = 0 ) : QGraphicsItem(parent)
{ setFlags( QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable ); }
void paint( QPainter *, const QStyleOptionGraphicsItem *option, QWidget *widget=0 );
QRectF boundingRect() const;
private:
QPointF pointForAngle( double, double );
};
#endif // _MYITEM_
myitem.cpp
Code: Alles auswählen
#include "myitem.h"
#include <QPainter>
#include <QBrush>
#include <QRectF>
#include <QGraphicsScene>
#include <QRadialGradient>
#include <cmath>
void MyItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
Q_UNUSED(option);
Q_UNUSED(widget);
QRadialGradient gradient( QPointF(0,0), 100, QPointF(0,0) );
if( this == scene()->mouseGrabberItem() ) {
gradient.setColorAt( 0.0, Qt::red );
gradient.setColorAt( 1.0, Qt::yellow );
} else {
gradient.setColorAt( 1.0, Qt::red );
gradient.setColorAt( 0.0, Qt::yellow );
}
painter->setBrush( gradient );
QPainterPath path;
int _spikes = 7;
double angle1 = 360.0 / (double)_spikes;
double angle2 = angle1 / 2.0;
double angle;
double rad1 = 100.0;
double rad2 = 70.0;
QPointF c1, c2, end;
end = pointForAngle( -90, rad1 );
path.moveTo( end );
for( int i=0; i<_spikes; i++ ) {
angle = i * angle1 - 90;
end = pointForAngle( angle + angle2, rad2 );
c1 = pointForAngle( angle + angle2/4, rad2 + 5.0 );
c2 = pointForAngle( angle + angle2 - angle2/4, rad1 - 5.0 );
path.cubicTo( c1, c2, end );
end = pointForAngle( angle + angle1, rad1 );
c1 = pointForAngle( angle + angle2 + angle2/4, rad1 - 5.0 );
c2 = pointForAngle( angle + angle1 - angle2/4, rad2 + 5.0 );
path.cubicTo( c1, c2, end );
}
painter->drawPath( path );
}
QRectF MyItem::boundingRect() const
{
return QRectF( -100, -100, 200, 200 );
}
QPointF MyItem::pointForAngle( double angle, double radius )
{
double radian = angle * 2 * M_PI / 360;
double x = cos( radian ) * radius;
double y = sin( radian ) * radius;
return QPointF( x, y );
}
main.cpp
Code: Alles auswählen
#include "myitem.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QApplication>
int main( int argc, char **argv )
{
QApplication app( argc, argv );
MyItem *item1 = new MyItem;
MyItem *item2 = new MyItem;
QGraphicsScene *scene = new QGraphicsScene;
scene->addItem( item1 );
scene->addItem( item2 );
QGraphicsView view;
view.setScene( scene );
view.setMinimumWidth( 500 );
view.setMinimumHeight( 500 );
view.show();
return app.exec();
}
Grüße
Franz
// edit:
Wie du siehst hab ich keinen QBrush & Co gespeichert, da ich aus deinem kleinen Code-Beispiel entnommen hab, dass du auf Maus-Klicks reagieren willst. Genau das hab ich jetzt gemacht. In anderen Fällen (ohne Maus-Klick, sondern von außen setzen) musst du dir aber schon die Farbe merken, da du nur in der paint()-Methode Zugriff auf den QPainter hast, mit dem gezeichnet wird, und du ja diesem deinen Brush zuweisen musst.
Verfasst: 19. Mai 2007 17:33
von Robzon
dankeschön ich probier es heut abend mal aus und meld mich dann nochmal ob ich es hinbekommen hab
EDIT:
hab dein Beispiel direkt mal umgesetzt. Hat super funktioniert - DANKE! Hübsche Items hast du gezeichnet

. Beim Einbinden steh ich noch vor ein paar Problemchen: Mein Projekt benutzt einen GraphicsView aus dem QT-designer - dort wird eine Scene eingebunden und in die wiederum ein Item. Im Header für das Item hab ich jetzt auch die Flags "ItemIsMovable" und "ItemIsSelectable" gesetzt. Dies wird zwar problemlos kompiliert aber im Programm gibts keine Reaktion. Die Scene und das Item haben jeweils ihre eigene CPP und Header Datei. Ich vermute also das es mit dem Verlinken zwischen den Files noch nicht ganz hin haut...
Verfasst: 21. Mai 2007 11:14
von Robzon
jetzt freu ich mich

Hab das Problem gefunden: ich habe bereits die Funktion MousePressEvent überschrieben -> dadurch reagierte QT nicht mehr auf das Drag des Items.
noch mal ganz großes Dankeschön!
Ein ähnliches Problem
Verfasst: 26. November 2009 14:35
von seishin_
Hallo!
Ich möchte das bereits gelöste Problem nochmal aufgreifen, da ich das gleiche Problem habe. Allerdings mit einem "kleinen" Unterschied.
Ich habe mir eine Klasse erstellt, die die Eigenschaften von QGraphicsItem erbt, um ein Item anzulegen. Allerdings habe ich in der paint-Funktion nicht nur ein Item gezeichnet, sondern ein ganzes Rudel. Ich programmiere nämlich ein Knobelspiel, dass aus einem n*n Feld besteht und in quadratische Segmente aufgeteilt ist. Diese habe ich in der Funktion einzeln gezeichnet mit drawRect(...). Ich möchte auch die einzelnen Quadrate optisch per Mausklick ändern, d.h. jeweils für die linke und rechte Maustaste. Gibt es die Möglichkeit? update(...) fiel mir ein, aber irgendwie werd ich nicht draus schlau. In der Doc steht zwar, man kann damit auch das Erscheinungsbild ändern, aber wie? Ich geh davon aus, das man eine x,y-Position anwählt, sowie Breite & Höhe angibt, und das neu gezeichnet wird. Oder bezieht sich die Funktion nur auf das SceneRect (welches bei mir sozusagen das ganze Spielfeld umfasst, in der die sich die Quadrate befinden)?
Ich hoffe sowas geht, sonst brauch ich bei 15x15 Feldern entweder 225 QGraphicsItem Objekte oder ich überschreib jedesmal das eine Objekt mit Parametern.
Ich muss dazu sagen, dass ich mir Qt selbst beibringe, nur mit den Tutorials, Beispielen. Und ich neige dazu zu kompliziert an die Sache zu gehen. Handelt es sich um ein triviales Problem, so nehmts mir bitte nicht übel.
Also Ziel ist es, per Links- und Rechtsklick unterschiedlich die Farbe der Quadrate im Item selbst zu ändern.
Vielen Dank im Vorraus!
Grüße,
seishin_
Verfasst: 26. November 2009 19:01
von upsala
225 Objekte sind gar nichts.
update() löst ein repaint() aus, ist also nach einem Farbwechsel zu empfehlen.
Verfasst: 27. November 2009 21:09
von seishin_
Danke für den Tipp, hatte das ganze Konzept etwas falsch verstanden. Habe einfach die mousePressEvent-Methode reimplementiert, dann gehts genauso, und ich spar mir sehr viel Schreibarbeit.
Allerdings kostet mich ein kleiner Bug noch den letzten Nerv. Ich merke mir vor dem update(...)-Auruf die Position, wo das MouseEvent stattfand. und beim neu zeichnen wird an dieser Position eine andere Farbe für den painter benutzt. Das funktioniert auch soweit, nur ab dem 2. Klick bekomme ich jedesmal das letzte Element eingefärbt statt das aktuell betätigte. Ich habe jetzt mehrere Stunden versucht, der Sache auf den Grund zu gehen, aber ich komme nicht drauf. Ich tippe auf einen Logik-Fehler. Ich gehe halt davon aus, das update(...) das im boundingRect() definierte Rechteck neu zeichnet, und damit paint(...) wieder aufruft. Warum ich dann jedesmal die alte Position dort bekomme, ist mir absolut schleierhaft.
Code: Alles auswählen
void GameWindow::mousePressEvent(QGraphicsSceneMouseEvent* event) {
if (event->button() == Qt::LeftButton) {
// weiterer Code, mitunter wird die QPointF-Position global gespeichert
update(boundingRect());
}
}
In paint(...) wird jetzt an der erkannten Stelle einfach ne andere Farbe eingesetzt. Vielleicht kann mir jemand auf die Sprünge helfen. Ich probier erstmal weiter. :/