首页 > 解决方案 > 选定鼠标事件的 Qt 透明

问题描述

C++ Qt 新手在这里。我使用旨在通过鼠标滚轮控制的 QDial 对象,它可以正常工作,在必要时发出 valueChanged() 信号。

我想在它上面放一个半透明的 QToolButton,允许用户单击按钮(并将 QDial 值设置为预定义的数字),同时保持像往常一样使用鼠标滚轮控制 QDial 的能力。

我对 TransparentForMouseEvents 属性做了一些试验:

ui->toolButton_Example->setAttribute(Qt::WA_TransparentForMouseEvents);

问题是 - 上面的代码关闭了所有事件,包括发出 clicked() 信号的能力。

有没有办法让 QToolButton 选择性地为 MouseWheelEvents 透明,同时保留响应 MouseClick 事件的能力?或者这是否需要从头开始重写事件过滤器?

编辑:澄清一下 - 这个问题是关于使 QToolButton 对 MouseWheel 事件透明,同时仍然允许它响应 MouseClick 事件。这不是让按钮在图形意义上透明。

解决方案 好的,通过继承 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 对象在按下时“行为”像一个按钮,发出 sliderPressed 信号,同时仍然响应 MouseWheelEvent(就像一个普通的 QDial)。

我认为这是最简单和最“类似 Qt”的解决方案,但如果我弄错了,请纠正我。

标签: c++qteventfilter

解决方案


您可以使用QObject::installEventFilter让父对象在事件到达工具按钮之前对其进行过滤。然后,覆盖父QObject::eventFilter级以处理/忽略该事件。

我在下面创建一个示例:

主窗口.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

主窗口.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
    }
}

推荐阅读