[英]Qt Q_OBJECT macro causes unexpected behaviour with style sheets
I have written a custom Qt widget extending the QWidget
class.我编写了一个扩展QWidget
类的自定义 Qt 小部件。
Let's consider the following code:让我们考虑以下代码:
.h 。H
#ifndef SS_TEST_H
#define SS_TEST_H
#include <QMainWindow>
class TestWidget : public QWidget
{
Q_OBJECT // ***>>> BUG HERE <<<***
public:
TestWidget(const QString & v1, const QString & v2, QWidget * parent = nullptr);
};
class TestWindow : public QMainWindow
{
Q_OBJECT
public:
TestWindow();
};
#endif // SS_TEST_H
.cpp .cpp
#include "ss_test.h"
#include <QGridLayout>
#include <QLabel>
#include <QApplication>
TestWidget::TestWidget(const QString & v1, const QString & v2, QWidget * parent) : QWidget(parent)
{
QGridLayout * lay = new QGridLayout;
QLabel * field = new QLabel(v1, this);
QLabel * value = new QLabel(v2, this);
value->setMinimumWidth(80);
value->setAlignment(Qt::AlignCenter);
value->setStyleSheet("QLabel { background-color: white; border: 1px solid silver; }");
lay->addWidget(field, 0, 0);
lay->addWidget(value, 0, 1);
this->setLayout(lay);
this->setStyleSheet("QWidget { background-color: red; }");
}
TestWindow::TestWindow()
{
setWindowTitle("ss test");
resize(400, 300);
QWidget * cw = new QWidget;
QVBoxLayout * cl = new QVBoxLayout;
TestWidget * tw1 = new TestWidget("Field 1", "Value 1", this);
TestWidget * tw2 = new TestWidget("Field 2", "Value 2", this);
cl->addWidget(tw1);
cl->addWidget(tw2);
cl->addStretch();
cw->setLayout(cl);
this->setCentralWidget(cw);
}
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
TestWindow tw;
tw.show();
return app.exec();
}
The widget that I am talking about is the TestWidget
class.我正在谈论的小部件是TestWidget
类。
Without the Q_OBJECT
macro in the class declaration, I obtain exactly the style I want:如果类声明中没有Q_OBJECT
宏,我将获得我想要的样式:
But if I add the Q_OBJECT
macro at the beginning of the class declaration (as you can see the comments in the header file), it unexpectedly modifies the style of the widget:但是如果我在类声明的开头添加Q_OBJECT
宏(正如你在头文件中看到的注释),它意外地修改了小部件的样式:
I do not understand what happens here.我不明白这里发生了什么。
Of course, in my real project, the widget is way more elaborated than it is in this minimal example and necessarily needs the Q_OBJECT
macro (in order to use signal/slots mechanisms and qobject_cast
).当然,在我的实际项目中,小部件比这个最小示例中的要复杂得多,并且必然需要Q_OBJECT
宏(为了使用信号/插槽机制和qobject_cast
)。
I would be very grateful if someone can explain me what Q_OBJECT
does here and why.如果有人能向我解释Q_OBJECT
在这里做什么以及为什么,我将不胜感激。
One has to read the documentation quite carefully to stumble on the right passage .人们必须非常仔细地阅读文档才能偶然发现正确的段落。
Your TestWidget class needs to reimplement the paintEvent:您的 TestWidget 类需要重新实现paintEvent:
void TestWidget::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
There is also the important note, that you have to define the Q_OBJECT macro.还有一个重要的注意事项,您必须定义 Q_OBJECT 宏。
Warning: Make sure you define the Q_OBJECT macro for your custom widget.警告:确保为自定义小部件定义 Q_OBJECT 宏。
I tried it and the behavior seemingly fit your needs.我试过了,这种行为似乎符合您的需求。
A possible explanation for the strange behavior, in case of lacking Q_OBJECT, might be, that qobject_cast<TestWidget*>(widget)
would yield nullptr
.在缺少 Q_OBJECT 的情况下,对这种奇怪行为的一种可能解释是, qobject_cast<TestWidget*>(widget)
将产生nullptr
。 That might result in a different behavior for the rendered stylesheet.这可能会导致呈现的样式表出现不同的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.