Qt 控件(含QPushButton)增加双击事件的实现方法(汇总)鼠标事件穿透(**)

目录

定时器法

一、重载函数mouseDoubleClickEvent

二、事件过滤器 (测试 OK)(*****)

QT按钮实现鼠标双击事件 (***)

QPushButton “双击”事件代码:样例源码 测试OK (*****)

QT鼠标事件穿透,使QLabel、QPushbutton等上层控件可以被穿透:

注:QLabel 在设置了“穿透”之后,会造成原来能够实现的鼠标点击 Label的功能、失效。

参考:

Qt Event事件详解 (*精*)

https://blog.csdn.net/ken2232/article/details/130272182

----------------------------------

Qt默认,QPushButton没有“双击”的槽函数。但有“单击”的槽函数。

====================

Qt报错:member access into incomplete type 'QMouseEvent'

#include <QMouseEvent>  //需要在头文件中添加这个头文件,OK。

参考:

Qt 事件总结(鼠标、键盘) QMouseEvent、QKeyEvent

https://blog.csdn.net/m0_73443478/article/details/127821498

Qt开发基础(11)——event事件分发器和过滤器 ******

https://blog.csdn.net/bigData1994pb/article/details/119726769

Qt学习笔记(十五):QPushButton 按钮的常用方法 ******

https://blog.csdn.net/qq_29331365/article/details/105110467?spm=1001.2101.3001.6650.18&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-18-105110467-blog-128008479.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-18-105110467-blog-128008479.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=25

获取 和 设置 按钮上的文本信息:

设置按钮控件获取焦点:

设置鼠标位于按钮控件区域时,光标的类型:

设置控件背景透明:即将控件外观设为平铺

设置按钮样式:前景色,背景色,边框等;需要通过样式表来修改

定时器法

https://blog.csdn.net/m0_48990191/article/details/126979971

参考:

char cnt =0;
void delayTime(int k)
{
    QEventLoop eventloop;
    //QTimer::singleShot(50*k, &eventloop, SLOT(quit()));
    QTimer::singleShot(50*k, &eventloop, SLOT(quit()));
    eventloop.exec();
}

void MainWindow::on_pushButton_clicked()
{
    cnt++;
    delayTime(10);
    
    if(cnt == 1)
    {
        qDebug()<<"单击";
        cnt = 0;
    }
    else if (cnt >= 2)
    {
        qDebug()<<"双击";
        cnt = 0;
    }
}

最佳应用场景:部件数量少的场景

QEventLoop事件循环的使用

https://blog.csdn.net/qq_42108501/article/details/125210922

最佳应用场景:对简单信号槽应用的扩展?

** QT 控件增加双击事件 ******

https://blog.csdn.net/ligare/article/details/125379742

一、重载函数mouseDoubleClickEvent

class SpinBoxAndCombox: public QWidget
{
Q_OBJECT
protected:
    // 然后重新实现鼠标双击事件
    void mouseDoubleClickEvent(QMouseEvent* e);
public:
    SpinBoxAndCombox(QWidget* parent = nullptr) : SpinBoxAndCombox(parent){ };
};
 
void SpinBoxAndCombox::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->buttons() == Qt::LeftButton)
    {
        qDebug() << "12345";
    }
}

最佳应用场景:屏幕绘图?

样例 功能实现:

  1. 样例针对的是:SpinBoxAndCombox::,因此,SpinBoxAndCombox::可以接收到双击信号。

  1. 如果改成如下代码,则:MainWindow::整个窗口可以接收到双击信号。

而在 QPushButton上进行鼠标“双击”,是没有反应的。上层的 QPushButton遮挡了 “双击”信号;无法穿透到 MainWindow,所以没有反应。

一般来说,点击 MainWindow就可以获得与坐标有关的一些信号。但当光标在QPushButton上时,这时点击鼠标,将获得与 QPushButton有关的信号了,而不是与 ui界面有关的坐标信号;此时,需要对 QPushButton进行“穿透”设置,相当于此时可以无视 QPushButton的遮挡,于是,就又可以获得ui坐标信号了。

ui->pushButton->setAttribute(Qt::WA_TransparentForMouseEvents); //设置 QPushButton可以被穿透,这样双击QPushButton,就有反应了。

