Qt 中的样式表、隐藏的小部件和大小

Posted

技术标签:

【中文标题】Qt 中的样式表、隐藏的小部件和大小【英文标题】:Stylesheets, widgets hidden and sizes in Qt 【发布时间】:2014-02-14 11:50:29 【问题描述】:

样式表有一个大问题。

如果您通过样式表通过将最大值和最小值设置为相同(固定大小)或其他方式来设置大小,然后您尝试在小部件上使用 size() 获取它们,如果小部件从未显示你得到的尺寸很奇怪。

但您也无法从样式表中获取它们,因此您必须在调整大小或获取位置之前显示所有小部件

就我而言,我从一个窗口开始。但此窗口下的小部件稍后会出现,并且它们必须定位在正确的位置才能出现。我有浮动小部件,它们没有集成为 QMainWindow 的子级,所以我手动移动它们并定位它们......但是如果我不知道它们是怎么做的,我该怎么做?

你知道任何其他方法来获取存储在样式表中的尺寸吗?

【问题讨论】:

如果解决方案是一个不带参数的单一方法调用,我想这不是一个大问题 :) 它可能是文档或 PEBKAC 的问题,但不是带有样式表:) 样式表文档肯定是一个非常糟糕的信息来源。对我来说,猜测这些事情有时是一场噩梦。关于那个函数调用,我从来没有见过它写在任何地方......所以我必须阅读文档,从来没有见过它!让我检查一下。 这是什么平台(操作系统、编译器),Qt 的具体版本是什么,configure 有哪些选项?我真的很难复制它。 Windows 64Bit,Visual Studio 2008(哪个编译器?O_o)。 Qt4.7. 现在您的问题可能会被关闭,因为它要么无法复制,要么您没有提供足够的详细信息(如在一个独立的最小测试用例中显示它不起作用)。如果没有代码可以看到,这里真的没有人可以帮助你。 【参考方案1】:

目前我知道的解决方案有以下三种:

    润色小部件:致电widget->ensurePolished()

    通过样式润色小部件:调用qApp->style()->polish(widget)

    在显示之前将发布到小部件的事件发送到小部件:QCoreApplication::sendPostedEvents(widget, 0)。使用 Qt 5,您不需要第二个参数,因为它现在的默认值为 0。

解决您的问题的另一种方法是根本不编写任何同步代码。要在第一次显示时布置***小部件:

    在小部件上安装事件过滤器。

    当 show 事件到达小部件时:

      从小部件中卸载事件过滤器。

      传递所有窗口的事件,直到一个都没有:

      while (widget->d_ptr->postedEvents)
        QCoreApplication::sendPostedEvents(widget, 0);
      

      您现在可以确保小部件可见且大小正确。

      使用小部件的几何图形并移动它。如果您需要来自所有小部件的信息来做出决定,请将其存储在某种数据结构中,并仅在所有小部件都存在时进行处理。

如果您希望防止在错误位置临时显示小部件,您可能希望改为对调整大小事件采取行动。布局和样式系统将适当调整***小部件的大小以适合其内容。仅当从对 sendPostedEvents 的调用返回时不再为该对象传递事件时,您才应卸载事件过滤器并处理最新的几何图形。

以下演示了强制抛光方法,在 Qt 4.8.5 和 5.2.0 下均有效。我已经在 OS X 上的 64 位版本和 Windows 上的 32 位版本上对其进行了测试。

请注意,l1l2 均未显示,但它们都报告了正确的大小。显示l3,但显示前查询时,报错大小。

#include <QApplication>
#include <QLabel>
#include <QStyle>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    QString style("QLabel  min-height:100px; max-height:100px; min-width: 300px; max-width:300px ");
    a.setStyleSheet(style);
    QLabel l1, l2, l3;
    l1.ensurePolished(); // equivalent first/second methods
    QCoreApplication::sendPostedEvents(&l2, 0); // third method
    l3.setText(QString("l1: %1 x %2 l2: %3 x %4 l3: %5 x %6")
               .arg(l1.width()).arg(l1.height())
               .arg(l2.width()).arg(l2.height())
               .arg(l3.width()).arg(l3.height()));
    l3.setAlignment(Qt::AlignCenter);
    l3.show();
    return a.exec();

【讨论】:

谢谢你的好回答。我不知道这个功能。但对我不起作用。样式表是在创建 UI 之前分配的。然后在创建隐藏小部件后,我输出大小(它很大)。然后我使用该功能。大小保持不变。然后在显示小部件后,它会按照样式表的指示变小。不要为我工作。 事实上,正如文档所说:“QWidget 在它完全构建之后但在它第一次显示之前调用这个函数”。所以,它是默认调用的。 @darkgaze 您误解了文档所说的内容。在这种情况下,Qt 可以在两次情况下使用小部件做重要的事情:在构造时,以及在您调用 show() 时。它是单线程代码,当你调用size() 时不会为你做任何事情!因此,该函数只能在您调用show() 时调用,但在它变得可见之前show() 在小部件可见之前做了很多事情。文档的真正意思是:当您致电 show() 时,我们会调用它,但在电子撞击屏幕上的荧光粉之前 :) @darkgaze 好吧,我真的不能为你调试。软件开发中的问题解决需要将其缩小到最小的可重现案例。你应该很容易复制项目并开始扔掉不相关的东西。它应该可以工作,所以你的问题不在这里,它在代码中的其他地方可能与样式表等无关。 @darkgaze 是的。文档中没有任何内容声称setStyleSheet 会立即生效。唯一可以保证的是,之后,当事件循环耗尽事件队列时,设置样式的效果将生效并可见。在 Qt 中,更新显示是从事件循环异步完成的。由于您不能按需绘画,因此样式机制假装可以绘画是没有任何意义的。样式的视觉和非视觉效果设置在同一点,异步从队列中排出相关事件。

以上是关于Qt 中的样式表、隐藏的小部件和大小的主要内容,如果未能解决你的问题,请参考以下文章

通过Qt样式表定制程序外观(比较通俗易懂)

在 Qt 中为整个小部件设置样式表

自定义小部件的 Qt 样式表

如何获取样式表设置的Qt中小部件的字体?

[Qt]如何支持:自定义小部件样式表的按下状态?

qt 样式表基本用法