How can I prevent the clicked() signal when I want to grab the doubleClicked() signal in mytablewidget ?
-
I copy code from http://qt-project.org/faq/answer/how_can_i_prevent_the_clicked_signal_from_being_emitted_when_i_want_to_grab,
but when doubleClicked() is Executed,two clicked() are Executed too.how can i do . -
Well, basically, you can't. Not really. A click will by definition happen before a double click is detected.
What you can do, is instead of directly triggering your action from your click handler, start a timer with a short timeout if it is not already running. If a doubleclick is detected, stop the timer. Connect the timer's timeout signal to the action you had in mind for your single click. The timer interval needs to be slightly bigger than the doubleclick interval, I think. You can get that interval from QApplication. -
Hi Andre!
I became quite curious to know the technique when *foxgod* posted this question. I tried implementing it using the timer. Am I doing it right?
@
bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
QTimer *timer = new QTimer();
if (event->type() == QEvent::MouseButtonDblClick)
{
QMouseEvent * mouseEvent = static_cast <QMouseEvent *> (event);
if (mouseEvent->button()==Qt::LeftButton)
{
timer->stop();
qDebug()<<"Button is double clicked";
return true;
}
}
else
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent * mouseEvent = static_cast <QMouseEvent *> (event);
if (mouseEvent->button()==Qt::LeftButton)
{
timer->start(10000);
timer->setSingleShot(true);
connect( timer, SIGNAL(timeout()), SLOT(single_click_function()) );
return true;
}
}
return QObject::eventFilter(target, event);
}void MainWindow::single_click_function()
{
qDebug()<<"Button is single clicked";
}
@ -
Have you tried it? I bet if you did, it doesn't work.
First, a timeout of 10000 ms (ten full seconds!) seems excessive to wait for a mouse click. I'd use QApplication::doubleClickInterval to get a more reasonable value. Then, don't make a new QTimer instance every time your eventFilter method is called. Do you have any idea how often that happens? Worse, those timers you create are not cleared up, causing a memory leak. Use a single QTimer instance somewhere in your class for this. Next, as it stands, your code handling the double click is useless. It stops a timer instance that is not even started, and leaves all other instances in tact. Finally, note that for a doubleclick, you will (I think) get two MouseButtonPress events. Only the first should start a timer, of course.
So no, I don't think this implementation will work.
What I would do, I create a separate class for this, probably in the form of a charm.
-
[quote author="Andre" date="1364374349"]Have you tried it? I bet if you did, it doesn't work.
What I would do, I create a separate class for this, probably in the form of a charm. [/quote]What does this mean?
And yes, I am aware my code doesn't work. I just wanted to know where I am going wrong and how you would go about solving the problem because I learn a lot from that.
P.S. - I hope my questions weren't extra work since I'm not even the OP.
-
A charm... Hmmm... not an official term I guess.
The terms (for me) comes from the "flick charm":http://blog.qt.digia.com/blog/2008/11/15/flick-list-or-kinetic-scrolling/ that was blogged about a couple of years ago (before QML was introduced). For me, the real value of this post was not the specific functionality it demonstrated, but the way it was done. Instead of creating a subclass, a new class that extends the functionality of a class from the 'outside': a charm. You 'cast' it like a spell over another object, and that object magically changes his behavior. Qt's event filters are perfect for doing that.
See for instance this "topic on renaming tabs":/forums/viewthread/10390/ and also "this explanation":/forums/viewreply/66091/ of the idea.
-
Well, I tried to create this functionality as a charm, and it works nicely:
header:
@
#ifndef CLICKANDDOUBLECLICKCHARM_H
#define CLICKANDDOUBLECLICKCHARM_H#include <QObject>
class QTimer;
class QWidget;class ClickAndDoubleClickCharm : public QObject
{
Q_OBJECT
public:
static ClickAndDoubleClickCharm* cast(QWidget* subject);
bool eventFilter(QObject *, QEvent *);signals:
void clicked(Qt::MouseButton);
void doubleClicked(Qt::MouseButton);private:
explicit ClickAndDoubleClickCharm(QWidget *parent = 0);
Q_SLOT void clickTrigger();private:
QWidget* m_subject;
QTimer* m_clickTimer;
Qt::MouseButton m_mouseButton;
};#endif // CLICKANDDOUBLECLICKCHARM_H
@implementation:
@
#include "clickanddoubleclickcharm.h"
#include <QWidget>
#include <QApplication>
#include <QTimer>
#include <QMouseEvent>ClickAndDoubleClickCharm::ClickAndDoubleClickCharm(QWidget *parent) :
QObject(parent),
m_subject(parent),
m_clickTimer(new QTimer(this)),
m_mouseButton(Qt::NoButton)
{
m_clickTimer->setInterval(qApp->doubleClickInterval() * 1.1);
connect(m_clickTimer, SIGNAL(timeout()), this, SLOT(clickTrigger()));
parent->installEventFilter(this);
}void ClickAndDoubleClickCharm::clickTrigger()
{
m_clickTimer->stop();
emit clicked(m_mouseButton);
m_mouseButton = Qt::NoButton;
}ClickAndDoubleClickCharm *ClickAndDoubleClickCharm::cast(QWidget *subject)
{
if (!subject)
return 0;ClickAndDoubleClickCharm* charm = subject->findChild<ClickAndDoubleClickCharm*>(); if (!charm) { charm = new ClickAndDoubleClickCharm(subject); } return charm;
}
bool ClickAndDoubleClickCharm::eventFilter(QObject o, QEvent e)
{
if (o == m_subject) {
QMouseEvent mouseEvent = dynamic_cast<QMouseEvent>(e);
if (e->type() == QEvent::MouseButtonPress) {
m_mouseButton = mouseEvent->button();
} else if (e->type() == QEvent::MouseButtonRelease) {
if (m_mouseButton == mouseEvent->button()) {
if (!m_clickTimer->isActive()) {
m_clickTimer->start();
}
}
} else if (e->type() == QEvent::MouseButtonDblClick) {
if (m_mouseButton == mouseEvent->button()) {
m_clickTimer->stop();
emit doubleClicked(m_mouseButton);
m_mouseButton = Qt::NoButton;
}
}
}return QObject::eventFilter(o, e);
}
@Example of how to use:
@
ClickAndDoubleClickCharm* charm = ClickAndDoubleClickCharm::cast(ui->pushButton);
connect(charm, SIGNAL(clicked(Qt::MouseButton)), this, SLOT(clicked()));
connect(charm, SIGNAL(doubleClicked(Qt::MouseButton)), this, SLOT(doubleClicked()));
@Clicking on the button will result in the clicked slot, and double clicking only of the doubleClicked slot.