https://blog.csdn.net/weixin_43246170/article/details/127383224

void MainWindow:: mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->buttons() == Qt:: LeftButton)
{
qDebug() << "mouse Double Click: active 激发.";
}
}

 

  1. ?除非为 QPushButton单独采用一个类来实现,并将mouseDoubleClickEvent(QMouseEvent *event) 的作用域限定为 QPushButton。但这样就太繁琐了。

假如一个窗口有 10个部件,那么,难道每一个部件都需要编写 一个mouseDoubleClickEvent函数吗?

这就是事件过滤器的好处了。

二、事件过滤器 (测试 OK)(*****)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
protected:
    virtual bool eventFilter(QObject * obj,QEvent *event) override;
 
private:
    Ui::MainWindow *ui;
};
 
#endif // MAINWINDOW_H

最佳应用场景:部件数量多的场景?与定时器双击功能相比。

注a1:event 输出

qDebug() << event;

QMouseEvent(MouseButtonDblClick, LeftButton, localPos=157,95, screenPos=861,200)

#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->widget->installEventFilter(this); //widget控件安装事件过滤器
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->widget) // 你要过滤的对象
            if (event->type() == QEvent::MouseButtonDblClick) 
            { // 你要过滤的对象的事件类型
              // 你自己期望实现的功能,在这里我的实现是新建一个标签页以及新的文本编辑栏
                
                return true; // 注意这里一定要返回true,表示你要过滤该事件原本的实现
            }
        return false; // 返回false表示不过滤,还按默认的来
}

注a2:event 输出

  1. 直接安装在按键上,OK

 ui->installEventFilter(this); // pushButton控件安装事件过滤器

QMouseEvent(MouseButtonDblClick, LeftButton, localPos=49,8, screenPos=639,368)

注a3:综合比较

注a1/2的共同点,输出的数据相同

qDebug() << event;

QMouseEvent(MouseButtonDblClick, LeftButton, localPos=157,95, screenPos=861,200)

注a1/2的不同点:

注a1并没有直接关联部件:需要进行坐标换算等等。如屏幕绘图场景?

注a2被安装在部件上:可以直接对部件进行双击,有效。扩展简单信号槽的应用?

QPushButton “双击”事件代码:样例源码 测试OK (*****)

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMouseEvent> //需要在头文件中添加这个头文件,OK。
#include <QDebug>

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

// ui->pushButton->setAttribute(Qt::WA_TransparentForMouseEvents);

ui->pushButton->installEventFilter(this); //pushButton控件安装事件过滤器
}

MainWindow::~ MainWindow()
{
delete ui;
}


bool MainWindow:: eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->pushButton) // 你要过滤的对象
{
if (event->type() == QEvent:: MouseButtonDblClick)
{
             // 你要过滤的对象的事件类型
// 你自己期望实现的功能,在这里我的实现是新建一个标签页以及新的文本编辑栏

qDebug()<<"pushButton MouseButtonDblClick : active";

//拦截
return true; // 注意这里一定要返回true,表示你要过滤该事件原本的实现
}
else
{
//不进行拦截
return false; // 返回false表示不过滤,还按默认的来
}
}
else
{
//当不确定是否继续传播时,按照父类的方法来处理
//即调用父类的evenFilter函数
return QMainWindow::eventFilter(obj, event);
}
}

要点说明:

  1. #include <QMouseEvent>

  1. ui->pushButton->installEventFilter(this); //pushButton控件安装事件过滤器

  1. bool MainWindow::eventFilter(QObject *obj, QEvent *event)

bool MainWindow:: eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->pushButton ) // 你要过滤的对象
{
if (event->type() == QEvent:: MouseButtonDblClick)
{
// 你要过滤的对象的事件类型
// 你自己期望实现的功能,在这里我的实现是新建一个标签页以及新的文本编辑栏

qDebug()<<"Debug_11: pushButton MouseButtonDblClick : active";

//拦截
return true;  //(1)  // 注意这里一定要返回true,表示你要过滤该事件原本的实现
}
        else
        {
qDebug()<<"Debug_22: pushButton MouseButtonDblClick : active";

//不进行拦截
return false; //(2) // 返回false表示不过滤,还按默认的来
        }
    else
    {
         return MainWindow::eventFilter(obj, event);
    }
}

   

