Qt MouseMoveEvent auf QLabel

Alles rund um die Programmierung mit Qt
Antworten
undertone
Beiträge: 8
Registriert: 26. März 2010 12:32

Qt MouseMoveEvent auf QLabel

Beitrag von undertone »

Hallo,
ich beschäftige mich erst seit kurzem mit Qt und passe gerade den Beispielcode des ImageViewers meinen Bedürfnissen an. Ich konnte aber bisher nichts zu meiner Frage finden: Ich würde gerne bei einem Bild (Dargestellt als Pixmap auf QLabel) die Maus Position und später auch den Grauwert des Bildes an dieser Position in der Statusbar anzeigen lassen. Ich bekomme es hin, dass ich bei gedrückter Maus und dem MouseMoveEvent Koordinaten angezeigt bekomme. Leider gehören diese nicht zum Label, sondern sind die Koordinaten des Fensters.

Code: Alles auswählen

void ImageViewer::mouseMoveEvent( QMouseEvent* event){
  int xpos = (event->pos()).x();
  int ypos = (event->pos()).y();
  cout << xpos << "   " << ypos << endl;
  QString qstr;
  qstr.sprintf(" W:%d,%d / G:%d,%d ", event->pos().x(), event->pos().y(), event->globalPos().x(), event->globalPos().y());
  statusBar()->showMessage(qstr);
  //Wie bekommt man die Maus Position des Labels???
  }
Kann mir jemand weiterhelfen?
GSoft
Beiträge: 24
Registriert: 30. Dezember 2008 01:16
Wohnort: NRW

Beitrag von GSoft »

Im Moment hast du das mouseMoveEvent des ImageViewers überschrieben, deswegen werden dir auch die Koordinaten des Fensters angezeigt.

Du musst eine Klasse von QLabel ableiten und darin das mouseMoveEvent() überschreiben, da bekommst du die Koordinaten auch vom Label :D

Hoffe das hilft :D

Gruß
GSoft
Lerne aus den Fehlern Anderer! Du hast nicht die Zeit sie selbst zu machen.
undertone
Beiträge: 8
Registriert: 26. März 2010 12:32

Beitrag von undertone »

Oh das ging aber schnell!
Ich glaube ich verstehe, was mit einer Klasse von QLabel ableiten gemeint ist, aber für mich Anfänger wäre eine etwas ausführlichere Anleitung super...
GSoft
Beiträge: 24
Registriert: 30. Dezember 2008 01:16
Wohnort: NRW

Beitrag von GSoft »

Also ich versuche es einmal :D

Wenn du die Koordinaten der Maus innerhalb deines Labels haben möchtest, muss auch das Label dir die Position der Maus (über sich selber) mitteilen.

Um dies am besten zu machen, solltest du von QLabel ableiten und die Methode mouseMoveEvent() überschreiben.

Deine Label.h-Datei

Code: Alles auswählen

class MyLabel: public QLabel
{
   Q_OBJECT

signals:
   void posChanged(QPoint &pos);

public:
   MyLabel(QWidget * parent = 0, Qt::WindowFlags f = 0);

protected:
   virtual void mouseMoveEvent(QMouseEvent *event);
};
In der ersten Zeile deklariere ich die neue Klasse und sage mit "public QLabel" das ich von QLabel erben möchte.

Anschließend erstelle ich unter "public" einen Konstruktor der Klasse (kann man eigentlich komplett aus der QLabel übernehmen!) und unter protected deklariere ich die Methode mouseMoveEvent(). Da diese in der Basisklasse virtual ist, kann man diese in der abgeleiteten Klasse überschreiben.

Jetzt implementiere ich deine Funktionalität in das mouseMoveEvent():

Deine Label.cpp-Datei

Code: Alles auswählen

MyLabel::MyLabel(QWidget * parent, Qt::WindowFlags f): 
   QLabel(parent, f)
{}

void MyLabel::mouseMoveEvent(QMouseEvent *event)
{
   // hier wird das event der Label-Klasse aufgerufen, damit die Implementation
   // bzw. die Funktionalität des Labels erhalten bleibt.
   QLabel::mouseMoveEvent(event);

   // in diesem Schritt löse ich das in der Klasse deklarierte Signal "posChanged"
   // mit der aktuellen Position als Parameter aus.
   emit posChanged(event->pos());
}
So das dürfte erst einmal alles auf der Label-Seite sein.

Jetzt musst du nur noch in deiner ImageViewer-Klasse ein Slot schreiben, dass ein "QPoint &" als Parameter erwartet und dann das Signal mit diesem Slot verbinden.

In diesem Slot kannst du dann die x- und y-Koordinate auslesen und in deine statusBar schreiben.

Hoffe das es jetzt etwas ausführlicher/verständlicher war ;)

Wenn du noch Probleme oder Fragen zu der Label-Klasse oder zum Verbinden des Signals mit dem SLOT haben solltest, kannst du ja nochmal fragen. :)

Gruß
GSoft
Lerne aus den Fehlern Anderer! Du hast nicht die Zeit sie selbst zu machen.
undertone
Beiträge: 8
Registriert: 26. März 2010 12:32

Beitrag von undertone »

Vielen Dank, die Antwort hat doch schonmal einiges Licht ins Dunkle gebracht :D

