Исправлен порядок вкладок после вставки виджетов в макет в QT

У меня есть пользовательская реализация списка (подкласс QWidget) в QT 5.5. Элементы списка организованы с использованием QVBoxLayout, Во время выполнения, элементы (которые также QWidgets) может быть динамически добавлен и удален из списка в любой позиции макета. Это работает нормально, за исключением одной детали: неправильный порядок табуляции вставляемых фокусируемых элементов. Последний вставленный элемент всегда будет последним в порядке табуляции, даже если он вставлен между двумя другими элементами.

Как я могу исправить порядок табуляции для представления порядка макета? Я уже пробовал перебирать элементы списка и использовать setTabOrder() на каждой соседней паре, без успеха.

Еще несколько подробностей о реализации:

  • Виджеты не добавляются непосредственно в список. Каждый раз, когда должен быть добавлен виджет, вместо него создается и добавляется виджет-посредник, реальный виджет будет переставлен в прокси-сервер (прокси-сервер выполняет некоторые графические операции).
  • QVBoxLayout::insertWidget() используется для вставки прокси-виджетов с последующим вызовом QWidget::show()
  • при удалении элементов элемент будет скрыт, удален из прокси, прокси удален из макета списка и освобожден
  • Фокусируемые виджеты могут быть в любом месте дерева объектов элементов, которые добавляются в список, они не обязательно сами элементы

Обновление: добавлено MCVE!

Следующий минимизированный пример демонстрирует проблему. Для полноты я также включил заголовки, основную функцию и файл.pro. Вы можете безопасно пропустить эти файлы, если вы не хотите воспроизводить проблему, TabOrderTestWindow.cpp является важным.

TabOrderTestWindow.cpp:

#include "TabOrderTestWindow.h"

#include <QVBoxLayout>
#include <QPushButton>

// create a button inside a proxy widget
QWidget* createButtonProxy(const QString& caption, QWidget* parent) {
    QWidget* proxy = new QWidget(parent);
    QPushButton* button = new QPushButton(caption, proxy);
    proxy->setFocusProxy(button);
    return proxy;
}

TabOrderTestWindow::TabOrderTestWindow()
    : QWidget()
{
    setMinimumHeight(200);
    setMinimumWidth(350);

    QVBoxLayout* layout = new QVBoxLayout(this);

    // create and add 3 buttons in order
    QWidget* button1 = createButtonProxy("button 1", this);
    QWidget* button2 = createButtonProxy("button 2", this);
    QWidget* button3 = createButtonProxy("button 3", this);
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);

    // now insert a fourth button in between the others - incorrect tab order!
    QWidget* buttonInbetween = createButtonProxy("button in between", this);
    layout->insertWidget(1, buttonInbetween);

    // attempt to correct tab order - not working, even with focus proxy set...
    setTabOrder(button1, buttonInbetween);
    setTabOrder(buttonInbetween, button2);
}

TabOrderTestWindow.h:

#ifndef TABORDERTESTWINDOW_H
#define TABORDERTESTWINDOW_H

#include <QMainWindow>

class TabOrderTestWindow : public QWidget
{
    Q_OBJECT

public:
    TabOrderTestWindow();
};

#endif // TABORDERTESTWINDOW_H

main.cpp:

#include "TabOrderTestWindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TabOrderTestWindow w;
    w.show();

    return a.exec();
}

TabOrderTest.pro:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TabOrderTest
TEMPLATE = app


SOURCES += main.cpp\
        TabOrderTestWindow.cpp

HEADERS  += TabOrderTestWindow.h

1 ответ

Здесь действительно, кажется, ошибка, поскольку Doc-состояние, о котором будут заботиться прокси фокуса.

Но мы можем заботиться о них сами, используя:

setTabOrder(button1->focusProxy(), buttonInbetween->focusProxy());
setTabOrder(buttonInbetween->focusProxy(), button2->focusProxy());

Похоже, вам нужно сделать то, что должен был сделать Qt для вас.

Другие вопросы по тегам