问题:

在 win下,OK.

在linux下,NG。出现:qt.qpa.xcb: internal error: void QXcbWindow::setNetWmStateOnUnmappedWindow() called on mapped window

源码说明abc:

  1. 双击信号的发出者和接收者,都是同一个 pushButton,这就产生了上述的问题?

只要光标处在  pushButton的有效范围之内,Debug_22 就有条件地一直输出;这个条件就是达到了 Qt规定的默认鼠标没有变化的时候,才停止输出。

  1. ui->pushButton->installEventFilter(this); 在本例中,接收者本身就是自己,因此,实际上, return true;  进行拦截,是没有意义的。除非信号的发出者和接收者,不是同一个部件。

  1. 可能原因(?错误的分析 ?):冲突导致的问题?只要光标处在 pushButton的有效范围之内,信号的发出者(也是信号的接收者)就一直有条件地输出Debug_22;同时,信号的发出者又发出拦截信号,于是,由于Qt unlikely 的算法 if (Q_UNLIKELY(m_mapped)) 存在着某种问题,就造成了这种错误??

临时解决:

取消 (1)(2)两句,则 OK。  why ????????

从 源码说明abc 处来看:在这个例子中,取消掉,应该是没有问题的。

源码:

https://github.com/qt/qtbase/blob/dev/src/plugins/platforms/xcb/qxcbwindow.cpp

