QLayout 和离散小部件表示 - 如何?

QLayout and discrete widget representation - how to?

例如,我们在 QMainWindow 中有 QHBoxLayout。

让我们在上面的布局中设置小部件。

但是 (!) 很少有小部件具有离散的视觉表示。 换句话说,它们几乎没有依赖可用的状态 space。

例如:

  1. 如果可用的太多 space - 它必须看起来像大图片 + 一些文字
  2. 如果有可用的最小 space - 它必须看起来像小图像
  3. 如果只有极少可用 space - 它必须看起来像按钮 + 标签
  4. 等...

因此,当用户更改主要 window 大小时,我们的 "dynamic" 小部件必须根据可用 space.

显示自己的表示

在Qt中如何实现?

UPD:Microsoft 功能区界面中最接近的行为

UPD2:下面 gif 中出现的最接近 QML 的行为(window 部分由用户调整大小)

UPD3:更复杂的示例 - 菜单面板中的每个面板都会更改内容元素视图和计数,具体取决于可用 space

对此没有灵丹妙药。您需要实施 events/actions 以在调整容器大小时采取。它可以根据您的需要简单或复杂。有几种不同的方法可以实际实施它,具体取决于所涉及的复杂性和范围(它只是几个项目?整个 UI?等等...)。

这是一个非常基本(粗略但有效)的示例,它将工具栏移动到与另一个工具栏在同一行(对于更宽的 window)或移动到它自己的行(对于更窄的 [=36] =]). MdiChild 在这种情况下是一个 QWidget 实现,显然,它包含其他小部件并管理它们的布局。

void MdiChild::resizeEvent(QResizeEvent * event)
{
  QWidget::resizeEvent(event);
  if (size().width() > ui->topToolbarLayout->sizeHint().width() + ui->botToolbarLayout->sizeHint().width() + 30) {
    ui->botToolbarLayout->removeWidget(modelsToolbar);
    ui->topToolbarLayout->insertWidget(1, modelsToolbar);
  }
  else {
    ui->topToolbarLayout->removeWidget(modelsToolbar);
    ui->botToolbarLayout->insertWidget(0, modelsToolbar);
  }
}

如您所见,它必须考虑容器大小,最直接的方法是 QWidget::resizeEvent()。你可以在这里做任何你想做的事...将文本按钮更改为图标,hide/show/move 东西...随便什么。

您当然可以将 signals/slots 连接到包含的小部件,而不是处理容器中的视觉变化...例如。来自 resizeEvent() 处理程序的自定义信号 emit availableSizeChanged(QSize size) connect()ed 到包含的小部件。

您可能会发现 QStateMachine 可以方便地以正式方式维护视觉状态(这就是 QML 用于它的 state[s] 属性 和过渡系统)。

您也可以按照其他人的建议实施自己的 QLayout。尽管问题本身的范围表明您可能不需要。这个问题很笼统恕我直言。提供的两个示例在复杂性方面存在巨大差异。

对于这个答案,我将使用 Qt 等效术语,而不是官方的 MS Ribbon 术语。

概述

您实际上正在查看多种布局,其模式如下:

QToolbar
| (Layout)
+--> QGroupBox/QToolButton
|     | (Layout)
|     +----->Button
|     +----->Button
+--> QGroupBox/QToolButton

模式

让我们从 开始 填充的 QGroupBox 有助于将我们的按钮分组。

考虑到我们的组框可能包含 我们的动态 QToolButton 和常规小部件。当可用space收缩时,布局:

  • 计算固定大小的小部件所需的最小 space 和没有固定大小策略的小部件的 minimumSizeHint() 值。
  • 根据每个小部件的增长策略分配剩余 space。
  • 但是,我们的动态工具按钮 可能会也可能不会 更改大小,具体取决于可用的 space。
  • 现在我们必须开始检查布局的子项是否是动态的,使用 qobject_cast
  • 当我们找到一个动态按钮时,我们必须判断它是否可以收缩。如果是,我们缓存这个和它的首选,更小的大小。
  • 如果要缩小,我们必须重新计算最小尺寸。
  • 然后我们必须继续前进,希望在调整大小时缩小按钮不会导致任何棘手的决胜局。
  • 决胜局:如果两个按钮可以折叠成更小的尺寸,哪个先出现?我们也必须考虑 that。此外,MS 使用三排按钮。从Qt::ToolButtonTextBesideIconQt::ToolButtonIconOnly不能崩一个,得崩一组三个
  • 三个水平按钮可以折叠成三个垂直按钮。这也需要计算和缓存。

还有希望。

我们可以通过使每个容器能够容纳动态工具按钮来进行简化。这样我们就不必处​​理像固定大小的小部件这样棘手的问题,我们只需要处理一种类型的小部件。

Microsoft 也帮助我们实现了此行为。通过经验观察,您可以了解到很多关于布局和子部件的行为约束的信息。群体何时崩溃?如果一个组崩溃了,其他组是否会扩展以占据 space? (顺便说一句,答案是否定的。)按钮折叠时如何组合在一起?它们的折叠和展开方式(对其展开和折叠行为的约束)是否有些特殊?

Qt 还实现了几种布局,供我们研究和了解它们的工作原理以及它们的不同之处。 QGridLayout 是一个很有前途的基础,特别是如果您做一些数学运算来动态更改小部件的行跨度(这是为了在按钮从垂直布局折叠为一组三个水平按钮时对按钮进行分组)。

总结

完全回答您的问题过于宽泛,无法成为 SO 的主题,但我希望此信息能指导您前往需要去的地方。