是啥让 Qt 小部件及其布局正常运行(就其大小而言)?

Posted

技术标签:

【中文标题】是啥让 Qt 小部件及其布局正常运行(就其大小而言)?【英文标题】:What makes a Qt widget and its layout behave properly (in regard to its size)?是什么让 Qt 小部件及其布局正常运行(就其大小而言)? 【发布时间】:2011-08-24 21:40:49 【问题描述】:

我在使用 Qt 时遇到了各种大小问题。我正在创建自己的小部件并使用不同的布局(通常,我需要自己的小部件才能使它们正常工作,而无需花费数小时在“强大”的默认布局上......它不会按预期布局。)

不过,一旦我完成了一个小部件及其布局,它就无法正常工作。除非我调用widget->resize(1, 1);,否则大小永远不会正确设置,这最终会强制“调整大小”并使小部件看起来正确(即重新计算几何形状。)即使updateGeometry() 调用也没有效果。

当需要在父窗口小部件上调用 resize() 时,这是一个可怕的问题(糟糕!),而且从我正在阅读的内容来看,如果布局正确编程,则不需要。

是否有一个可以工作且不长达数千行的示例,或者 Qt 是否需要数千行才能使任何东西完美运行,即使是最简单的小部件?

要使小部件及其布局同时工作,需要调用哪些最小函数?

谢谢。 亚历克西斯

附:我试图实现sizeHint()minimumSize()maximumSize(),还有其他我想念的?我希望这就足够了。显然,我还在布局上实现了setGeometry() 以适当地调整孩子的大小。

---加法1

有一个带有布局的示例图像,显然在 Qt 中不可用。不同按键的位置、功能和颜色是 XML 驱动的,适用于世界上的任何键盘。

(请注意,此示例没有显示 Enter 键显示在两行上,并且下方比顶部更宽;或多或少,在常规布局中根本不可行;当然,它适用于我的版本。)

--- 澄清

我不太确定如何更好地描述这个问题。我正在考虑接下来编写一个测试小部件,以查看如何重现该问题,然后发布并最终修复它。 8-)

内部 Qt 布局使用的默认布局功能需要大量编码。我想避免复制/粘贴所有这些,因为为了维护,这几乎是不可能的。

---今天的发现

由于我需要调整其中一个小部件,我决定添加一个VBoxLayout 并让它工作。

我实际上发现了问题...我的树中的一个小部件是 QScrollArea,而 sizeHint() 返回 (-1, -1)。不完全是我所期望的,但是...无论您放入该小部件中的任何内容,都最好知道如何计算其宽度和高度,否则...它会失败。

仔细查看代码,我实际上可以使用找到的最宽宽度来计算宽度。一旦我使用了它,小部件就会出现(它实际上会随着列表中的事物变化而调整自己的大小,有点酷。)

话虽如此,我之前关于拥有自动调整自身大小的小部件树的评论是站得住脚的。从树的根到叶子的父级,所有这些小部件都需要有效的布局。一旦我在顶部小部件中添加了一个,它就会正确调整自身及其子级的大小(嗯......在我的情况下直到QScrollArea,其余的需要从下到上调整大小。这很有趣!)

——啊!哈!时刻(或:你在阅读实现代码时会发现什么!)

今天我遇到了另一个需要正确调用的问题...我只是在文档中找不到任何值得的东西。

所有对象现在都有一个布局,但是某个父对象无法正确调整大小。很简单。

我给家长打了如下电话:

// changes to the children are changing the geometry
parentWidget()->updateGeometry();

是的。文档说这是你必须做的。那个电话根本没有任何反应。不知道它应该做什么,我没有看那个功能。无论如何,它从来没有为我做任何事情。

所以...我查看了布局,试图了解它如何向上/向下发送信息。除了一条有趣的评论,我没看到太多:

// will trigger resize

这就是SetFixedSize 模式。要达到该功能,您需要进行布局以进行更新。啊!是的......布局,而不是父小部件......让我们尝试一下:

parentWidget()->layout()->update();

瞧!在我拥有的所有情况下,它都会正确调整大小。令人难以置信的是小部件updateGeometry() 不会触发相同的效果...

