如何在带有背景图像的小部件上制作不可见按钮?
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 的样式,但排除子类 。这是必要的,因为 QPushButton
是 QWidget
的子类,否则也会受到影响。
然后你可以像
一样将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 不可见可点击区域
我想做一个简单的带隐形按钮的应用程序。
我通过 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 的样式,但排除子类 。这是必要的,因为 QPushButton
是 QWidget
的子类,否则也会受到影响。
然后你可以像
一样将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 不可见可点击区域