gpt4 book ai didi

qt - heightForWidth标签

转载 作者:行者123 更新时间:2023-12-04 20:47:57 25 4
gpt4 key购买 nike

4-5年我需要一个具有以下属性的小部件

  • 显示文字,包括HTML
  • 文本应包裹在几行上
  • 将小部件放置在布局中时,应以使其文本完全适合小部件几何形状的方式调整小部件的高度

  • 应该在布局中使用此子部件,以提供有关布局中其他GUI元素如何工作的一些详细信息,但仅占用最小的空间来显示其内容。

    我以为这很容易-但是每次我回到挑战时,我总是以放弃而告终。

    主要问题是,当实现heightForWidth()并使用带有setHeightForWidth(True)的QSizePolicy时,布局会崩溃。它可以缩小到无限小。显然,这是Qt的错误。

    另一种方法是在发生resizeEvent()时调用updateGeometry(),并使用与宽度相关的高度来调用setFixedHeight(h)。但这也会引起一些奇怪的布局行为。

    如果有人对如何解决此问题有任何好的建议,请告诉我。

    下面,我包含一个片段,该片段再现了布局调整大小的行为。

    此致,

    狂人
    import sys
    from PyQt4 import QtCore, QtGui

    class Square(QtGui.QLabel):
    def __init__(self, parent=None):
    QtGui.QLabel.__init__(self, parent)
    self.setAutoFillBackground(True)

    palette = QtGui.QPalette()
    palette.setColor(QtGui.QPalette.Window, QtGui.QColor('red'))
    self.setPalette(palette)

    policy = self.sizePolicy()
    policy.setHeightForWidth(True)
    self.setSizePolicy(policy)

    def sizeHint(self):
    return QtCore.QSize(128, 128)

    def heightForWidth(self, width):
    return width

    class Widget(QtGui.QWidget):
    def __init__(self, parent=None):
    # Call base class constructor
    QtGui.QWidget.__init__(self, parent)

    # Add a layout
    layout = QtGui.QVBoxLayout()
    self.setLayout(layout)

    # Add Square
    label = Square()
    layout.addWidget(label)

    spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
    layout.addItem(spacerItem)

    # Some dummy button
    self._push_button = QtGui.QPushButton('Press me')
    layout.addWidget(self._push_button)

    if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)

    widget = Widget()
    widget.show()

    sys.exit(app.exec_())

    最佳答案

    我发现这非常成问题。我认为问题的核心如下:

  • Qt布局通常分配给我们可以称为父窗口小部件的窗口小部件(使用parentwidget->setLayout(layout))。
  • 布局向其子小部件(或子布局)询问其大小首选项(最小大小,大小提示[首选大小]和最大大小)。这是通过QLayoutItem派生的类(例如QWidgetItem)以稍微复杂的方式完成的。
  • 宽度为高度(HFW)的小部件(具有hasHeightForWidth() == true并提供int heightForWidth(int width)的部件)描述布局约束的能力有限,因为它们可以提供minimumSizeHint()sizeHint()heightForWidth(width)。如有必要,它们还可以调用setMinimumSize()setMaximumSize()之类的函数。但是,大多数Qt布局(例如QVBoxLayoutQHBoxLayoutQGridLayout)在为其父级提供自己的最小/首选/最大大小时,并不需要特别注意heightForWidth(width)结果,因为它们是通过QLayout::minimumSize()QLayout::sizeHint()QLayout::maximumSize()这样做的-不会调用有关布局目标大小的信息(在类似Catch-22的情况下),因此它们无法轻松地向其子级提供width值。
  • 因此,该布局会询问其子级,而无需过多考虑HFW,因此要设置其自身的最小/首选/最大尺寸(可能与其他约束条件一起确定父窗口小部件的尺寸)。
  • 在布局告诉其父级(及其父级等)需要多少空间之后,Qt算出它认为所有内容应该有多大。通过其setGeometry(const QRect& layout_rect)调用布局。现在布局知道它有多大了。它使用child->setGeometry()为其子代分配空间。
  • 但是仅在这一点上才发现布局的最终​​宽度。因此,到目前为止,它无法为其子级提供最终宽度,因此HFW小部件只有在最终布局好之后才能知道其最终宽度。到此时,布局及其父级可能已经被设置为错误的高度(可能太大;可能太小)。
  • http://kdemonkey.blogspot.co.uk/2013/11/understanding-qwidget-layout-flow.html上很好地描述了控件/布局交互。除此之外,您最好查看Qt源代码本身。

  • 因此,如上所述,您看到了两类解决方案,其中大小需要“适本地”限制为所需的大小。

    首先:
  • HFW小部件,例如使用自动换行的QLabel派生的类,或想要固定其长宽比的图像,可以为其最小和最大大小提供合理的值,并提供合理的sizeHint()(即它们想要的大小)。
  • 然后,当他们布置好后,他们(1)截获QWidget::resizeEvent(QResizeEvent* event)以找出其新宽度(例如,从event->size()中); (2)通过自己的heightForWidth()函数计算他们的首选高度; (3)通过setFixedHeight(height)updateGeometry()强制其高度。
  • 这倾向于合理地工作,除了任何想要使其尺寸与此类HFW小部件匹配的父小部件都必须做相同的事情,例如拦截resizeEvent,如果父窗口小部件的布局带有hasHeightForWidth() == true,则执行setFixedHeight(layout->heightForWidth(width())); updateGeometry();之类的操作。
  • 导致麻烦,因为您必须在很长一段时间的 parent 中修改可能任意的窗口小部件。
  • 它也可能导致大量重绘,这可能会很慢并导致视觉闪烁。

  • 第二:
  • 重写布局。
  • 我发现的最好的方法是让布局在假设某种标准矩形的情况下计算其子代的几何形状(Qt本身在绘制布局时通常以640x480开始);根据该草图提供高度信息;然后,在调用setGeometry()时,如果所得的高度(基于潜在的新宽度)与先前发布的布局不匹配,请通过调用parent->setFixedHeight()进行重新约束。
  • 这允许您使用任意窗口小部件,并且HFW小部件仅需要支持hasHeightForWidth()heightForWidth()才能具有新的布局(及其父窗口小部件,以及使用此机制的任何祖先布局)来调整其高度。
  • 它会导致一些重绘,但通常不会太多,因为它是按每个布局而不是每个小部件发生的。

  • 我已将C++代码放在 http://egret.psychol.cam.ac.uk/code/2017_01_16_qt_height_for_width/中,用于以下布局:
  • BoxLayoutHfwVBoxLayoutHfwHBoxLayoutHfw-替代QBoxLayout等。
  • GridLayoutHfw-替代QGridLayout
  • FlowLayoutHfw-替换Qt的FlowLayout(http://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html)。

  • 和以下小部件:
  • AspectRatioPixmapLabel-图像保持其长宽比;
  • LabelWordWrapWide-换行标签,试图在换行之前使用尽可能多的水平空间。
  • VerticalScrollArea-顾名思义,是一个垂直滚动区域,但是干净地支持宽度宽度。

  • ...加上一些基础结构代码( #define等),这些代码应使布局恢复到等效的Qt行为,以及一些支持文件(包括 gui_defines.hlayouts.h,这些布局文件使布局和基础小部件的选择取决于您在这方面的偏好) )。

    我尚未成功解决的一个残留问题是,我认为 QLabelheightForWidth()在某些情况下似乎会用样式表返回稍微错误的值(略微高估了其空间要求)。我怀疑问题出在 QLabelPrivate::sizeForWidth中,但是我只是通过计算一些样式表边框来解决这个问题。仍然不太正确,但是高估(导致空白)比低估(导致裁剪)更好。

    关于qt - heightForWidth标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14238138/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com