【问题讨论】:

内置布局系统无法为您完成的任务是什么?当它基本上归结为“我如何让事情发挥作用?”时,很难回答对你有用的问题。 对于 GUI/布局问题,包括带注释的屏幕截图会很有帮助。这里不乏喜欢在有可靠信息时弄清楚事情的人:) 如果您的代码没有问题,那么您可以在 www.ideone.com 上分享它:D @blueskin 我无法分享该代码,不……但我正在考虑创建一个失败的测试用例,以便我可以分享它。也许是因为我缺少每个级别的布局......只有较低的小部件不需要布局,我想如果我们想让它们工作,所有的祖先都需要一个布局。 【参考方案1】:

虽然可以做你想做的事,但听起来你遇到的问题是因为你使用 Qt 的方式并不适合使用它。为什么键盘上的每个键都需要单独的小部件?

我看到了两个选项,它们在某些方面都更好:

    使用QGraphicsScene 和QGraphicsView。 使用自定义绘图来显示键盘的单个自定义小部件(并且可能使用悬停作为提示)。

第一个选项可能更好。然后您的密钥可以由QGraphicsSimpleTextItem 甚至QGraphicsSvgItem 表示。它还提供了许多标准布局,或者您可以选择write your own layout。默认情况下,您可以使用keyPressEvent 或mouseReleaseEvent 来响应用户交互。

我强烈建议您查看 QGraphicsView examples 以了解您可以做什么。

如果您走第二条路线,则需要记录不同的关键位置,以便在用户移动鼠标、点击等时做出相应的响应。

【讨论】:

在这种情况下我是否必须手动渲染所有内容?使用 PushButtons,我可以免费获得渲染和 clicked() 事件......我的键盘也是一个例子,我遇到的问题是在一个列表中,其中布局链因 QScrollArea 而中断(即在 QScrollArea 下方,大小为不受高度限制,我们希望将 QScrollArea 内的小部件调整为尽可能高!但 QScrollArea 必须是合理的大小。)【参考方案2】:

这不会帮助您解决当前的问题,但我想向您展示我使用标准布局和按钮制作的键盘。它并不完美,它仍然无法帮助您使用跨越两行的输入键,但它还不错。它也可以通过调整窗口大小来调整大小,尽管我不确定这是否会从下面的图像中明显看出,因为 SO 可能正在缩放它们。 (您可以通过在自己的标签中打开它们来查看实际图像)

无论如何,这是仅使用 Qt Designer 完成的,无需手动编码。它由一个顶层垂直布局和 5 个水平布局组成。然后将按钮插入 5 个水平布局之一。可以通过将大多数按钮的水平和垂直大小策略设置为“忽略”,然后将您想要更宽的按钮的水平“最小”设置为来控制键的大小。可以通过为按钮设置最小和最大尺寸限制来调整事情。调整大小时,按钮不会保持它们的相对比例,这可能需要一些自定义编程。

使用 css 样式表和背景图像可以很好地近似您示例中的样式。仍然不是一件小事,但您应该能够在没有自定义布局和按钮的情况下完成大部分工作。

【讨论】:

是的。 QSS有很多问题。它仅在创建小部件时进行级联。在那之后,它完全忘记了父母。所以这真的不那么实用。话虽如此,我将 QSS 用于颜色、边框、字体大小、图像......现在,考虑一下,我想知道我的问题是否真的是因为所有祖先都不包含布局。我想我在某处读到过,要使布局正常工作,您在任何地方都需要它们。最后,在我的情况下,键盘可以切换到各种布局。例如,我可以将其更改为 Kania 或法语键盘。

以上是关于是啥让 Qt 小部件及其布局正常运行(就其大小而言)?的主要内容,如果未能解决你的问题,请参考以下文章

更改 Qt 布局中的调整大小行为

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

如果数据大小超过可用内存,是啥让 Spark 快速?

Qt - 如何控制 QLayout 中的小部件大小

如何在 Qt 中制作可展开/可折叠的部分小部件

在 QFileDialog 布局中调整按钮小部件的大小