如何在 Qt 中保持小部件的长宽比?
如何在 Qt 中保持小部件的纵横比以及使小部件居中怎么样?
How is it possible to maintain widgets aspect ratio in Qt and what about centering the widget?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不必实现自己的布局管理器。 您可以继承
QWidget
并重新实现以保持方形。 但是,
heightForWidth()
不适用于 X11 上的顶级窗口,因为显然 X11 协议不支持这一点。 至于居中,可以将Qt::AlignCenter
作为QBoxLayout::addWidget()
的第三个参数或QGridLayout::addWidget()的第五个参数传递
。注意:至少在较新版本的 Qt 中,QWidget 不再具有
heightForWidth
或widthForHeight
(因此它们无法被覆盖),因此setWidthForHeight(true)
或setHeightForHeight(true)
仅对 QGraphicsLayout 的后代有效。You don't have to implement your own layout manager. You can do with inheriting
QWidget
and reimplementingto stay square. However,
heightForWidth()
doesn't work on toplevel windows on X11, since apparently the X11 protocol doesn't support that. As for centering, you can passQt::AlignCenter
as the third parameter ofQBoxLayout::addWidget()
or the fifth parameter ofQGridLayout::addWidget()
.Note: In newer versions of Qt at least, QWidget does not have the
heightForWidth
orwidthForHeight
anymore (so they cannot be overriden), and thereforesetWidthForHeight(true)
orsetHeightForWidth(true)
only have an effect for descendants of QGraphicsLayout.正确的答案是创建自定义布局管理器。 这可以通过子类化 QLayout 来实现。
子类化 QLayout 时要实现的方法
进一步阅读
The right answer is to create your custom layout manager. That is possible by subclassing QLayout.
Methods to implement when subclassing QLayout
Further reading
从
resizeEvent()
内部调用resize()
对我来说从来都没有很好的效果——充其量它会导致闪烁,因为窗口大小调整了两次(就像你所做的那样),在最糟糕的是无限循环。我认为保持固定宽高比的“正确”方法是创建自定义布局。 您只需重写两个方法:
QLayoutItem::hasHeightForWidth()
和QLayoutItem::heightForWidth()
。Calling
resize()
from withinresizeEvent()
has never worked well for me -- at best it will cause flickering as the window is resized twice (as you have), at worst an infinite loop.I think the "correct" way to maintain a fixed aspect ratio is to create a custom layout. You'll have to override just two methods,
QLayoutItem::hasHeightForWidth()
andQLayoutItem::heightForWidth()
.我也试图实现所要求的效果:一个保持固定纵横比同时保持在其分配空间中心的小部件。 起初,我尝试了这个问题的其他答案:
heightForWidth
和hasHeightForWidth
对我来说根本不起作用。我最终创建了一个响应
resizeEvent
< 的自定义小部件/a> 并使用setContentsMargin
来设置边距,使剩余内容区域保持所需的比例。我发现我还必须在两个方向上将小部件的大小策略设置为 QSizePolicy::Ignored 以避免因子小部件的大小请求而导致奇怪的大小调整问题 - 最终结果是我的小部件接受任何大小它的父级分配给它(然后如上所述设置其边距,以在其内容区域中保持所需的宽高比)。
我的代码如下所示:(
显然,此代码是用 Python 编写的,但用 C++ 或您选择的语言表达应该很简单。)
I too was trying to achieve the requested effect: a widget that keeps a fixed aspect ratio while staying centred in its allocated space. At first I tried other answers from this question:
heightForWidth
andhasHeightForWidth
as suggested by marc-mutz-mmutz simply didn't work for me.I ended up creating a custom widget that responds to
resizeEvent
and usessetContentsMargin
to set margins such that the remaining content area keeps the desired ratio.I found I also had to set the widget's size policy to
QSizePolicy::Ignored
in both directions to avoid odd resizing issues resulting from the size requests of child widgets—the end result is that my widget accepts whatever size its parent allocates to it (and then sets its margins as described above to keep the desired aspect ratio in its content area).My code looks like this:
(Obviously, this code is in Python, but it should be straightforward to express in C++ or your language of choice.)
就我而言,覆盖 heightForWidth() 不起作用。 而且,对于某些人来说,获得使用调整大小事件的工作示例可能会有所帮助。
首先子类化qObject来创建过滤器。 有关事件过滤器的更多信息。
然后是eventFilter函数。 它的代码应该在 FilterObject 定义之外定义,以防止出现警告。 感谢这个答案。
然后在主代码中创建 FilterObject 并将其设置为目标对象的 EventFilter 侦听器。 感谢这个答案。
现在过滤器将接收所有 targetWidget 的事件并设置正确的高度调整事件大小。
In my case overriding heightForWidth() doesn't work. And, for someone, it could be helpful to get working example of using resize event.
At first subclass qObject to create filter. More about event filters.
Then eventFilter function. It's code should be defined outside of FilterObject definition to prevent warning. Thanks to this answer.
And then in main code create FilterObject and set it as EventFilter listener to target object. Thanks to this answer.
Now filter will receive all targetWidget's events and set correct height at resize event.