选定鼠标事件的 Qt 透明
Qt Transparent for selected Mouse Events
这里是 C++ Qt 新手。我使用旨在通过鼠标滚轮控制的 QDial 对象,它工作正常,必要时发出 valueChanged() 信号。
我想在上面放一个半透明的QToolButton,允许用户点击按钮(并将QDial值设置为预定义的数字)同时保持使用鼠标滚轮控制的能力照常Q拨号。
我对 TransparentForMouseEvents 属性进行了一些试验:
ui->toolButton_Example->setAttribute(Qt::WA_TransparentForMouseEvents);
问题是 - 上面的代码关闭了所有事件,包括发出 clicked() 信号的能力。
有没有办法使 QToolButton 有选择地对 MouseWheelEvents 透明,同时保留响应 MouseClick 事件的能力?或者这是否需要从头开始重写事件过滤器?
编辑:澄清一下——这个问题是关于使 QToolButton 对 MouseWheel EVENTS 透明,同时仍然允许它响应 MouseClick EVENTS。这不是让按钮在图形意义上透明。
解决方案
好的,问题通过继承 QDial 并覆盖 MousePressEvent 和 MouseReleaseEvent 的传统方式解决了:
#include <QDial>
#include <QMouseEvent>
class QSuperDial : public QDial {
public:
QSuperDial (QWidget *parent = nullptr) : QDial(parent) {
}
virtual void mousePressEvent (QMouseEvent *event) override {
emit sliderPressed();
}
virtual void mouseMoveEvent (QMouseEvent * event) override {
}
virtual void mouseReleaseEvent (QMouseEvent *event) override {
}
};
将 QDial 升级为 QSuperDial 会导致 QDial 对象 'behaves' 在按下时像一个按钮,发出 sliderPressed 信号,同时仍然响应 MouseWheelEvent(就像普通的 QDial)。
我认为这是最简单也是最'Qt-like'的解决方法,如果有误请指正
您可以使用 QObject::installEventFilter
to have the parent object filter the events before they reach the tool button. Then, override the parent's QObject::eventFilter
来 handle/ignore 活动。
我在下面创建了一个例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QToolButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
bool eventFilter(QObject *watched, QEvent *event) override;
private:
QToolButton tool_button_ignored_;
QToolButton tool_button_handled_;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
#include <QEvent>
#include <QHBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
tool_button_ignored_.setObjectName("tool_button_ignored_");
tool_button_ignored_.setText("Ignored button");
tool_button_ignored_.installEventFilter(this);
tool_button_handled_.setObjectName("tool_button_handled_");
tool_button_handled_.setText("Handled button");
tool_button_handled_.installEventFilter(this);
QWidget *central_widget = new QWidget{this};
QHBoxLayout *layout = new QHBoxLayout{central_widget};
layout->addWidget(&tool_button_ignored_);
layout->addWidget(&tool_button_handled_);
this->setCentralWidget(central_widget);
}
MainWindow::~MainWindow()
{
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched != &tool_button_ignored_ || event->type() != QEvent::Wheel)
{
qDebug() << event->type() << watched->objectName() << "handled";
return QMainWindow::eventFilter(watched, event);
}
else
{
qDebug() << event->type() << watched->objectName() << "ignored";
return true; // stop being handled further
}
}
这里是 C++ Qt 新手。我使用旨在通过鼠标滚轮控制的 QDial 对象,它工作正常,必要时发出 valueChanged() 信号。
我想在上面放一个半透明的QToolButton,允许用户点击按钮(并将QDial值设置为预定义的数字)同时保持使用鼠标滚轮控制的能力照常Q拨号。
我对 TransparentForMouseEvents 属性进行了一些试验:
ui->toolButton_Example->setAttribute(Qt::WA_TransparentForMouseEvents);
问题是 - 上面的代码关闭了所有事件,包括发出 clicked() 信号的能力。
有没有办法使 QToolButton 有选择地对 MouseWheelEvents 透明,同时保留响应 MouseClick 事件的能力?或者这是否需要从头开始重写事件过滤器?
编辑:澄清一下——这个问题是关于使 QToolButton 对 MouseWheel EVENTS 透明,同时仍然允许它响应 MouseClick EVENTS。这不是让按钮在图形意义上透明。
解决方案 好的,问题通过继承 QDial 并覆盖 MousePressEvent 和 MouseReleaseEvent 的传统方式解决了:
#include <QDial>
#include <QMouseEvent>
class QSuperDial : public QDial {
public:
QSuperDial (QWidget *parent = nullptr) : QDial(parent) {
}
virtual void mousePressEvent (QMouseEvent *event) override {
emit sliderPressed();
}
virtual void mouseMoveEvent (QMouseEvent * event) override {
}
virtual void mouseReleaseEvent (QMouseEvent *event) override {
}
};
将 QDial 升级为 QSuperDial 会导致 QDial 对象 'behaves' 在按下时像一个按钮,发出 sliderPressed 信号,同时仍然响应 MouseWheelEvent(就像普通的 QDial)。
我认为这是最简单也是最'Qt-like'的解决方法,如果有误请指正
您可以使用 QObject::installEventFilter
to have the parent object filter the events before they reach the tool button. Then, override the parent's QObject::eventFilter
来 handle/ignore 活动。
我在下面创建了一个例子:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QToolButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
bool eventFilter(QObject *watched, QEvent *event) override;
private:
QToolButton tool_button_ignored_;
QToolButton tool_button_handled_;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
#include <QEvent>
#include <QHBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
tool_button_ignored_.setObjectName("tool_button_ignored_");
tool_button_ignored_.setText("Ignored button");
tool_button_ignored_.installEventFilter(this);
tool_button_handled_.setObjectName("tool_button_handled_");
tool_button_handled_.setText("Handled button");
tool_button_handled_.installEventFilter(this);
QWidget *central_widget = new QWidget{this};
QHBoxLayout *layout = new QHBoxLayout{central_widget};
layout->addWidget(&tool_button_ignored_);
layout->addWidget(&tool_button_handled_);
this->setCentralWidget(central_widget);
}
MainWindow::~MainWindow()
{
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched != &tool_button_ignored_ || event->type() != QEvent::Wheel)
{
qDebug() << event->type() << watched->objectName() << "handled";
return QMainWindow::eventFilter(watched, event);
}
else
{
qDebug() << event->type() << watched->objectName() << "ignored";
return true; // stop being handled further
}
}