如何在带有背景图像的小部件上制作不可见按钮?

How to make invisible button on widget with background image?

我想做一个简单的带隐形按钮的应用程序。

我通过 UI 属性 styleSheet 和资源 -
为我的小部件设置背景图像 边框图片:url(:/image.jpg)。 我总是得到这样的东西

然后我尝试在上面添加按钮

我正在尝试

ui->pushButton->setStyleSheet("QPushButton{background: transparent;}");
ui->pushButton->setStyleSheet("background-color: rgba(255, 255, 255, 0);");

它适用于默认背景上的按钮,但不适用于我的情况。

我添加的每个按钮都采用默认父背景图像。我不想看到按钮的任何提示,但是当我单击某个区域时能够执行某些功能。

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->centralWidget->setStyleSheet("background-image:url(:image.jpg)");
    ui->pushButton->setStyleSheet("QPushButton{border:none;}");
}

上面的代码使按钮变平,但它仍然从父窗口小部件复制背景图像。

你知道如何解决吗?

我认为在这里回答比在评论中回答更好。

您只需为 QPushButton 设置以下样式表即可使其不可见:

QPushButton
{
    border: none;
}

我已经做了测试,效果很好。

为了测试,我设置了包装小部件的 background-image 属性。我还用 background-color 属性 做了另一个测试。它在两种情况下都有效(无论背景是纯色还是 picture/photo)。

希望对您有所帮助。


编辑:

我已经编写了一个小部件来执行您想要的操作。我还提供了一个 windows 以使下面的示例最小化和完整,以便您可以重现它。

我已经测试过了,效果很好。

test.h:

#ifndef TEST_H
#define TEST_H

#include <QMainWindow>
#include <QPushButton>

class WidgetWithHiddenButton : public QWidget
{
    Q_OBJECT

    protected:
        QPushButton * invisible_button;

    public:
        WidgetWithHiddenButton(QWidget * parent = nullptr);
        QPushButton * getButton();

    protected:
        void paintEvent(QPaintEvent *) override;
};

class TestWindow final : public QMainWindow
{
    Q_OBJECT

    private:
        WidgetWithHiddenButton * widget;

    public:
        TestWindow();
};

#endif // TEST_H

test.cpp:

#include "test.h"

#include <QApplication>
#include <QStyleOption>
#include <QPainter>
#include <QVBoxLayout>

WidgetWithHiddenButton::WidgetWithHiddenButton(QWidget * parent) : QWidget(parent)
{
    // build your widget as you want.

    invisible_button = new QPushButton("Here is a button", this);
    QVBoxLayout * lay = new QVBoxLayout;
    QHBoxLayout * inner_lay = new QHBoxLayout;
    inner_lay->addStretch();
    inner_lay->addWidget(invisible_button);
    inner_lay->addStretch();
    lay->addLayout(inner_lay);
    this->setLayout(lay);

    this->setStyleSheet("WidgetWithHiddenButton {background-image: url(path_to_image/image.jpg);}");
    invisible_button->setStyleSheet("QPushButton {border: none;}");
}
QPushButton * WidgetWithHiddenButton::getButton()
{
    return invisible_button;
}
void WidgetWithHiddenButton::paintEvent(QPaintEvent *)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

TestWindow::TestWindow()
{
    resize(500, 300);

    widget = new WidgetWithHiddenButton;
    this->setCentralWidget(widget);

    connect(widget->getButton(), &QPushButton::clicked, qApp, &QApplication::quit);
}

int main(int argc, char ** argv)
{
    QApplication app(argc, argv);

    TestWindow tw;
    tw.show();

    return app.exec();
}

随意调整它(尤其是通过更改 class 名称,因为 WidgetWithHiddenButton 非常丑陋:))。

备注:

  • 我在按钮中写了一段文字以使其可见(用于测试目的),但如果您希望按钮完全不可见,您可以将其删除。
  • 我将 QPushButton::clicked() 信号连接到 QApplication::quit() 插槽,以便在我们单击按钮区域时执行操作。
  • 我重新定义了 paintEvent() 方法,因为在 documentation 提到的自定义 QWidget 上使用 Q_OBJECT 宏和样式表时需要它。
  • 请随意修改我在构造函数中构建小部件的方式(布局、大小...)以使其符合您的要求。

原因

一个常见的误解是,如果将不带 selector 的样式表应用于元素,则它仅用于该元素。事实上,所有元素的子元素也有样式。因此应该使用选择器来达到预期的结果。

解决方案

我建议您更改代码中的这一行

ui->centralWidget->setStyleSheet("background-image:url(:image.jpg)");

ui->centralWidget->setStyleSheet(".QWidget { background-image:url(:image.jpg) }");

重要提示: 注意 QWidget 之前的点。这意味着 设计 QWidget 的样式,但排除子类 。这是必要的,因为 QPushButtonQWidget 的子类,否则也会受到影响。

然后你可以像

一样将pushButton的背景颜色设置为透明
ui->pushButton->setStyleSheet("QPushButton{background: transparent;}");

例子

这是我为您准备的一个简单示例,用于演示建议的解决方案(需要 pix/images 下的资源文件中的 cat.png):

#include <QMainWindow>
#include <QWidget>
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr) :
        QMainWindow(parent) {
        auto *widget = new QWidget(this);
        auto *button = new QPushButton(widget);

        widget->setStyleSheet(".QWidget {"
                              " background-image:url(':/pix/images/cat.png');"
                              " background-repeat: no-repeat;"
                              "}");

        button->setStyleSheet(".QPushButton {"
                              " background-color: transparent"
                              "}");
        button->move(100, 100);
        button->resize(100, 100);

        connect(button, &QPushButton::clicked, [](){
            qDebug("clicked");
        });

        setCentralWidget(widget);
        resize(600, 480);
    }
};

结果

给定的示例生成一个 window,带有背景和位于 (100, 100):

的 100x100px 不可见可点击区域