如何在带有背景图像的小部件上制作隐形按钮?
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 设置样式,但排除子类。这是必要的,因为QPushButton
是QWidget
的子类,否则也会受到影响。
然后你可以像你一样将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 像素的不可见可点击区域:
【讨论】:
我没有想到QPushButton
和QWidget
之间的继承。你的解决方案比我的好,所以我支持你。谢谢你的解释。
@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。 好吧,我当时不明白,它对我有用。我尝试使用QPushButton
和QToolButton
并且效果相同。也许如果我们能看到你的代码...
@KkVova 我的解决方案有效,但我认为 scopchanov 提供的解决方案要简单得多。以上是关于如何在带有背景图像的小部件上制作隐形按钮?的主要内容,如果未能解决你的问题,请参考以下文章
带有媒体上传按钮的自定义Wordpress窗口小部件,在每个窗口小部件上插入相同的图像