【问题标题】:Modifying layout in resize event在调整大小事件中修改布局
【发布时间】:2019-05-20 15:47:55
【问题描述】:

PyQt 5.9.2、Python 3.6.6、Windows 10

我想根据容器小部件的当前宽度动态隐藏/显示小部件。如果space 占用不到整个宽度的 10%,按钮“一”被隐藏,则按钮“二”。当用户使容器变大时,按钮会再次显示:“二”,然后是“一”。

这是我的实现的一个非常基本的版本,它大部分都可以工作,但是有一个大问题。我开始调整大小,按钮“One”隐藏,但随后出现了一些约束,容器无法再减小大小。我必须释放鼠标按钮并再次开始该过程以隐藏按钮“Two”。

import sys
from PyQt5 import QtWidgets

form, space, widgets = None, None, None

def resize_event(event):
    if free_space_width() < 0:
        visible_w = [w for w in widgets if w.isVisible()]
        if len(visible_w) > 1:  # do not hide the last one
            for w in visible_w:
                w.hide()
                if free_space_width(w.width()) >= 0:
                    break  # enough space
    else:
        invisible_w = [w for w in widgets if not w.isVisible()]
        for w in reversed(invisible_w):
            if free_space_width(-w.width()) < 0:
                break
            w.show()


def free_space_width(shift=0):
    "Free space should be at least 10% of the bar width"
    return space.width() + shift - 0.1 * form.width()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    form = QtWidgets.QWidget()
    layout = QtWidgets.QHBoxLayout(form)
    layout.setSpacing(0)  # for simplicity
    form.resize(480, 64)
    form.resizeEvent = resize_event

    widgets = [QtWidgets.QPushButton("test button %d" % (i + 1), form)
               for i in range(3)]
    for i in widgets:
        layout.addWidget(i)
    space = QtWidgets.QWidget(form)  # stretchable space
    s_policy = space.sizePolicy()
    s_policy.setHorizontalStretch(1)
    space.setSizePolicy(s_policy)
    layout.addWidget(space)

    form.show()
    sys.exit(app.exec_())

【问题讨论】:

  • 使用您提供的代码,我发现它可以正常工作。也就是说,如果我在按住鼠标而不松开鼠标的情况下将鼠标向左移动,小部件会被隐藏,首先是“1”,然后是“2”。
  • @eyllanesc 对我来说只有在两个按钮都被隐藏时开始调整大小时才能正常工作:imgur.com/a/MNGcsQW
  • 在我的情况下,Linux 中的 PyQt5 5.12.2 不会产生这个问题,你能试试更新版本吗?如果它有效,那么问题将是您使用的版本中的错误,如果不是,那么问题可能是 Qt 错误,但仅适用于您的操作系统。

标签: python pyqt pyqt5 qlayout


【解决方案1】:

可以将按钮放在容器小部件中并重新实现minimumSizeHint 方法,这样Qt 就不会尝试自行计算。

def minimumSizeHint(self):
    return QtCore.QSize(150, 30)

更新:我在 custom layoutsetGeometry 函数中实现了显示/隐藏逻辑。

【讨论】:

  • 在我的情况下,执行您的代码后我遇到了同样的问题。我通过setSizeConstraint解决了它。没有mouseRelease,小部件可以顺利移动。老实说,我的回答是建议一个解决方案。它可能是徒劳的。你的回答对我的学习很有用,在 SOF 的规则中,我给你第二个 upvode。谢谢。
【解决方案2】:

然后一些约束就位,容器不能缩小尺寸

layout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)

我认为你应该在这样的代码下实现它。

layout = QtWidgets.QHBoxLayout(form)
layout.setSpacing(0)  # for simplicity
layout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)

【讨论】:

  • 谢谢,这给了我一个线索。实际上,我的示例并不完整,因为在我的项目中,按钮位于容器小部件内,该小部件是QFrame 的子类。所以我需要在我的容器类中重新实现minimumSizeHint,让Qt来做其他的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
相关资源
最近更新 更多