[SOLVED] Handle mouse double clicked and mouse single click event
-
wrote on 29 May 2015, 11:31 last edited by mistralegna 6 Aug 2015, 11:44
Hello,
I would like to handle in a list view mouse single click and mouse double click events. So I reimplemented two slots connected to the corresponding signals of the QListView. However, when a I perform a double click, the single click is called. I also tried to reimplement the corresponding protected methods (to mousePress and mouseDoubleClick events) in subclasses of QListView, but the same issue occurs.
Do you have some idea to avoid this behavior ?
Thanks a lot !
-
Hi,
Can you share your code ?
-
wrote on 30 May 2015, 10:27 last edited by
Here is an extracted version of the code, showing the issue I'm encountering.
I'm compiling in C++11.
File main.cpp
#include <QApplication> #include <QDebug> #include <QFileSystemModel> #include "ListView.hpp" void viewClicked(const QModelIndex& idx) { qDebug() << QObject::trUtf8("Item %1 has been clicked.").arg(idx.data().toString()); } void viewDoubleClicked(const QModelIndex& idx) { qDebug() << QObject::trUtf8("Item %1 has been double clicked.").arg(idx.data().toString()); } int testWithNoSubclass(int argc, char** argv) { QApplication app(argc, argv); QFileSystemModel fileModel; QListView view; view.setWindowTitle(QObject::trUtf8("Test with standard view")); view.setEditTriggers(QAbstractItemView::NoEditTriggers); view.setModel(&fileModel); view.setRootIndex(fileModel.setRootPath(QDir::homePath())); view.show(); QObject::connect(&view, &QListView::clicked, &viewClicked); QObject::connect(&view, &QListView::doubleClicked, &viewDoubleClicked); return app.exec(); } int testWithSubclass(int argc, char** argv) { QApplication app(argc, argv); QFileSystemModel fileModel; ListView view; view.setWindowTitle(QObject::trUtf8("Test with subclassed view")); view.setEditTriggers(QAbstractItemView::NoEditTriggers); view.setModel(&fileModel); view.setRootIndex(fileModel.setRootPath(QDir::homePath())); view.show(); return app.exec(); } int main(int argc, char** argv) { testWithNoSubclass(argc, argv); testWithSubclass(argc, argv); }
FIle ListView.hpp
#ifndef LISTVIEW_HPP #define LISTVIEW_HPP #include <QDebug> #include <QAbstractItemModel> #include <QListView> #include <QMouseEvent> class ListView : public QListView { Q_OBJECT public: ListView(QWidget* parent = nullptr) : QListView(parent) {} protected: void mousePressEvent(QMouseEvent* e) { if ( e == nullptr ) return; QModelIndex idx = QListView::indexAt(e->pos()); if ( not idx.isValid() ) return; qDebug() << QObject::trUtf8("Item %1 has been clicked.").arg(idx.data().toString()); } void mouseDoubleClickEvent(QMouseEvent* e) { if ( e == nullptr ) return; QModelIndex idx = QListView::indexAt(e->pos()); if ( not idx.isValid() ) return; qDebug() << QObject::trUtf8("Item %1 has been double clicked.").arg(idx.data().toString()); } }; #endif // LISTVIEW_HPP
I put the code in the header just in order to avoid copying too many files here.
Thank you a lot !
-
Since you have re-implemented mousePressEvent and mouseDoubleClickEvent and you don't call the base class implementation, you are breaking the base functionality
-
wrote on 31 May 2015, 08:47 last edited by
So, according to you, I should call QListView::mousePressEvent and QListView::mouseDoubleClickEvent in the subclassed class ? In that case, I should call it at the end of the method, should I ?
I was insipired by the Scribber example, where some protected methods are reimplemented, but base class is not called in this example.
I try to modify the code today, and see how it will react to single and double click events.
-
It really depends on what you do in your subclass.
You can ignore the base class implementation, but in the case of e.g. QAbstractItemView derived classes, the function your reimplemented handles the drag and drop part. So if you want it to work, then you need to call the base class implementation or rewrite the code (you don't want to do that)
-
It really depends on what you do in your subclass.
You can ignore the base class implementation, but in the case of e.g. QAbstractItemView derived classes, the function your reimplemented handles the drag and drop part. So if you want it to work, then you need to call the base class implementation or rewrite the code (you don't want to do that)
wrote on 1 Jun 2015, 06:06 last edited byThe aim is to distinguish the single click from the double click. I would like to handle those two types of events independently.
My first message was not clear about how I did it in a first time, i.e. by connecting the signals clicked(QModelIndex) and doubleClicked(QModelIndex) of a QListView to appropriate slots. However, even in this case, the first slot is called on a double click event.
Sorry for my poor English, that is not at all my native language.
-
Do you mean you had that problem with unmodified methods ?
-
wrote on 2 Jun 2015, 13:03 last edited by
When I connected the clicked(QModelIndex) and doubleClicked(QModelIndex) signals of QListView to the following slots :
@mistralegna said:
void viewClicked(const QModelIndex& idx)
{
qDebug() << QObject::trUtf8("Item %1 has been clicked.").arg(idx.data().toString());
}void viewDoubleClicked(const QModelIndex& idx)
{
qDebug() << QObject::trUtf8("Item %1 has been double clicked.").arg(idx.data().toString());
}the double click on an item is first calling the first slot.
I would like to call only the second slot in case of an item's double click and only the first slot in the case of a single click.
-
Does it also happen if you don't modify mousePressEvent ?
-
wrote on 2 Jun 2015, 23:38 last edited by
Do you mean you had that problem with unmodified methods ?
I believe widget will always receive both single click and double click event.
When I needed I have not found reliable way to skip single click event.As far as I can recall the working solution was to start a timer on a single click which in case doubleclick event arrived was destroyed.
But most of the time it is better just to change functionality which allows both single click and double click actions to coexist. -
Do you mean you had that problem with unmodified methods ?
I believe widget will always receive both single click and double click event.
When I needed I have not found reliable way to skip single click event.As far as I can recall the working solution was to start a timer on a single click which in case doubleclick event arrived was destroyed.
But most of the time it is better just to change functionality which allows both single click and double click actions to coexist.wrote on 3 Jun 2015, 13:49 last edited by@SGaist My first post showed two different implementations to handle click events. The first is just to connect the signals QAbstractItemView::clicked(const QModelIndex&) and QAbstractItemView::doubleClicked(const QModelIndex&) to respective slots.
#include <QApplication> #include <QDebug> #include <QFileSystemModel> #include <QListView> void viewClicked(const QModelIndex& idx) { qDebug() << QObject::trUtf8("Item %1 has been clicked.").arg(idx.data().toString()); } void viewDoubleClicked(const QModelIndex& idx) { qDebug() << QObject::trUtf8("Item %1 has been double clicked.").arg(idx.data().toString()); } int main(int argc, char** argv) { QApplication app(argc, argv); QFileSystemModel fileModel; QListView view; view.setWindowTitle(QObject::trUtf8("Test with standard view")); view.setEditTriggers(QAbstractItemView::NoEditTriggers); view.setModel(&fileModel); view.setRootIndex(fileModel.setRootPath(QDir::homePath())); view.show(); QObject::connect(&view, &QListView::clicked, &viewClicked); QObject::connect(&view, &QListView::doubleClicked, &viewDoubleClicked); return app.exec(); }
Here, there is no reimplementation at all. I'm just using base functionnalities (at least, I think I am). Unfortunately, when I double click on an item, here is the output:
"Item data has been clicked." // Seems to be the first click handled. "Item data has been double clicked." // Double click event. "Item data has been clicked." // Seems to be the second click of the double click.
This is quite relevant, because the view seems to have handled two single clicks and the double click. But that's not corresponding to what I'd like to have. I thought the view would have blocked the single click event when reacting to a double click.
@alex_malyu So, according to you, does it mean that without a timer, we cannot distinguish between a single click and a double click? I'd prefer to make the distinction between those two events without any timer, if possible.
Thank you a lot!
-
wrote on 4 Jun 2015, 00:10 last edited by alex_malyu 6 Apr 2015, 00:14
If nothing changed since Qt 4 single click event on the platforms I was working on always arrives before double click event.
Lets look at scenario:- single click occurs:
Single click event arrives.
If you want to do something on a single click that is only event you will get,
So you have to react on it.- double click occurs:
- First single click event arrives.
- second double click event arrives
You want to ignore single click , but react on second event.
Question: How do you know that it was double click and will not react on a single click?
I might be missing the obvious , but the only way I found to achieve this was to start the timer when single click arrived at event handler.
This timer was stopped at double click event handler.
If it was not stopped slot with reaction needed on a single click was executed.As I said solution was not perfect and it was done for Qt 4.
But I did not see anything better except implementing behavior when reaction on single click does not have to be avoided on double click. -
If nothing changed since Qt 4 single click event on the platforms I was working on always arrives before double click event.
Lets look at scenario:- single click occurs:
Single click event arrives.
If you want to do something on a single click that is only event you will get,
So you have to react on it.- double click occurs:
- First single click event arrives.
- second double click event arrives
You want to ignore single click , but react on second event.
Question: How do you know that it was double click and will not react on a single click?
I might be missing the obvious , but the only way I found to achieve this was to start the timer when single click arrived at event handler.
This timer was stopped at double click event handler.
If it was not stopped slot with reaction needed on a single click was executed.As I said solution was not perfect and it was done for Qt 4.
But I did not see anything better except implementing behavior when reaction on single click does not have to be avoided on double click.wrote on 8 Jun 2015, 11:43 last edited by@alex_malyu Thank you ;-)
1/14