PDA

View Full Version : QEvents subclassing QListWidget - not getting mouse press or release



bmahf
24th January 2011, 00:30
I'm a bit lost here. I've created a new class subclassing QListWidget, and I have a qDebug() as the first statement in my event() method. It's printing out the event type for each call. I'm getting the following list (with the text to the right of the event # added by me):

1 - Regular timer event
8 - Gaining keyboard focus
9 - Losing keyboard focus
10 - Mouse entering boundaries
11 - Mouse leaving boundaries
13 - Widget position changed
14 - Widget size changed
17 - Widget shown on screen
24 - Window was activated
25 - Window was deactivated
26 - A child widget has been shown
39 - Widget palette has changed
67 - ??
68 - Child was added
69 - Child was polished
70 - Child was inserted
71 - Child was removed
74 - Request for polish
75 - Widget was polished
97 - Font was changed
110 - "What's This?" help was clicked
178 - The margins of the content rect changed
194 - Touch begin: beginning of a sequence of touch-screen or track pad events
198 - Gesture: a gesture was triggered
203 - Widget's WinId was changed

I'm not seeing any mouse press or release events. I'm trying to trap events so that mouse clicks are no longer processed by QListWidget, but by me. And yet, when I click the mouse in my list widget, the items in the list are still being highlighted and unhighlighted. How is the base class getting ahold of these events if I'm overriding event()?

Any help here? Or should this question be in another forum? It seems to me this is a Qt question, because somehow the super class is getting events I'm not seeing.

high_flyer
24th January 2011, 15:46
Why don't you override the corresponding event handlers?
mousePressEvent() and friends...

bmahf
24th January 2011, 19:56
I started working on that. But the question still remains. When I look in the "C++ GUI Programming with Qt 4" book by Blanchette, supposedly the officially supported book, but admittedly old at this point, they say that you should be able to override event() to catch any events before it goes to the specific event filters, such as mousePressEvent(). The online documentation seems to support this. So I guess the question still stands in my mind as to why this doesn't work. I'm off to do it the other way, but if anyone has an ideas as to why the documented approach doesn't work, or as to how I could be reading that incorrectly, I would appreciate the input.

high_flyer
24th January 2011, 21:00
they say that you should be able to override event() to catch any events before it goes to the specific event filters, such as mousePressEvent().
This is true.
You are probably doing something wrong in your implementation.
Instead of dwelling on that, I suggested to override the event handlers since it will work for sure, and get you going.
If you want, post your code, and we can have a look at what you are doing wrong ;)

bmahf
26th January 2011, 21:15
So I have looked further and found that the event() function in QWidget is not virtual, which I'm not sure why that's that way. As far as code, I set up a gui project, and my MainWindow class creates and populates a ChildListWidget object which is derived from QListWidget. I found out that I had to implement mousePressEvent(), mouseReleaseEvent(), and mouseMoveEvent() in order to get QListWidget to no longer process these events. They were not being passed through my reimplementation of event(). At the very top of ChildListWidget::event(), I am printing the enum for the event type that I get. The enum for mouseButtonPress is 2 and for mouseButtonRelease is 3, but I see neither of these when I look at the output. My code is as follows. If I'm doing something wrong here I'd love to know about it:

mainwindow.h:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class ChildListWidget;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;
ChildListWidget *m_listWidget;
};

#endif // MAINWINDOW_H


mainwindow.cpp:


#include "mainwindow.h"
#include "childlistwidget.h"
#include "ui_mainwindow.h"
#include <QListWidget>
#include <QSize>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

QSize winsize = this->window()->size();

m_listWidget = new ChildListWidget(this);
m_listWidget->resize(winsize.width(), winsize.height() - 35);

QListWidgetItem* item;
item = new QListWidgetItem("Item 1");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 2");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 3");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 4");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 5");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 6");
m_listWidget->addItem(item);
item = new QListWidgetItem("Item 7");
m_listWidget->addItem(item);

this->setCentralWidget(m_listWidget);
}


childlistwidget.h:


#ifndef CHILDLISTWIDGET_H
#define CHILDLISTWIDGET_H

#include <QListWidget>

class QGestureEvent;
class QSwipeGesture;
class QPanGesture;
class QEvent;

