- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
Qt 允许您使用样式表来设置 GUI 的样式。那些使用与常规 CSS 类似的选择器语法。我想在代码中使用这些选择器来访问特定的小部件,类似于 jQuery 的工作方式。例如:
SomeQtCSSMagic::resolveSelector("QPushButton#okButton");
这可能吗?如果没有,是否至少有我可以从 Qt 库复制粘贴并编辑以满足我的需要的代码?
最佳答案
目前,Qt 没有为此提供官方支持。但使用普通 C++ 代码并不难。
您的选择器转换为:
for (auto top : qApp->topLevelWidgets()) {
auto widgets = top->findChildren<QWidget*>("okButton");
widgets << top;
for (auto widget : widgets)
if (widget->inherits("QPushButton"))
qDebug() << "found" << widget;
}
如果您觉得这样的代码很乏味,您可以利用私有(private) Qt 代码。 CSS 解析器接口(interface)在 src/gui/text/qcssparser_p.h 中.除了解析器之外,您还需要一些代码来使用已解析的选择器来查找小部件。即,您必须为指向 QObject
的节点实现 QCss::StyleSelector
。这是由 QStyleSheetStyleSelector
在 src/widgets/styles/qstylesheetstyle.cpp 中完成的,但这是一个未导出的本地类,因此您确实有一些 copypasta 来处理它。
一旦您实现了QCss::StyleSelector
,此处为QObjectStyleSelector
,获取选择器应用的小部件就很容易了。您必须遍历所有小部件,并查看 CSS 机制是否对给定节点有任何规则,假设一个虚拟样式表由您的选择器和一个空主体 {}
组成。这种方法支持样式表支持的所有选择器,但在小部件的样式上进行选择除外:
QWidgetList select(const QString & selector) {
static QHash<QString, StyleSheet> cache;
QWidgetList result;
QObjectStyleSelector oSel;
auto it = cache.find(selector);
if (it == cache.end()) {
StyleSheet styleSheet;
Parser parser(selector + "{}");
if (!parser.parse(&styleSheet))
return result;
it = cache.insert(selector, styleSheet);
}
oSel.styleSheets.append(*it);
for (auto top : qApp->topLevelWidgets()) {
auto widgets = top->findChildren<QWidget*>();
widgets << top;
for (auto widget : widgets) {
StyleSelector::NodePtr n { widget };
auto rules = oSel.styleRulesForNode(n);
if (!rules.isEmpty()) result << widget;
}
}
return result;
}
上面的代码不会被小部件上可能存在的任何样式表“分散注意力”——它考虑了它们的副作用(例如属性更改),但忽略了它们。
您可以按如下方式进行测试:
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QDialog dialog;
QPushButton button{"OK", &dialog};
button.setObjectName("okButton");
button.setStyleSheet("color: red");
auto dialog_l = QWidgetList() << &dialog;
auto button_l = QWidgetList() << &button;
auto all_l = button_l + dialog_l;
Q_ASSERT(select("QPushButton#okButton") == button_l);
Q_ASSERT(select("QDialog QPushButton") == button_l);
Q_ASSERT(select("QDialog") == dialog_l);
Q_ASSERT(select("QDialog, QPushButton") == all_l);
}
copy-pasta 在上面之前:
// https://github.com/KubaO/stackoverflown/tree/master/questions/css-selector-35129103
#include <QtWidgets>
#include <private/qcssparser_p.h>
using namespace QCss;
// FROM src/widgets/styles/qstylesheetstyle.cpp
#define OBJECT_PTR(node) (static_cast<QObject*>((node).ptr))
static inline QObject *parentObject(const QObject *obj)
{
if (qobject_cast<const QLabel *>(obj) && qstrcmp(obj->metaObject()->className(), "QTipLabel") == 0) {
QObject *p = qvariant_cast<QObject *>(obj->property("_q_stylesheet_parent"));
if (p)
return p;
}
return obj->parent();
}
class QObjectStyleSelector : public StyleSelector
{
public:
QObjectStyleSelector() { }
QStringList nodeNames(NodePtr node) const Q_DECL_OVERRIDE
{
if (isNullNode(node))
return QStringList();
const QMetaObject *metaObject = OBJECT_PTR(node)->metaObject();
#ifndef QT_NO_TOOLTIP
if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
return QStringList(QLatin1String("QToolTip"));
#endif
QStringList result;
do {
result += QString::fromLatin1(metaObject->className()).replace(QLatin1Char(':'), QLatin1Char('-'));
metaObject = metaObject->superClass();
} while (metaObject != 0);
return result;
}
QString attribute(NodePtr node, const QString& name) const Q_DECL_OVERRIDE
{
if (isNullNode(node))
return QString();
auto obj = OBJECT_PTR(node);
auto value = obj->property(name.toLatin1());
if (!value.isValid()) {
if (name == QLatin1String("class")) {
auto className = QString::fromLatin1(obj->metaObject()->className());
if (className.contains(QLatin1Char(':')))
className.replace(QLatin1Char(':'), QLatin1Char('-'));
return className;
}
}
if(value.type() == QVariant::StringList || value.type() == QVariant::List)
return value.toStringList().join(QLatin1Char(' '));
else
return value.toString();
}
bool nodeNameEquals(NodePtr node, const QString& nodeName) const Q_DECL_OVERRIDE
{
if (isNullNode(node))
return false;
auto metaObject = OBJECT_PTR(node)->metaObject();
#ifndef QT_NO_TOOLTIP
if (qstrcmp(metaObject->className(), "QTipLabel") == 0)
return nodeName == QLatin1String("QToolTip");
#endif
do {
const ushort *uc = (const ushort *)nodeName.constData();
const ushort *e = uc + nodeName.length();
const uchar *c = (const uchar *)metaObject->className();
while (*c && uc != e && (*uc == *c || (*c == ':' && *uc == '-'))) {
++uc;
++c;
}
if (uc == e && !*c)
return true;
metaObject = metaObject->superClass();
} while (metaObject != 0);
return false;
}
bool hasAttributes(NodePtr) const Q_DECL_OVERRIDE
{ return true; }
QStringList nodeIds(NodePtr node) const Q_DECL_OVERRIDE
{ return isNullNode(node) ? QStringList() : QStringList(OBJECT_PTR(node)->objectName()); }
bool isNullNode(NodePtr node) const Q_DECL_OVERRIDE
{ return node.ptr == 0; }
NodePtr parentNode(NodePtr node) const Q_DECL_OVERRIDE
{ NodePtr n; n.ptr = isNullNode(node) ? 0 : parentObject(OBJECT_PTR(node)); return n; }
NodePtr previousSiblingNode(NodePtr) const Q_DECL_OVERRIDE
{ NodePtr n; n.ptr = 0; return n; }
NodePtr duplicateNode(NodePtr node) const Q_DECL_OVERRIDE
{ return node; }
void freeNode(NodePtr) const Q_DECL_OVERRIDE
{ }
};
// END FROM
#cssparser-35129103.pro
QT = widgets gui-private
CONFIG += c++11
TARGET = cssparser-35129103
TEMPLATE = app
SOURCES += main.cpp
关于c++ - 使用 CSS (QSS) 选择器获取 QWidget*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35129103/
一些帖子(即这两个:Set CSS in QPushButton's subclass's constructor 和 Does the use of styleSheets in a dynamic
是否有任何好的 Qt QSS 教程,或者在某个地方我可以看到样式小部件的示例?如果某处可用,我想要一些完整的引用。除了有关如何设置按钮或某些选项卡样式的小教程外,我找不到任何其他内容。 最佳答案 Qt
所以我们为选项卡定制了 QSS,我想从标准选项卡中重新创建这种外观,但出于某种原因,我无法重新创建它。我希望所选选项卡看起来像在顶部并直接进入 Pane 。 选中或未选中时,选项卡的边框都可以正常工作
如果我有一个标签,其边距是使用 setMargin() 设置的,那么我可以使用 margin() 来获取值。 但是如果我使用样式表设置内边距呢? ui->label->setStyleSheet("Q
如何设置作为小部件文本一部分的跨度的样式(例如 QLabel)通过全局样式表? 例如。在下面的例子中, foo 和 bar 都应该是红色的。 #include #include class som
我知道不支持 QCalendarWidget QSS 样式,但有谁知道更改 1 和 部分颜色的一些解决方法QCalendarWidget 的 2? (1 部分为浅蓝色,2 部分为白色) 谢谢! 最佳答
我正在尝试为我的应用程序中的所有 QLineEdits 设置一些样式。以下是代码: QLineEdit { border: none; padding-bottom: 2px;
我有一个像这样的自定义QFrame //! Widget which displays a audio level meter, indicating the //! level and peak l
我想要做的是在特定文件夹中有一个 QSS 样式表。我想以编程方式从 GUI 编辑选定的元素。由于 QT 不支持 SaSS 或 LeSS,我需要“手动”执行此操作。到目前为止,我所拥有的是读取一个 qs
我尝试(font-weigth: 有效,但 text-align: 无效): QTabBar::tab:text{ font-weight:bold; text-align:left;
我已经尝试使用 disabled 和 !enabled 但它不起作用。这是我的 QSS 代码: QPushButton { background-color:#44c767; bord
当用户将鼠标悬停在 PyQT4 QSS 中时,如何在按钮周围创建一个发光的边框?我说的是类似于 CSS 中的 box-shadow 的东西。 someButton:hover { border
如何将 qt 的样式表 .qss 文件导入应用程序? 在 HTML 中我们使用 如何在 PyQt 中完成? 或者我在哪里可以读到它?无法用谷歌搜索或在 Qt 的文档中找到它。 最佳答案 .qss 文
有人能告诉我如何在 pyqt4 中使用 qss 文件吗?我尝试在 QTdesigner 中更改样式表,例如 this在QT的官方文档上。但它不起作用。我不确定它对 pyqt 是否有效。我发现this
晚上好,我正在尝试生成一个如图所示的日历: 到目前为止,我通过 QSS 取得的成果是: 这就是我用过的QSS QCalendarWidget QAbstractItemView { selection
我有一个问题。 如何在我的项目文件夹中创建一个文件。 .QSS ? 在创建新文件的选项中不要有这个扩展名! 非常感谢您的帮助。 谢谢。 最佳答案 Control+N -> 一般 ->选择 在名字里写s
我正在尝试这样做: 但我在我的 QTableView 中设置了那个样式表: QTableView { gridline-color: black; background-color:
我有一个包含 QTableView 的 QDialog,以及一个显示枚举类型的 QComboBox 的自定义委托(delegate)。当未选择该行时,我仍然希望 QComboBox 可见(我想避免使用
使用 QFontDialog 我得到一个 QFont 对象作为返回值。我将 Qt 样式表与小部件一起使用,因此设置 myWidget->setFont(fontFromDialog) 似乎没有有任何效
我想自定义 QMdiSubWindow 的标题栏。 为此,我使用 qss。 QMdiSubWindow { border: 1px solid #000000; background: #000000
我是一名优秀的程序员,十分优秀!