Qt FlowLayout 示例 - 如何在布局更改时调用 sizeHint?
Qt FlowLayout example - how to get sizeHint to be called when layout changes?
我想在一个布局中排列一堆 QPushButton,这样它们就可以水平环绕(就像文本一样)。我正在尝试在 PySide2 中使用 Qt 示例 FlowLayout。
我发布了一个简单的例子revision 2 here
(这是基于官方的例子here,所以我很不安,它不能很好地工作。)
具体来说,当 window 足够大时效果很好:
但不会阻止 window 缩小,而 VBoxLayout 或 GridLayout 会:
我认为最小尺寸应该取决于当前宽度。这应该是最小尺寸:
这也应该如此:
如何获取布局以防止其父级缩小到看不到其内容?
sizeHint() 和 minimumSize() 总是 return 单个项目的大小,我认为这是问题所在。但是,如果我重写它们以考虑当前布局宽度的所有项目,那没关系,因为当我创建和填充布局时,两者只被调用一次。
到目前为止,我最好的想法是从 heightForWidth() 调用 update(),大致如下:
def heightForWidth(self, width):
oldWidth = self.geometry().width() - 2 * self.contentsMargins().top()
oldHeight = self.doLayout(QtCore.QRect(0, 0, oldWidth, 0), True)
height = self.doLayout(QtCore.QRect(0, 0, width, 0), True)
print 'heightForWidth', width, oldWidth, height, oldHeight
if height != oldHeight:
self.update()
return height
更改了 minimumSize 和 doLayout 的完整样本是 revision 3。
它有时会起作用,但有几个问题:
首次创建布局时,会不断调用 update()。我认为对 update() 的调用会触发对 heightForWidth() 的调用,并且由于某种原因,传入的宽度不接近我计算的 "oldWidth",直到我调整 window 的大小,即使是单个像素.
一旦我调整 window 的大小,对 heightForWidth() 的调用就完全停止,并且 minimumSize() 也停止被调用,我无法再调整 window 的大小小于上次计算的尺寸。我不知道为什么。
(不太重要)self.geometry().width() - 2 * self.contentsMargins().top()
不会 return 最后传递给 heightForWidth 的宽度(即使 top/bottom/left/right 边距相同),尽管我从示例中的其他代码中获取它。这通常无关紧要,但在某些宽度下,它会导致对 update()
的一系列调用
我想我做错了。可以做对吗?
您只能修改 setGeometry()
和 minimumSize()
函数。我在 C++ 中工作,但它很容易修改为 Python。
首先,我更改了 minimumSize()
返回的 QSize 以考虑布局的当前大小,随后设置返回的 QSize 的高度。然后,我在 setGeometry()
中调用 update()
以强制布局重新检查 sizeHint()
。以下是代码示例。
QSize FlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem *item : qAsConst(itemList))
{
size = size.expandedTo(item->minimumSize());
}
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
// ADDED CODE **************************************
auto layoutSize = this->contentsRect();
size.setHeight(heightForWidth(layoutSize.width()));
// *************************************************
return size;
}
void FlowLayout::setGeometry(const QRect &rect)
{
// ADDED CODE ************************************
update();
// ***********************************************
QLayout::setGeometry(rect);
doLayout(rect, false);
}
希望对您有所帮助。
我现在已将 original/official 示例移植到 PySide2,它无需更改即可运行。我不确定之前是什么阻止了它工作。
我想在一个布局中排列一堆 QPushButton,这样它们就可以水平环绕(就像文本一样)。我正在尝试在 PySide2 中使用 Qt 示例 FlowLayout。
我发布了一个简单的例子revision 2 here
(这是基于官方的例子here,所以我很不安,它不能很好地工作。)
具体来说,当 window 足够大时效果很好:
但不会阻止 window 缩小,而 VBoxLayout 或 GridLayout 会:
我认为最小尺寸应该取决于当前宽度。这应该是最小尺寸:
这也应该如此:
如何获取布局以防止其父级缩小到看不到其内容?
sizeHint() 和 minimumSize() 总是 return 单个项目的大小,我认为这是问题所在。但是,如果我重写它们以考虑当前布局宽度的所有项目,那没关系,因为当我创建和填充布局时,两者只被调用一次。
到目前为止,我最好的想法是从 heightForWidth() 调用 update(),大致如下:
def heightForWidth(self, width):
oldWidth = self.geometry().width() - 2 * self.contentsMargins().top()
oldHeight = self.doLayout(QtCore.QRect(0, 0, oldWidth, 0), True)
height = self.doLayout(QtCore.QRect(0, 0, width, 0), True)
print 'heightForWidth', width, oldWidth, height, oldHeight
if height != oldHeight:
self.update()
return height
更改了 minimumSize 和 doLayout 的完整样本是 revision 3。 它有时会起作用,但有几个问题:
首次创建布局时,会不断调用 update()。我认为对 update() 的调用会触发对 heightForWidth() 的调用,并且由于某种原因,传入的宽度不接近我计算的 "oldWidth",直到我调整 window 的大小,即使是单个像素.
一旦我调整 window 的大小,对 heightForWidth() 的调用就完全停止,并且 minimumSize() 也停止被调用,我无法再调整 window 的大小小于上次计算的尺寸。我不知道为什么。
(不太重要)
self.geometry().width() - 2 * self.contentsMargins().top()
不会 return 最后传递给 heightForWidth 的宽度(即使 top/bottom/left/right 边距相同),尽管我从示例中的其他代码中获取它。这通常无关紧要,但在某些宽度下,它会导致对 update() 的一系列调用
我想我做错了。可以做对吗?
您只能修改 setGeometry()
和 minimumSize()
函数。我在 C++ 中工作,但它很容易修改为 Python。
首先,我更改了 minimumSize()
返回的 QSize 以考虑布局的当前大小,随后设置返回的 QSize 的高度。然后,我在 setGeometry()
中调用 update()
以强制布局重新检查 sizeHint()
。以下是代码示例。
QSize FlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem *item : qAsConst(itemList))
{
size = size.expandedTo(item->minimumSize());
}
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
// ADDED CODE **************************************
auto layoutSize = this->contentsRect();
size.setHeight(heightForWidth(layoutSize.width()));
// *************************************************
return size;
}
void FlowLayout::setGeometry(const QRect &rect)
{
// ADDED CODE ************************************
update();
// ***********************************************
QLayout::setGeometry(rect);
doLayout(rect, false);
}
希望对您有所帮助。
我现在已将 original/official 示例移植到 PySide2,它无需更改即可运行。我不确定之前是什么阻止了它工作。