Qt5中QPushButton::setAutoRepeat(true)在Windows触摸屏上失效求助
解决方案
针对Windows 10触摸屏上Qt5按钮长按触发右键菜单、setAutoRepeat失效的问题,可通过以下几种方案解决:
方案一:拦截Windows原生右键菜单消息
重写QPushButton的nativeEvent方法,直接拦截系统发送的右键菜单触发消息,避免黑色矩形弹出,同时保留Qt自带的自动重复逻辑:
#include <QPushButton> #include <windows.h> class TouchRepeatButton : public QPushButton { Q_OBJECT public: explicit TouchRepeatButton(QWidget *parent = nullptr) : QPushButton(parent) { setAutoRepeat(true); // 可根据需求调整自动重复的初始延迟和间隔 setAutoRepeatDelay(500); setAutoRepeatInterval(100); } protected: bool nativeEvent(const QByteArray &eventType, void *message, long *result) override { MSG *msg = static_cast<MSG*>(message); // 拦截WM_CONTEXTMENU消息,阻止系统弹出右键菜单 if (msg->message == WM_CONTEXTMENU) { *result = 0; return true; } return QPushButton::nativeEvent(eventType, message, result); } };
方案二:手动实现触摸长按重复逻辑
放弃Qt自带的setAutoRepeat,通过定时器完全自定义长按重复逻辑,同时拦截触摸事件避免系统触发右键:
#include <QPushButton> #include <QTimer> #include <windows.h> class TouchRepeatButton : public QPushButton { Q_OBJECT public: explicit TouchRepeatButton(QWidget *parent = nullptr) : QPushButton(parent) { m_repeatTimer = new QTimer(this); connect(m_repeatTimer, &QTimer::timeout, this, [this](){ emit clicked(); // 触发点击信号,或直接调用你的计数器递增逻辑 }); // 配置长按初始延迟和重复间隔 m_initialDelay = 500; m_repeatInterval = 100; } protected: void touchEvent(QTouchEvent *event) override { if (event->type() == QEvent::TouchBegin) { m_repeatTimer->start(m_initialDelay); } else if (event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel) { m_repeatTimer->stop(); // 短按情况下触发一次点击 if (!m_repeatTimer->isActive()) { emit clicked(); } } event->accept(); // 阻止事件传递给系统,避免触发长按右键 } bool nativeEvent(const QByteArray &eventType, void *message, long *result) override { MSG *msg = static_cast<MSG*>(message); if (msg->message == WM_CONTEXTMENU) { *result = 0; return true; } return QPushButton::nativeEvent(eventType, message, result); } private: QTimer *m_repeatTimer; int m_initialDelay; int m_repeatInterval; };
方案三:调整Qt全局触摸属性
在应用启动时配置以下属性,让Qt优先处理触摸事件,减少系统合成右键的可能:
int main(int argc, char *argv[]) { QApplication a(argc, argv); // 禁用系统原生触摸手势 a.setAttribute(Qt::AA_DisableNativeGesture); // 关闭未处理触摸事件的鼠标合成,避免干扰按钮逻辑 a.setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); // 确保Qt主动处理触摸事件 a.setAttribute(Qt::WA_AcceptTouchEvents, true); // 同时给按钮设置禁用上下文菜单 QPushButton btn; btn.setContextMenuPolicy(Qt::NoContextMenu); btn.setAutoRepeat(true); MainWindow w; w.show(); return a.exec(); }
关键说明
Windows触摸长按右键是系统级行为,无需全局禁用系统设置,通过拦截原生消息或自定义逻辑即可规避。若Qt自带自动重复在触摸模式下仍失效,手动实现定时器逻辑是更稳定的选择。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