void QXcbWindow::setNetWmStateOnUnmappedWindow()
{
if (Q_UNLIKELY(m_mapped))
qCWarning(lcQpaXcb()) << "internal error: " << Q_FUNC_INFO << "called on mapped window";

C++关键字之likely和unlikely 

什么是likely和unlikely

既然程序是我们程序员所写,在一些明确的场景下,我们应该比CPU和编译器更了解哪个分支条件更有可能被满足。

我们是否可将这一先验知识告知编译器和CPU, 提高分支预测的准确率,从而减少CPU流水线分支预测错误带来的性能损失呢?答案是可以!它便是likely和unlikely。

likely()与unlikely()函数的作用

https://blog.csdn.net/q2519008/article/details/83929064

#define likely(x) __builtin_expect(!!(x), 1)

也就是说明x==1是“经常发生的”或是“很可能发生的”。

所以使用likely ,执行if后面语句的可能性大些,编译器将if{}是的内容编译到前面

使用unlikely ,执行else后面语句的可能性大些,编译器将else{}里的内容编译到前面。

以上操作是有利于cpu预取,提高预取指令的正确率,因而可提高效率。

————————————————

QtConcurrent多线程 - map、mapped和mappedReduced

https://blog.csdn.net/douzhq/article/details/104758445

未解决:

结论:

有时,采用其他方法,比如定时器法,也不错。

毕竟 Qt IDE开发工具本身,也是有 bug的。

直接获取屏幕坐标

https://blog.csdn.net/Larry_Yanan/article/details/125046472

Qt:QPushButton 单击、双击响应区分
子类化

开发环境:win10+vs2015+qt5.9.1

背景:QPushButton的双击事件虽然一直有,但是在双击完成之前,总会响应到单击的事件处理或者连接槽,使用很不方便。自己子类化了一个QPushButton来区分这两种点击事件的处理

https://blog.csdn.net/a1115873361/article/details/101151330?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-101151330-blog-125423858.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-5-101151330-blog-125423858.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=9

QT 中实现QLabel的点击事件(重写QLabel)

默认情况下,QLabel是不支持点击事件的,要实现QLabel的点击事件,一般有两种方式:

1、继承QLabel,重写鼠标点击事件,通过发送信号与父窗体实现通讯

2、安装事件过滤器,通过判断控件以及事件来实现

QToolButton双击事件

QToolButon自身信号不具有双击事件,如果想要实现双击事件,需要重写QToolButton。

首先需要继承QToolButtton,利用鼠标双击事件void mouseDoubleClickEvent(QMouseEvent *event);进行实现

MyToolButton.h

#ifndef MyToolButton_H
#define MyToolButton_H

#include <QtWidgets/QWidget>
#include <QtGui/QMouseEvent>
#include <QtWidgets/QToolButton>

//带双击事件的QToolButoon
class MyToolButton : public QToolButton
{
    Q_OBJECT
public:
    explicit MyToolButton(QWidget * parent = 0);
    ~MyToolButton();
    
    //实现QToolButton左键双击事件
    virtual void mouseDoubleClickEvent(QMouseEvent *event);
    
signals:
    //双击信号
    void doubleClicked();
};

#endif //MyToolButton_H

MyToolButton.cpp

#include "MyToolButton.h"

MyToolButton::MyToolButton(QWidget * parent) : QToolButton(parent)
{
    
}

MyToolButton::~MyToolButton()
{
    
}

//实现QToolButton左键双击事件
void MyToolButton::mouseDoubleClickEvent(QMouseEvent *event)
{
    /* 也可在此写双击想要实现的事件*/
    
    //如果需要自定义控件,则发送左键双击信号
    //如果双击事件则发送双击事件信号
    if (event->button() == Qt::LeftButton) 
    {
        emit doubleClicked();
    }    
}

继承重写后接口实现双击事件,在需要使用的文件中加上MyToolButton.h文件,连接信号槽事件接口。

//创建自定义QToolButton
MyToolButton * m_toolButoon = new MyToolButton;
 
//连接信号槽事件
connect(m_toolButoon, SIGNAL(doubleClicked()), this, SLOT(slotTableShow1()));

————————————————

版权声明:本文为CSDN博主「没有网名L」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/RYIJU5YUJTY/article/details/125404947

重写mouseDoubleClickEvent()函数

https://blog.csdn.net/qq_40714324/article/details/88862370

QPushButton实现双击效果

废话不多说,直接贴代码。只需继承QPushButton再重写mouseDoubleClickEvent()函数即可。这里判断了左键双击发出一个自定义信号doubleClicked()。

class Mybtn :public QPushButton
{
    Q_OBJECT
public:
    explicit Mybtn(QWidget *parent = 0):QPushButton(parent){}
    virtual void mouseDoubleClickEvent(QMouseEvent *event) {
        if(event->button() == Qt::LeftButton) {
            emit doubleClicked();
        }
    }
signals:
    void doubleClicked();
};

QT按钮实现鼠标双击事件 (***)

利用事件过滤器实现按钮双击功能,新手第一次写这个,网上找不到方便的方法,所以就直接上代码了。

首先,在需要点击的按钮或者控件设置事件过滤器。

例如:

ui->btnPressure->installEventFilter(this);

.......................

然后在.h文件添加事件函数

bool MainWindow::eventFilter(QObject *watched, QEvent *event);

在.cpp文件实现 ,另:项目需要用的比较多,所以给合在一起了。注意分开就好。

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{     
    if(watched==ui->btnPressure||watched==ui->btnStart||watched==ui->btnPause||watched==ui->btnUseTime||watched==ui->btnAuxiliary||watched==ui->btnUser||watched==ui->btnTrigger||watched==ui->btnExit)  
    {     
        if(event->type()==QEvent::MouseButtonDblClick)      
        {         
            QMouseEvent *e = static_cast<QMouseEvent *>(event);          
            if(e->button() == Qt::LeftButton)          
            { 
                if(watched==ui->btnPressure)
                    qDebug()<<"参数双击了按钮";
                
                else if(watched==ui->btnStart)
                    qDebug()<<"开始双击了按钮";
                
                else if(watched==ui->btnPause)
                    qDebug()<<"双压机双击了按钮";
                
                else if(watched==ui->btnUseTime)                  
                    qDebug()<<"治疗时间机双击了按钮";
                
                else if(watched==ui->btnAuxiliary)                 
                    qDebug()<<"反搏比双击了按钮";
                
                else if(watched==ui->btnUser)                  
                    qDebug()<<"用户管理双击了按钮";
                
                else if(watched==ui->btnTrigger)                   
                    qDebug()<<"触发模式双击了按钮";
                
                else if(watched==ui->btnExit)                  
                    qDebug()<<"退出双击了按钮";              
            }
        }
    }
    return QWidget::eventFilter(watched, event); 
}

————————————————

版权声明:本文为CSDN博主「缄默221」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_70432649/article/details/126643190

思考:

事件循环:本质上,就是“软中断”而已?

信号槽:本质上,就是复杂一些的信号发送小模块和信号接收模块而已?

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值