OK, una soluzione alternativa consiste nel reimpostare i flag della finestra sulla barra degli strumenti quando viene visualizzata per la prima volta ed è mobile. L'ho rintracciato vedendo cosa succede una volta che una barra degli strumenti viene rilasciata dopo essere stata trascinata (ma non collegata alla finestra principale). (Si chiama setWindowState()
e tutto ciò che fa in questa situazione è nascondere la barra degli strumenti, chiama updateWindowFlags()
e mostralo di nuovo).
Questo potrebbe essere gestito dal QMainWindow::showEvent()
o dal eventFilter
installato sul QToolBar
. Penso che sia più semplice dal primo.
AGGIORNA :Questo problema si verifica effettivamente ogni volta che la barra degli strumenti viene mostrata per la prima volta anche se non all'avvio dell'app, ad es. dal menu di visualizzazione alternata dall'utente una volta avviata l'app. Ho aggiornato il codice qui sotto per risolvere anche questo problema. E vedi le note sotto su un altro problema con la riduzione a icona della finestra principale.
Ho aggiunto questo al MainWindow
classe da 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.
Ho anche notato un altro problema con la barra degli strumenti inizialmente mobile. Quando la finestra principale è ridotta a icona, la barra degli strumenti non viene nascosta ma rimane dov'era sullo schermo. Indipendentemente da cosa c'è nella barra degli strumenti (es. nessuna casella combinata, solo QActions). Questa soluzione alternativa potrebbe anche risolvere il problema (vedere il commento sul codice), ma solo la seconda volta che la finestra viene ridotta a icona. Ha bisogno di una soluzione alternativa migliore per la prima minimizzazione.
Altri possono confermarlo? Potenzialmente un problema più grande della combinazione modificabile e sarei sorpreso se nessuno se ne fosse accorto prima.
Immagino che questo dovrebbe essere archiviato come un bug Qt in entrambi i casi.
AGGIORNAMENTO2 :Questa versione risolve anche il problema di minimizzazione. Immagino che accada qualcosa dopo il QMainWindow::showEvent()
che cambia il comportamento della barra degli strumenti. Il che spiega perché la soluzione sopra descritta funziona solo dopo la prima riduzione a icona. Quindi programmare la "correzione" della barra degli strumenti per un lavoro successivo risolve anche questo problema.
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;
};
AGGIUNTO :A QToolBar
sottoclasse che applica la soluzione alternativa da sola, non è necessario nulla di speciale nel QMainWindow
. La correzione di riduzione a icona funziona ancora solo quando adjustToolbar()
la funzione è in coda o se restoreState()
viene chiamato solo dopo show()
(vedi commenti sul codice).
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
};
AGGIORNAMENTO3 :Il problema di minimizzazione esiste anche con il floating QDockWidget
se il QMainWindow
lo stato viene ripristinato prima di essere visualizzato. In effetti con le versioni Qt "vecchie" il widget mobile non viene visualizzato affatto (non con <=5.9.5 ma con>=5.12.4, non c'è niente in mezzo per provare ATM). Quindi l'approccio corretto è show()
prima la finestra principale e poi restoreState()
. Sfortunatamente questo non sembra funzionare per QToolBar
.
AGGIORNAMENTO4 :archiviato come QTBUG-78293