QT:在运行时更改选项卡遍历顺序?

时间:2013-01-21 13:46:21

标签: qt user-interface tab-ordering

你或许可以说我对QT很新......

我的程序在QGridLayout中包含一个包含多个小部件的窗口。其中一些小部件本身具有布局和子小部件。按Tab键按照我预期的方式移动焦点,按照我创建小部件的顺序。

当窗口小部件更改内容时会出现问题(我通过删除所有子窗口小部件然后构建新窗口小部件来实现。)如果我这样做,新窗口小部件将移动到选项卡链的末尾(这表明我, Tab键顺序对于窗口来说是全局的)。我曾尝试使用QWidget :: setTabOrder()对所有小部件进行重新排序(我尝试了两种方法,仅为主窗口的竞争设置Tab键顺序,并为子级设置它)但实际顺序不会改变。我通过在小部件的竞争发生变化并将其连接到我的主窗口上的插槽时发出信号来完成此操作。 我想我理解setTabOrder()函数的工作方式。我做了类似的事情:

QWidget* a = firstWidget;
QWidget* b = secondWidget;
QWidget::setTabOrder(a,b);
for (int i = 0; i < widgets.size(); ++i) {
  a = b;
  b = widgets[i];
  QWidget::setTabOrder(a,b);
}

更改标签顺序时,有什么特别之处吗?

我还尝试重新实现focusNextPrevChild(bool next)和focusInEvent(QFocusEvent * e)类似于此站点上可以找到的内容。 1

我设法将标签顺序弄得更像这样......这种方法是否朝着正确的方向迈出了一步?

我很抱歉,如果这是一件我想错过的简单的事情,但我现在已经挣扎了一段时间,我找不到解决方案。 非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,并使用评论中提供的Tim Meyer信息解决了这个问题。

Tab顺序不是分层的 - 在不接受焦点的父窗口小部件上调用setTabOrder不会导致焦点传递给子节点。您需要从窗口小部件中获取适当的子项并在其上设置顺序

在我的例子中,动态构造的QTreeWidget包含可编辑的小部件,我需要重置setTabOrder以解决无序创建的小部件。

以下代码是(大多数)实现

// Perform a depth-first gather of the child widgets of this item
void gatherTabWidgets( QObject* item, QWidgetList& tabWidgets )
{
  if (item->isWidgetType())
  {
    QWidget* itemWidget = static_cast<QWidget*>(item);
    if (itemWidget->focusPolicy() & Qt::TabFocus)
      tabWidgets.push_back( itemWidget );
  }
  const QObjectList& children = item->children();
  for (QObjectList::const_iterator itr = children.begin(); itr != children.end(); itr++)
  {
    gatherTabWidgets( const_cast<QObject*>(*itr), tabWidgets );
  }
}

// Perform a depth-first gather of the child items widgets;
void gatherTabWidgets( QTreeWidgetItem* item, QWidgetList& tabWidgets )
{
  QWidget* itemWidget = fetchWidgetForItem( item );
  gatherTabWidgets( itemWidget, tabWidgets );

  for (int i = 0; i < item->childCount(); i++)
  {
    gatherTabWidgets( item->child( i ), tabWidgets );
  }
}

void VETreeWidget::sortTree()
{
  // Ensure ordering is maintained.
  sortItems( 0, Qt::AscendingOrder );

  // Once the items have been re-ordered, re-create the tab ordering
  QTreeWidgetItem* baseItem = topLevelItem( 0 );
  QWidgetList tabWidgets;
  gatherTabWidgets( baseItem, tabWidgets );

  if (!tabWidgets.empty())
  {
    QWidget* lastWidget = tabWidgets.first();
    // Connect this treeview to the first widget.  This ensures
    // if the treeview is tabbed-to, it will tab to the correct sub-widget
    setTabOrder( this, lastWidget );
    for (QWidgetList::iterator itr = tabWidgets.begin() + 1; itr != tabWidgets.end(); itr++)
    {
      setTabOrder( lastWidget, *itr );
      lastWidget = *itr;
    }
  }
}