OK, řešením je resetovat příznaky okna na panelu nástrojů, když je poprvé zobrazen a plovoucí. Sledoval jsem to tak, že jsem viděl, co se stane, když panel nástrojů po přetažení (ale není zapojen do hlavního okna) spadne. (Volá setWindowState()
a vše, co v této situaci udělá, je skrýt panel nástrojů, zavolat updateWindowFlags()
a ukažte jej znovu).
To lze vyřešit z QMainWindow::showEvent()
nebo z eventFilter
nainstalován na QToolBar
. Myslím, že je to jednodušší než předchozí.
AKTUALIZACE :Tento problém ve skutečnosti nastává vždy, když je panel nástrojů poprvé zobrazen, i když ne při spuštění aplikace, např. z nabídky přepnout zobrazení uživatelem po spuštění aplikace. Aktualizoval jsem níže uvedený kód, abych tento problém také vyřešil. A viz poznámky níže o dalším problému s minimalizací hlavního okna.
Přidal jsem to do MainWindow
třídy z MCVE:
protected:
void showEvent(QShowEvent *e) override {
QMainWindow::showEvent(e);
#ifdef Q_OS_LINUX
if (lToolbar->isFloating()
// remove the next condition and the toolsbar will get hidden the 2nd time main window is minimized.
&& lToolbar->windowFlags().testFlag(Qt::X11BypassWindowManagerHint)
) {
const bool vis = !lToolbar->isHidden();
qDebug() << lToolbar->isFloating() << vis << lToolbar->windowFlags();
lToolbar->hide();
lToolbar->setWindowFlag(Qt::X11BypassWindowManagerHint, false);
if (vis)
lToolbar->show();
#endif
}
QToolBar* lToolbar; // Use this in MainWindow constructor to save the instance pointer.
Také jsem si všiml dalšího problému s původně plovoucím panelem nástrojů. Když je hlavní okno minimalizováno, panel nástrojů se neskryje, ale zůstane tam, kde byl na obrazovce. Bez ohledu na to, co je na panelu nástrojů (např. žádné pole se seznamem, pouze QActions). Toto zástupné řešení by také mohlo tento problém vyřešit (viz komentář ke kódu), ale pouze při druhém minimalizaci okna. Potřebuje lepší řešení pro první minimalizaci.
Mohou to potvrdit ostatní? Potenciálně větší problém než upravitelné kombo a byl bych překvapen, kdyby si toho předtím nikdo nevšiml.
Myslím, že by to mělo být v každém případě označeno jako chyba Qt.
AKTUALIZACE 2 :Tato verze také řeší problém s minimalizací. Myslím, že se něco stane po QMainWindow::showEvent()
to změní chování panelu nástrojů. Což vysvětluje, proč výše uvedené řešení funguje pouze po 1. minimalizaci. Takže naplánování "opravy" panelu nástrojů na později to také obchází.
class MainWindow : public QMainWindow
{
...
#ifdef Q_OS_LINUX
protected:
void showEvent(QShowEvent *e) override
{
QMainWindow::showEvent(e);
if (lToolbar->isFloating() && lToolbar->windowFlags().testFlag(Qt::X11BypassWindowManagerHint) ) {
// QMainWindow::show() after QMainWindow::restoreState() will break the minimizing again so we should delay calling adjustToolbar().
QMetaObject::invokeMethod(this, "adjustToolbar", Qt::QueuedConnection);
// If we're sure restoreState() is only called after show() then adjustToolbar() could be called here directly instead.
//adjustToolbar();
}
}
private slots:
void adjustToolbar() const
{
const bool vis = !lToolbar->isHidden();
qDebug() << lToolbar->isFloating() << vis << lToolbar->windowFlags();
lToolbar->hide();
lToolbar->setWindowFlag(Qt::X11BypassWindowManagerHint, false);
if (vis)
lToolbar->show();
}
#endif
private:
QToolBar* lToolbar;
};
PŘIDÁNO :A QToolBar
podtřída, která používá řešení sama o sobě, v QMainWindow
není potřeba nic zvláštního . Oprava minimalizace stále funguje pouze při adjustToolbar()
funkce je zařazena do fronty nebo pokud restoreState()
je voláno pouze po show()
(viz komentáře ke kódu).
class ToolBar : public QToolBar
{
Q_OBJECT
public:
using QToolBar::QToolBar;
#ifdef Q_OS_LINUX
protected:
void showEvent(QShowEvent *e) override
{
QToolBar::showEvent(e);
if (isFloating() && windowFlags().testFlag(Qt::X11BypassWindowManagerHint) ) {
// QMainWindow::show() after QMainWindow::restoreState() will break the minimizing again so we should delay calling adjustToolbar().
QMetaObject::invokeMethod(this, "adjustToolbar", Qt::QueuedConnection);
// If we're sure restoreState() is only called after show() then adjustToolbar() could be called here directly instead.
//adjustToolbar();
}
}
private slots:
void adjustToolbar()
{
const bool vis = !isHidden();
hide();
setWindowFlag(Qt::X11BypassWindowManagerHint, false);
if (vis)
show();
}
#endif
};
AKTUALIZACE 3 :Problém s minimalizací existuje také u plovoucích QDockWidget
pokud QMainWindow
stav je obnoven, než se zobrazí. Ve skutečnosti se u "starších" verzí Qt plovoucí widget vůbec nezobrazuje (nezobrazuje se s <=5.9.5, ale ano s>=5.12.4, nemáte nic mezi tím, abyste vyzkoušeli ATM). Správný přístup je tedy show()
nejprve hlavní okno a pak restoreState()
. Bohužel se zdá, že to pro QToolBar
nefunguje .
AKTUALIZACE 4 :Soubor jako QTBUG-78293