如何在带有背景图像的小部件上制作隐形按钮?

Posted

技术标签:

【中文标题】如何在带有背景图像的小部件上制作隐形按钮?【英文标题】:How to make invisible button on widget with background image? 【发布时间】:2019-08-08 14:00:16 【问题描述】:

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

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

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

我正在尝试

ui->pushButton->setStyleSheet("QPushButtonbackground: 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("QPushButtonborder:none;");

上面的代码使按钮变平,但无论如何它都会复制父窗口小部件的背景图像。

你知道怎么解决吗?

【问题讨论】:

你为什么使用border-image?如果要设置背景图像,请改用background-image。此外,在您提供的代码中,第二个 setStyleSheet() 覆盖了第一个(变得无用)。然后,第二个样式表不正确。 @Fareanor,我使用它是因为我需要将背景图像放入小部件中。示例代码不是我实际使用的 - 仅作为示例。 这不是border-image的意思。 @Fareanor,但有一个技巧 我不太明白你想做什么。但是,如果您想让按钮不可见,只需删除边框("QPushButton border: none;")并调用pushButton->setIcon(QIcon()); 以清除显示的图像。它应该可以工作。 【参考方案1】:

原因

一个常见的误解是,当没有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("QPushButtonbackground: 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);
    
;

结果

给定的示例生成一个带有背景的窗口和一个位于 (100, 100) 处的 100x100 像素的不可见可点击区域:

【讨论】:

我没有想到QPushButtonQWidget之间的继承。你的解决方案比我的好,所以我支持你。谢谢你的解释。 @Fareanor,不客气!实际上,我也觉得它不是很直观,但它就是这样。 :( 不,我没有。你刚刚告诉我,我们可以用一个点来做到这一点。我想我只是走运了。从现在开始,我将在将来请求它的应用程序中添加这个点。无论如何感谢您的提示:) @Fareanor,对于自定义小部件,您必须输入自定义类的名称而不是 QWidget,并使用setAttribute(Qt::WA_StyledBackground); 启用样式表。 成功了。你今天学到了两件事啊哈:)。那我会更正我的答案。即使不设置此属性,它似乎也可以工作。【参考方案2】:

我认为在这里回答比在 cmets 更好。

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

QPushButton

    border: none;

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

对于测试,我设置了包装小部件的 background-image 属性。我还使用 background-color 属性进行了另一项测试。它适用于两种情况(无论背景是纯色还是图片/照片)。

希望对你有帮助。


编辑:

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

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

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();

随意调整它(尤其是通过更改类名,因为WidgetWithHiddenButton 非常难看:))。

注意事项:

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

【讨论】:

我不知道,这是我做错了还是我没有很好地解释我的问题。我不明白你的意思。这是您答案的result。我还有可见的按钮。我添加的每个按钮都采用默认的父背景图像。我不想看到按钮的任何提示,但是当我点击某个区域时能够执行某些功能。 @KkVova 如果您使用 QtDesigner,请不要从这里设置样式表,而是从 C++ 代码设置。我从未使用过任何设计师,这就是为什么我不知道它的行为。在我的示例中,我已经用 C++ 编写了所有内容。 我删除了 Qt 设计器中提到的所有 styleSheet,并从代码中获取了the same result。 好吧,我当时不明白,它对我有用。我尝试使用QPushButtonQToolButton 并且效果相同。也许如果我们能看到你的代码... @KkVova 我的解决方案有效,但我认为 scopchanov 提供的解决方案要简单得多。

以上是关于如何在带有背景图像的小部件上制作隐形按钮?的主要内容,如果未能解决你的问题,请参考以下文章

带有媒体上传按钮的自定义Wordpress窗口小部件,在每个窗口小部件上插入相同的图像

简单的小部件按钮 - Lua - Corona SDK

如何在不影响 Pyqt5 中的小部件的情况下将背景图像添加到主窗口

php 带有图像场图像小部件的小部件

在颤振/飞镖中与图像下的小部件交互

如何关闭在提升的小部件中单击的按钮上的 qt 小部件 ui?