是什么让 Qt 小部件及其布局表现正常(就其大小而言)?

发布于 2024-12-01 04:14:17 字数 2181 浏览 4 评论 0原文

我在使用 Qt 时遇到了各种大小问题。 不会按预期布局。)

我正在创建自己的小部件并使用不同的布局(通常,我需要自己的小部件才能使它们正常工作,而无需在“强大的”默认布局上花费数小时......这 尽管使用小部件及其布局完成,但它无法正常工作。除非我调用 widget->resize(1, 1); ,否则尺寸永远不会正确设置,这最终会强制“调整大小”并使小部件看起来正确(即重新计算几何形状)。 updateGeometry() 调用无效。

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

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

制作小部件和小部件需要调用的最少函数是什么?它的布局立即起作用吗?

谢谢。 亚历克西斯

P.S.我尝试实现 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() 没有触发相同的效果......

I'm having all sorts of size problems with Qt. I am creating my own widgets and using different layouts (generally, I need my own to make them work properly without spending hours on the "powerful" default layouts... which don't lay things out as intended.)

Once I'm done with a widget and its layout though, it doesn't work right. The size is never getting set properly unless I call widget->resize(1, 1); which finally forces a "resize" and makes the widget look correct (i.e. recompute the geometry.) Even the updateGeometry() call has no effect.

This is a dreadful problem when the resize() needs to be called on the parent widget (yuck!) and from what I'm reading should not be necessary were the layouts properly programmed.

Is there a sample that works and is not several thousand of lines long, or does Qt require several thousand lines to make anything work perfectly, even the simplest widget?

What are the minimal functions to be called to make a widget & its layout work at once?

Thank you.
Alexis

P.S. I tried to implement the sizeHint(), minimumSize(), maximumSize(), others that I'm missing? I was hoping that would be enough. Obviously, I also implement the setGeometry() on the layout to resize the children appropriately.

--- addition 1

There is a sample image with a layout that clearly isn't available as is in Qt. The positioning, functions, and colors of the different keys is XML driven and works for any keyboard in the world.

On screen keyboard

(note, this sample doesn't show the Enter key displayed on two rows and wider below than at the top; more or less, not doable at all with the regular layouts; of course, it works with my version.)

--- clarification

I'm not too sure how to describe the problem better. I was thinking to write a test widget next to see how I can reproduce the problem and then post that and eventually fix it. 8-)

The default layout function that the internal Qt layouts make use of require a lot of coding. I would like to avoid having to copy/paste all of that because for maintenance, it makes it close to impossible.

--- today's findings

As I needed to tweak one of the widgets, I decided to add a VBoxLayout and make it work.

I actually found the problem... One of the widgets in my tree is a QScrollArea and that sizeHint() returns (-1, -1). Not exactly what I'd expect but... whatever you put inside that widget has better know how to compute its width and height or else... it fails.

Looking at the code closely, I could actually compute the width by using the widest width found. Once I used that, the widget would appear (and it actually resizes itself as things change in the list, kinda cool.)

This being said, my earlier comment about having a tree of widgets that auto-resize themselves stands. From the root up to the parents of the leaves in your tree, all of those widgets will need a valid layout. Once I added one in the top widget it resized itself and its children properly (well... in my case up to the QScrollArea, the rest required a bottom to top resizing. Funny how that works!)

--- ah! ha! moment (or: what you find reading the implementation code!)

Today I bumped in another problem which just needed the correct call... I just couldn't find anything worth it in the documentation.

All the objects have a layout now, but a certain parent would not resize properly. Plain simple.

I had a call to the parent as following:

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

Yeah. The docs says that's what you have to do. Nothing happens at all with that call. No idea what it's supposed to do, I did not look at that function. It never did anything for me anyway.

So... I looked at the layout to try to understand how it would send the info up/down. I did not see much except for one interesting comment:

// will trigger resize

This is said of the SetFixedSize mode. To reach that function you need to make the layout for update. Ah! Yes... the layout, not the parent widget... let's try that instead:

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

And voila! It resizes correctly in all cases I have. Quite incredible that the widget updateGeometry() doesn't trigger the same effect...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

输什么也不输骨气 2024-12-08 04:14:17

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

我看到两个选项,两者在某种程度上都更好:

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

第一个选择可能更好。然后,您的键可以由 QGraphicsSimpleTextItem 或什至 QGraphicsSvgItem。它还提供了许多标准布局,或者您可以选择编写您的自己的布局。默认情况下,您可以使用 keyPressEventmouseReleaseEvent 响应用户交互。

我强烈建议您查看 QGraphicsView 示例 来了解一下你能做什么。

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

Although it's possible to do what you want it sounds like the problems you are having are because you're using Qt in a way that it's not meant to be used. Why do you need separate widgets for each key represented on the keyboard?

I see two options, both of which are better in some way:

  1. Use QGraphicsScene and QGraphicsView.
  2. A single custom widget that uses custom drawing to display the keyboard (and likely uses hover for hints).

The first option is probably better. Your keys could then be represented by QGraphicsSimpleTextItem's or even a QGraphicsSvgItem. It also provides a number of standard layouts or you could choose to write your own layout. By default you can use the keyPressEvent or mouseReleaseEvent to respond to user interactions.

I'd highly recommend you take a look at the QGraphicsView examples to get an idea what you can do.

If you go the second route you'll need to record the different key locations so you can respond accordingly as the user moves the mouse around, clicks, etc.

┼── 2024-12-08 04:14:17

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

在此处输入图像描述

在此处输入图像描述

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

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

This won't help you with your immediate issue but I wanted to show you a keyboard I made using standard layouts and buttons. It's not perfect and it still won't help you with an enter key that spans two rows but it's not bad. It's resizable too by resizing the window, although I'm not sure if that will be apparent from the images below as SO may be scaling them. (you can view the actual images by opening them in their own tab)

enter image description here

enter image description here

Anyway, this was done using only Qt Designer with no manual coding. It consists of a top level vertical layout with 5 horizontal layouts in it. The buttons are then inserted into one of the 5 horizontal layouts. The size of the keys can be controlled by setting the horizontal and vertical size policies to "ignored" for most of the buttons and then horizontal "minimum" for buttons that you want to be wider. Things can be tweaked by setting min and max size restrictions to buttons. When resized, the buttons will not maintain their relative proportions though, that would probably take some custom programming.

The styling in your example could be approximated pretty well using css style sheets and background images. Still not a minor effort but you should be able to get most of the way there without custom layouts and buttons.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文