class ChildListWidget : public QListWidget
{
Q_OBJECT
public:
explicit ChildListWidget(QWidget *parent = 0);

virtual bool event(QEvent *e);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);

bool gestureEvent(QGestureEvent *event);

void swipeTriggered(QSwipeGesture* gesture);
void panTriggered(QPanGesture* gesture);

bool eventFilter(QObject *obj, QEvent *event);

};

#endif // CHILDLISTWIDGET_H


childlistwidget.cpp:


#include "childlistwidget.h"

#include <QEvent>
#include <QGesture>
#include <QGestureEvent>
#include <QPainter>
#include <QEvent>
#include <QList>
#include <QDebug>

ChildListWidget::ChildListWidget(QWidget *parent) :
QListWidget(parent)
{
grabGesture(Qt::PanGesture);
grabGesture(Qt::SwipeGesture);
grabGesture(Qt::PinchGesture);
installEventFilter(this);
}

bool ChildListWidget::event(QEvent *e)
{
qDebug() << "ChildListWidget::event(): type(): " << e->type();
if (e->type() == QEvent::Gesture) {
qDebug() << "QEvent::Gesture";
return gestureEvent(static_cast<QGestureEvent*>(e));
}
if (e->type() == QEvent::MouseButtonPress) {
qDebug() << "QEvent::MouseButtonPress";
return true;
// do nothing
}
if (e->type() == QEvent::MouseButtonRelease) {
qDebug() << "QEvent::MouseButtonRelease";
// do nothing
return true;
}
return QListWidget::event(e);
}

void ChildListWidget::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
event->accept();
}

void ChildListWidget::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event);
event->accept();
}

void ChildListWidget::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event);
event->accept();
}

bool ChildListWidget::gestureEvent(QGestureEvent *event)
{
Q_UNUSED(event);
qDebug() << "ChildListWidget::gestureEvent()";
qDebug() << "Gesture type: " << event->gestures().at(0)->gestureType();
if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) {
//swipeTriggered(static_cast<QSwipeGesture *>(swipe));
} else if (QGesture *pan = event->gesture(Qt::PanGesture)) {
//panTriggered(static_cast<QPanGesture *>(pan));
}
return true;
}

void ChildListWidget::swipeTriggered(QSwipeGesture* gesture)
{
Q_UNUSED(gesture);
qDebug() << "ChildListWidget::swipeTriggered()";
}

void ChildListWidget::panTriggered(QPanGesture* gesture)
{
Q_UNUSED(gesture);
qDebug() << "ChildListWidget::panTriggered()";
}

bool ChildListWidget::eventFilter(QObject *obj, QEvent *event)
{
Q_UNUSED(obj);
qDebug() << "ChildListWidget::eventFilter()";
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
}


main.cpp:


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

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

return a.exec();
}

high_flyer
27th January 2011, 09:12
So I have looked further and found that the event() function in QWidget is not virtual, which I'm not sure why that's that way.
That is not true - its virtual protected:
(documentation):

bool QWidget::event ( QEvent * event ) [virtual protected]

This is not realated (that I can see) to the problem you are talking about but:


installEventFilter(this);


This code makes no sense.
You use an event filter when you want anotehr object to filter this objects events - each object receives its own events any way.

Why do you use Q_UNUSED when you are clearly using the variable?

At the moment I don't see why some events will not be caught in your event() handler, in respect to your original post (except that the code for these events is not in the function as you are now using the specialized handlers).

bmahf
27th January 2011, 17:06
Yes, I see that, as far as the online documentation is concerned, but when I open qwidget.h (and I'm sure that I'm opening the correct one because in QtCreator, I have #include <QWidget> and then I type the word QWidget in a function and then right click and choose "Follow Symbol Under Cursor") I see (for 4.7.1) at line 635 that "bool event(QEvent *);" is what is declared, not "virtual book event(QEvent *);".

Thanks, I see what you mean about the installEventfilter(this).

As to the Q_UNUSED, that was something I put in there before putting the accept, and forgot to remove it. The Q_UNUSED, as I understand it, just tells the compiler not to print a warning, so I'm not sure that's causing any issues. Chalk it up to moving too quickly. :)