Leider bekomme ich die Verbindung des Signals mit dem Slot noch nicht hin. Und void posChanged(QPoint &pos) ging nicht, da const QPoint erwartet wurde. Habe das jetzt in void posChanged(QPoint pos) geändert.

In meiner ImageViewer.h Datei habe ich noch folgendes hinzugefügt

Code: Alles auswählen

 private slots:
   ...
  void showPosition(QPoint pos);
und in der cpp Datei

Code: Alles auswählen

 void ImageViewer::showPosition(QPoint pos)
  {
	QString qstr;
	qstr.sprintf(" Koordinaten:%d,%d ", pos.x(), pos.y());
	statusBar()->showMessage(qstr);
  }
Wie muss mein "connect" aussehen?
GSoft
Beiträge: 24
Registriert: 30. Dezember 2008 01:16
Wohnort: NRW

Beitrag von GSoft »

undertone hat geschrieben:Vielen Dank, die Antwort hat doch schonmal einiges Licht ins Dunkle gebracht :D
Freut mich :D
undertone hat geschrieben: Leider bekomme ich die Verbindung des Signals mit dem Slot noch nicht hin. Und void posChanged(QPoint &pos) ging nicht, da const QPoint erwartet wurde. Habe das jetzt in void posChanged(QPoint pos) geändert.
Ich arbeite lieber mit Referenzen (wo es halt geht), in der Regel sollte es, bis auf beim Arbeiten mit Threads, überall ausreichen und die bevorzugte Wahl sein.

Bei deiner Version wird beim jedem Auslösen, das QPoint-Object aus dem Label einmal kopiert und als Kopie übergeben. Bei Referenzen würde man nur auf einem Objekt arbeiten. Das neu anlegen des Objekts und das kopieren in das neue Objekt, kann bei zeit intensiven Sachen etwas Geschwindigkeit kosten... was in diesem Fall eh nicht zu spüren währe. (ist halt eine Optimierungsmöglichkeit :D)
undertone hat geschrieben: In meiner ImageViewer.h Datei habe ich noch folgendes hinzugefügt

Code: Alles auswählen

 private slots:
   ...
  void showPosition(QPoint pos);
und in der cpp Datei

Code: Alles auswählen

 void ImageViewer::showPosition(QPoint pos)
  {
	QString qstr;
	qstr.sprintf(" Koordinaten:%d,%d ", pos.x(), pos.y());
	statusBar()->showMessage(qstr);
  }
Wie muss mein "connect" aussehen?
Das Connect macht man i. d. R. in dem Constructor der Klasse.

Die Syntax dafür findest du im Qt-Assistent unter dem Index: QObject::connect

Dieses QObject:: kannst du dir ersparen, da deine Klasse auch von QObject ableitet.

Das heißt das dein connect ungefähr so aussehen muss:

Code: Alles auswählen

connect(meinLabel, SIGNAL(posChanged(QPoint)), this, SLOT(showPosition(QPoint)));
Das this kannst du auch weglassen, da es eine überschriebene connect-Funktion gibt, die dann automatisch this nimmt (zumindest beim Empfänger der Nachricht!).

Damit könnte der Konstruktor auch wie folgt aussehen:

Code: Alles auswählen

connect(meinLabel, SIGNAL(posChanged(QPoint)), SLOT(showPosition(QPoint)));
Gruß
GSoft

PS: Bitte denk an das Q_OBJECT in deiner Klassendeklaration, sonst werden die Signale/Slots garnicht verbunden.
Lerne aus den Fehlern Anderer! Du hast nicht die Zeit sie selbst zu machen.
undertone
Beiträge: 8
Registriert: 26. März 2010 12:32

Beitrag von undertone »

Vielen vielen Dank! Jetzt funktionierts! Ich bin begeistert!
undertone
Beiträge: 8
Registriert: 26. März 2010 12:32

Beitrag von undertone »

Jetzt habe ich eine neue Frage: gibt es eigentlich die Möglichkeit, auf die Farbwerte des Labels an einer bestimmten Position zuzugreifen? Toll wäre, wenn ich mit der Maus über mein Label "fahre" und in der Statusleiste dann die Koordinaten (klappt ja schon super :D ) und der Grauwert des Bildes angezeigt werden...
GSoft
Beiträge: 24
Registriert: 30. Dezember 2008 01:16
Wohnort: NRW

Beitrag von GSoft »

Möglich ist schon mal alles ;), die Frage ist immer ob der Aufwand dafür gerechtfertigt werden kann :D

So wie ich beim Überfliegen gesehen habe, mit einem QPixmap, nicht. Bei einem QImage ist das über die nachfolgende Methode möglich:

Code: Alles auswählen

QRgb QImage::pixel ( const QPoint & position ) const
Der Ablauf ist/währe dann ungefähr so, in deiner showPosition() Methode (oder besser einen neuen Slot showPixelColor(QPoint pos) oder so schreiben und dem mit auch mit dem gleichen Signal vom Label connecten) ermittelst du über die oben gennante Methode den Farbwert an der Position und zeigst ihn an.

Die einzige Voraussetzung dafür ist, das dein Label immer genauso groß wie dein Bild ist.

Gruß
GSoft
Lerne aus den Fehlern Anderer! Du hast nicht die Zeit sie selbst zu machen.
Antworten