QToolBar + QToolExtension без QMainWindow
От: Мёртвый Даун Россия  
Дата: 05.07.21 17:25
Оценка:
Короче неделю сижу уже, закис. В одном из наших проектов такая бага обнаружилась.

Есть такая кнопка на тулбаре справа ">>", появляется когда начинаешь уменьшать окно/тулбар и кнопки не влазят. Я не помню как она в WinAPI/MFC называется, в Qt — это QToolExtension button. Находится в сорцах Qt в приватных заголовках. Так вот она перестала работать, мелочь, но неприятно.



Как выяснилось, отломалось когда выкинули QMainWindow, заменив своим от QWidget. И действительно, там свой layout для тулбара, анимация обеспечивается в qtoolbarlayout.cpp, который тоже в приватных заголовках. Ну и также отломалось потому что на тулбаре свои виджеты, а не просто action'ы. И если не QMainWindow, то при нажатии на эту кнопку ">>" будет просто обычное popup меню в случае своих. Т.е. хочется чтобы на тулбаре были свои виджеты, и при нажатии на кнопку открывалось popup меню, в котором были виджеты которые не влезли. Ок.

В доках нашлось такое:

When a toolbar is resized in such a way that it is too small to
show all the items it contains, an extension button will appear as
the last item in the toolbar. Pressing the extension button will
pop up a menu containing the items that do not currently fit in
the toolbar.
When a QToolBar is not a child of a QMainWindow, it loses the ability
to populate the extension pop up with widgets added to the toolbar using
addWidget(). Please use widget actions created by inheriting QWidgetAction
and implementing QWidgetAction::createWidget() instead.


Ну т.е. QWidgetAction — это такой же QAction, но только умеет визуализироваться.

И действительно, если делать так, то всё работает:

class MyWidget : public QWidget {
...
}

class MyWidgetAction : public QWidgetAction {
    Q_OBJECT
public:
    MyWidgetAction(QObject *parent) : QWidgetAction(parent) {}

protected:
    QWidget *createWidget(QWidget *parent) {
        auto *widget = new MyWidget();
        // создали наш виджет, настроили, этот метод потом будет вызван в тулбаре при добавлении action'а.
        
        return widget;
    }

    void deleteWidget(QWidget *widget) { QWidgetAction::deleteWidget(widget); }
};


Всё бы ничего, но хочется создавать свой виджет за пределами QWidgetAction. И вот как раз эта шляпа перестает работать, не понятно почему. Т.е. хочется вот так (воспроизводится на самом простом тестовом проекте),

class MyWidgetAction : public QWidgetAction {
    Q_OBJECT
public:
    explicit MyWidgetAction(QWidget *widget, QObject *parent) : QWidgetAction(parent), widget_(widget) {}
    ~MyWidgetAction() Q_DECL_OVERRIDE { widget_->setParent(Q_NULLPTR); }

    QWidget *createWidget(QWidget *parent) Q_DECL_OVERRIDE {
            // widget это всего лишь контейнер для нашего виджета, чтобы положить его на тулбар
            QFrame *widget = new QFrame(parent);
            widget->setMinimumHeight(32);
             //widget_->setParent(widget); // ???
        
            auto layout = new QHBoxLayout();
            layout->setContentsMargins(0, 0, 0, 0);
            layout->setSpacing(0);
            layout->addWidget(widget_.data());

            widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
            widget->setLayout(layout);
            widget->show();
            widget_->show();
            widget->update();

            return widget;
    }
    void deleteWidget(QWidget *widget) Q_DECL_OVERRIDE {
        // Виджет-контейнер тут потом удалится, а наш виджет где-то там потом сам удалится
        widget_->hide();
        widget->layout()->removeWidget(widget_.data());
        widget_->setParent(Q_NULLPTR);

        QWidgetAction::deleteWidget(widget);
    }

private:
    const QScopedPointer<QWidget, QScopedPointerDeleteLater> widget_; // указатель на наш уже созданный виджет где-то за пределами
};

// Используем

// Где-то создали наш виджет, настроили его, еще чота поделали
auto *myWidget = new MyWidget(toolBar);
...
// и добавляем его на тулбар
toolBar->addAction(new MyWidgetAction(myWidget, toolBar));


И усё, на тулбаре пусто. Но зато появляется в popup меню при нажатии на кнопку ">>".

Шо не так?
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Отредактировано 05.07.2021 17:35 Мёртвый Даун . Предыдущая версия . Еще …
Отредактировано 05.07.2021 17:29 Мёртвый Даун . Предыдущая версия .
Отредактировано 05.07.2021 17:26 Мёртвый Даун . Предыдущая версия .
qt toolbar
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.