QGraphicsScene und mouse-Event Propagierung

Alles rund um die Programmierung mit Qt
Antworten
lyman
Beiträge: 2
Registriert: 5. Oktober 2010 11:13

QGraphicsScene und mouse-Event Propagierung

Beitrag von lyman »

Hallo zusammen,

ich beschäftige mich erst seit ein paar Wochen mit Qt - Wenn mein folgendes Problem trivial ist oder auf meiner Blödheit beruht, möge man es mir verzeihen... :) Ich habe leider nichts dazu gefunden und die Doku konnte mir da auch nicht helfen.

Mein Programm hat folgende Struktur:
Ich habe eine eher verwaltende Klasse abgeleitet von QWidget, die wiederum eine QGraphicsScene und eine QGraphicsView zur Darstellung und für Benutzereingaben hat. Das Maus-Event-Handling möchte ich aber eigentlich in meiner Verwaltungsklasse beherbergen.
Mein Problem ist jedoch, dass mousePressEvents zwar wunderbar von der View bis zur Verwaltungsklasse durchgereicht werden, mouseRelease und Doppelklick jedoch in der Scene "verschwinden", auch wenn sich in der Scene keine Items befinden.
Ist das so gewollt (wenn ja, was wird damit gemacht?), habe ich irgendwelche Flags vergessen, oder hab ich sonst irgendwas übersehen? Ich wollte das Eventhandling ungern in die Scene oder View auslagern, zumal mich interessiert, warum das ganze nicht so funktioniert, wie ich mir das gedacht hatte...

Kompilierbares Beispiel um zu verdeutlichen, was ich meine:

mainwindow.h

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <qDebug>
#include "myview.h"
#include "myscene.h"
#include <QDockWidget>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    MyView* myView;
    MyScene* myScene;

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);

};

#endif // MAINWINDOW_H
mainwindow.cpp

Code: Alles auswählen

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    myView = new MyView();
    myScene = new MyScene();
    myView->setScene(myScene);
    myScene->setSceneRect(-50,-50,100,100);
    QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this);
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
                                Qt::RightDockWidgetArea);
    dockWidget->setWidget(myView);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
}

MainWindow::~MainWindow()
{

}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "MainWindow: mousePressEvent";
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    qDebug() << "MainWindow: mouseReleaseEvent";
}
myscene.h

Code: Alles auswählen

#ifndef MYSCENE_H
#define MYSCENE_H

#include <QGraphicsScene>
#include <qDebug>

class MyScene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit MyScene(QObject *parent = 0);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};

#endif // MYSCENE_H
myscene.cpp

Code: Alles auswählen

#include "myscene.h"

MyScene::MyScene(QObject *parent) :
    QGraphicsScene(parent)
{
}

void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "MyScene: mousePressEvent";
    QGraphicsScene::mousePressEvent(event);
}

void MyScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    qDebug() << "MyScene: mouseReleaseEvent";
    QGraphicsScene::mouseReleaseEvent(event);
}

myview.h

Code: Alles auswählen

#ifndef MYVIEW_H
#define MYVIEW_H

#include <QGraphicsView>
#include <qDebug>

class MyView : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyView(QWidget *parent = 0);

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
};

#endif // MYVIEW_H
myview.cpp

Code: Alles auswählen

#include "myview.h"

MyView::MyView(QWidget *parent) :
        QGraphicsView(parent)
{
}

void MyView::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "MyView: mousePressEvent";
    QGraphicsView::mousePressEvent(event);
}

void MyView::mouseReleaseEvent(QMouseEvent *event)
{
    qDebug() << "MyView: mouseReleaseEvent";
    QGraphicsView::mouseReleaseEvent(event);
}
und eine passende main:

Code: Alles auswählen

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
Das ganze erzeugt bei einem Mausklick mit release folgende Ausgabe:

Code: Alles auswählen

MyView: mousePressEvent
MyScene: mousePressEvent
MainWindow: mousePressEvent
MyView: mouseReleaseEvent
MyScene: mouseReleaseEvent

Vielen Dank schonmal... :)
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Vielleicht hilft dir die API:
http://doc.qt.nokia.com/4.6/qmouseevent.html#details
Detailed Description
[snipp]
A mouse event contains a special accept flag that indicates whether the receiver wants the event. You should call ignore() if the mouse event is not handled by your widget. A mouse event is propagated up the parent widget chain until a widget accepts it with accept(), or an event filter consumes it.
Note: If a mouse event is propagated to a widget for which Qt::WA_NoMousePropagation has been set, that mouse event will not be propagated further up the parent widget chain.
[snipp]
The QWidget::setEnabled() function can be used to enable or disable mouse and keyboard events for a widget. Reimplement the QWidget event handlers, QWidget::mousePressEvent(), QWidget::mouseReleaseEvent(), QWidget::mouseDoubleClickEvent(), and QWidget::mouseMoveEvent() to receive mouse events in your own widgets.
Für die DoubleClicks fehlen dir die Handler (im Minibeispiel, das war vorbildlich, die Beschreibung auch ::thumbup:: ... und vermutlich solltest du mal auf Qt::WA_NoMousePropagation testen .. ansonsten vielleicht noch eine event.ignore() nach der QIrgendWas::mouseHandler() machen
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
lyman
Beiträge: 2
Registriert: 5. Oktober 2010 11:13

Beitrag von lyman »

Das mit dem Doppelklick ist mir klar - ich wollte es hier nur etwas kürzer halten und hatte mir gedacht, dass das Verhalten von mouseRelease und Doppelklick eh irgendwie zusammenhängen.

In meinem Programm habe ich die Scene nicht abgeleitet und verwende die Basisimplementierung von QGraphicsScene, weil sie für meine Verwendung wunderbar ausreicht. Ich hab die hier nur zu Testzwecken abgeleitet um zu sehen, wo die Propagierung aufhört. Scheinbar tut sie das ja bei der QGraphicsScene - für die ich aber ja keine WidgetAttributes setzen kann, weil sie garnicht von QWidget erbt? Wenn ich event.ignore() richtig verstehe, müsste ich das ja im Event-Handler selber aufrufen, also in meinem Fall scheinbar in der Scene-Klasse (die ich ja eigentlich nicht haben wollte). Und trotzdem kommt scheinbar nichts beim MainWindow an. (Veranlasst ein ignore() im Event-Handler von MyScene, dass der Event-Handler von QGraphicsScene aufgerufen wird?) Event-Filter verwende ich nicht.

Was mich halt wundert ist, dass der Press weitergeleitet wird, wie er soll, der ReleaseEvent und Doubleclick aber nicht.
Antworten