如何平均分配QSplitter的宽度

14

我在调整QSplitter的宽度方面遇到了问题。 我使用Qt Designer准备了UI,现在看起来是这样的:

设计视图:

enter image description here

这是我的对象检查器

enter image description here

我的问题是如何在左右区域中平均分配QSplitter的宽度。 我希望获得以下效果作为初始大小,然后客户可以随意更改。

我想要的效果如下所示:

enter image description here

换句话说,我正在寻找一种方法来指定左侧和右侧区域的分割线的初始比例为窗口宽度的50%/ 50%。 是否有任何选项可以实现这一点?

感谢您的帮助,请原谅,我刚开始学习Qt。

3个回答

35

简短回答

splitter->setSizes(QList<int>({INT_MAX, INT_MAX}));

注意:如果您想使用其他比例,微调部分可能包含必要的信息。

解释

QSpacer?不需要。

在这种情况下,您不需要使用QSpacer。空间占位符的目标是填充所有可用空间。

QSplitter提供了两种方法来指定其子项的大小:

1. QSplitter::setStretchFactor?不适用。

虽然拉伸系数似乎是您希望指定子窗口小部件相对大小的内容,但对于您的情况,它具有缺点,即系数相对于子窗口小部件的初始大小:

stretch 不是有效的拉伸因子;有效的拉伸因子是通过取小部件的初始大小并将其乘以 stretch 来计算的。

因此,将两个子窗口小部件的拉伸系数设置为相同的值(例如1)将不起作用:

splitter->setStretchFactor(0, 1);
splitter->setStretchFactor(1, 1);

2. QSplitter::setSizes?是的。

更好的选择是使用setSizes,因为只有相对大小才有关系:

拆分器窗口部件的总体大小不受影响。 相反,任何多余/缺失的空间都按照大小的相对权重分配给小部件。

因此,可以认为将两个大小都设置为一个将在两个子项之间均匀分配总大小:

splitter->setSizes(QList<int>({1, 1}));

不行,因为你应该考虑到最小尺寸策略会通过用最小尺寸替换太小的值来执行:

控件的大小策略保持不变。也就是说,比相应控件的最小大小提示更小的值将被替换为提示值。

所以,你应该使用一个比你的子控件的最小尺寸大的值,例如可以用 int 表示的最大数,即 INT_MAX

splitter->setSizes(QList<int>({INT_MAX, INT_MAX}));

微调

正如评论中所建议的那样,INT_MAX可能会导致一些溢出问题,这取决于Qt对这些值进行的计算。 如果您想要非等分布比率,可能特别如此。 因此,一个更明智的大值可能是桌面宽度/高度。

// Horizontal splitter
int largeWidth = QGuiApplication::primaryScreen ()->virtualSize ().width ();
splitter->setSizes(QList<int>({largeWidth , largeWidth}));

// Vertical splitter
int largeHeight = QGuiApplication::primaryScreen ()->virtualSize ().height ();
splitter->setSizes(QList<int>({largeHeight , largeHeight}));

更多阅读

大多数情况下,Qt 会为所有小部件提供适当的大小,但微调可能变得非常困难,需要进行一些试验和错误。因此,我想提供一些额外的资源,这些资源可能在使用 Qt 中的布局管理时有用:


1
我不建议在QSplitter大小的上下文中使用INT_MAX。在某些情况下,它可以正常工作,在某些情况下则不能。如果您想最大化一个部分并最小化另一个部分,则使用QList<int>({INT_MAX, 1})将无法起作用。因为它会在qlayoutengine.cpp中调用qGeomCalc,并且有一个“int sumStretch”变量来计算拉伸因子的总和。对于像INT_MAX这样的巨大数字,它可能会溢出并产生错误的结果。 - Vladislav
@Vladislav,你有什么建议吗?如果所有值都设置为INT_MAX,会有问题吗?如果您尝试最大化一部分并最小化另一部分,那么将QSizePolicy :: Policy(分别设置为Maximum/PreferredMinimumExpanding)是否更合适? - m7913d
1
想象一下用于2个小部件的分裂器。如果你设置setSizes({INT_MAX,INT_MAX}),它将分成两个相等的块。如果你设置setSizes({INT_MAX,1}),它也会分成两个相等的块。如果你调用setSizes({99999,1}),它将最大化第一个小部件并将第二个小部件最小化。关于SizePolicy,是更合适的解决方案,但是如果您调用了一次QSplitter :: setSizes()方法,则此后分裂器将不会对SizePolicy更改做出反应。 - Vladislav

6

基于 m7913d

要等比例地分割一个分裂器,使用QSplitter::setSizes,列表中的每个大小应该是相等的。 使用QWidget::minimumSizeHint() 来确定要使用的大小。 对于添加到分裂器的每个小部件,使用其最大宽度(对于水平分裂器)或最大高度(对于垂直分裂器)。

// Example for a horizontal splitter
splitter = new QSplitter(Qt::Horizontal, this);
splitter->addWidget(widgetLeft);
splitter->addWidget(widgetRight);
auto equalWidth = std::max(widgetLeft->minimumSizeHint().width(), 
                           widgetRight->minimumSizeHint().width());
splitter->setSizes({ equalWidth, equalWidth });

// Example for a vertical splitter
splitter = new QSplitter(Qt::Vertical, this);
splitter->addWidget(widgetTop);
splitter->addWidget(widgetBottom);
auto equalHeight = std::max(widgetTop->minimumSizeHint().height(),
                            widgetBottom->minimumSizeHint().height());
splitter->setSizes({ equalHeight, equalHeight });

1
我建议进一步的改变。m7913d的所有观点都很重要。但在我的情况下(Qt5.13.2),我发现设置足够大的尺寸仍然可能导致一些变化。我不知道为什么,但将所有拉伸因子都设置为1,最终表现出了我想要的结果。
另外,请注意,将所有拉伸因子都设置为1,但使用非相等的(但仍足够大以避免最小尺寸约束)大小与setSizes一起使用也可以!例如:
splitter->setStretchFactor(0,1);
splitter->setStretchFactor(1,1);
splitter->setSizes({static_cast<int>(10000 / 1.618), static_cast<int>(10000 - 10000 / 1.618)});

设置黄金分割比例。

请注意,这似乎也不是稳定的,只是更稳定一些。在我的代码中,我不得不容忍相当多的跳跃...不知道为什么Qt解决得如此糟糕。 - IceFire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接