wake-up-neo.com

C++ Größe eines angedockten Qt QDockWidget programmatisch ändern?

Ich habe gerade angefangen, an einem neuen C++/Qt-Projekt zu arbeiten. Es wird ein MDI-basiertes IDE mit angedockten Widgets für Dinge wie den Dateibaum, den Objektbrowser, die Compiler-Ausgabe usw. sein Verkleinern Sie programmgesteuert eine QDockWidget. Mit diesem Snippet wird beispielsweise mein unteres Dock-Fenster "Build Information" erstellt:

m_compilerOutput = new QTextEdit;
m_compilerOutput->setReadOnly(true);
dock = new QDockWidget(tr("Build Information"), this);
dock->setWidget(m_compilerOutput);
addDockWidget(Qt::BottomDockWidgetArea, dock);

Nach dem Start sieht mein Programm so aus (bedenke den frühen Entwicklungsstand):

Actual

Ich möchte jedoch, dass es so aussieht:

Expected

Ich kann nicht scheinen, dass das passiert. In der Qt-Referenz auf QDockWidget heißt es:

Benutzerdefinierte Größenhinweise, minimale und maximale Größen und Größenrichtlinien sollten im untergeordneten Widget implementiert werden. QDockWidget respektiert sie und passt seine eigenen Einschränkungen an, um den Rahmen und den Titel einzuschließen. Größenbeschränkungen sollten nicht für das QDockWidget selbst festgelegt werden, da sie sich abhängig davon ändern, ob es angedockt ist

Dies deutet darauf hin, dass eine Methode, um dies zu tun, darin besteht, QTextEdit als Unterklasse anzugeben und die Methode sizeHint() zu überschreiben. Ich würde es jedoch vorziehen, dies nicht nur zu diesem Zweck zu tun, noch habe ich versucht, dies als funktionierende Lösung zu finden.

Ich habe versucht, dock->resize(m_compilerOutput->width(), m_compilerOutput->minimumHeight()) aufzurufen, m_compilerOutput->setSizePolicy() mit jeder seiner Optionen aufzurufen ... Bisher hat sich nichts auf die Größe ausgewirkt. Wie ich bereits sagte, würde ich es vorziehen, eine einfache Lösung in ein paar Codezeilen zu erstellen, nur um sizeHint() zu ändern. Alle Vorschläge werden geschätzt.

25
Zac

Ich habe gerade denselben Prozess durchlaufen. Nachdem ich viel zu viele Permutationen von resize(), adjustSize() und Freunden auf Dock-Widgets und deren enthaltenen Widgets ausprobiert hatte, funktionierte keines davon. Am Ende habe ich QListView in Unterklassen unterteilt und diese sizeHint() -Methode hinzugefügt.

Jetzt funktioniert es wie ein Zauber.

4
Charl Botha

Ich habe es einfach gemacht: HEADER:

private void setDockSize(QDockWidget *dock, int, int);
  public slots:
  void returnToOldMaxMinSizes();

QUELLE:

QSize oldMaxSize, oldMinSize;

void MainWindow::setDockSize(QDockWidget* dock, int setWidth,int setHeight)
{

    oldMaxSize=dock->maximumSize();
    oldMinSize=dock->minimumSize();

  if (setWidth>=0)
    if (dock->width()<setWidth)
        dock->setMinimumWidth(setWidth);
    else dock->setMaximumWidth(setWidth);
  if (setHeight>=0)
    if (dock->height()<setHeight)
        dock->setMinimumHeight(setHeight);
    else dock->setMaximumHeight(setHeight);

    QTimer::singleShot(1, this, SLOT(returnToOldMaxMinSizes()));
}

void MainWindow::returnToOldMaxMinSizes()
{
    ui->dockWidget->setMinimumSize(oldMinSize);
    ui->dockWidget->setMaximumSize(oldMaxSize);
}
7
semenvx

Es hört sich so an, als würde sich das Dock-Widget in Anbetracht seines untergeordneten Widgets auf die richtige Größe verkleinern. Aus der QDockWidget-Dokumentation (Hervorhebung meiner):

Ein QDockWidget fungiert als Wrapper für sein untergeordnetes Widget, das mit setWidget () festgelegt wurde. Benutzerdefinierte Größenhinweise, minimale und maximale Größen und Größenrichtlinien sollten im untergeordneten Widget implementiert werden . QDockWidget respektiert sie und passt seine eigenen Einschränkungen an, um den Rahmen und den Titel einzuschließen. Größenbeschränkungen sollten nicht für das QDockWidget selbst festgelegt werden, da sie sich in Abhängigkeit davon ändern, ob es angedockt ist. Ein angedocktes QDockWidget hat keinen Rahmen und eine kleinere Titelleiste.

Um die Größe zu ändern, müssen Sie die Größe des untergeordneten Widgets ändern.

BEARBEITEN: Die Qt-Dokumentation kann manchmal irreführend sein, wenn es um Größenhinweise geht. Häufig bezieht es sich auf jede Art von Größenänderung, unabhängig davon, ob sie automatisch vom Widget oder programmgesteuert durchgeführt wird.

6
TreDubZedd

Dies ist eine alte Frage, aber ich wollte darauf hinweisen, dass Qt 5.6 die Funktion QMainWindow :: resizeDocks eingeführt hat, um dies zu handhaben.

Leider funktioniert es nicht für meinen Anwendungsfall (Verschieben des Trennzeichens zwischen zwei QDockWidgets, die mit QMainWindows :: splitDockWidget aufgeteilt wurden)

4
Alex Goldberg

Sie könnten dies tun:

Legen Sie eine maximale Höhe für Ihre QTextEdit fest:

m_compilerOutput = new QTextEdit;
m_compilerOutput->setMaximumHeight(100);

Und dann setzen Sie es im show event Ihres Hauptfensters wieder auf die alte Größe oder etwas Hoches:

void MainWindow::showEvent(QShowEvent *)
{
   m_compilerOutput->setMaximumHeight(10000);
}

Das ist alles was Sie brauchen sollten.

2
thuga

Haben Sie versucht, resize() für die QTextEdit in Ihrem Dock-Widget aufzurufen? Sie können auch versuchen, die maximale und minimale Größe des Dock-Widgets vorübergehend auf die gewünschte Größe einzustellen und dann die ursprünglichen Werte wiederherzustellen.

2
Kitsune

Wenn die dockWidgets angedockt sind, werden die Größen von ihrem übergeordneten Element gesteuert. In solchen Fällen können Sie die Funktion QMainWindow::resizeDocks verwenden.

Wenn schwebend, werden die Größen von ihren Kindern bestimmt. Ändern Sie die Größe der Kinder , um Ihren Zweck zu erreichen.

1
momo

Tests mit Größenänderung für QDockWidget::widget() (d. H. Das Widget, das von QDockWidget verwaltet wird) funktionieren nicht wie erwartet.

Bei einer Unterklasse QDockWidget (DW), in der bei einer Unterklasse QWidget mit einem QHBoxLayout zwei Widgets ( linkes Bedienfeld und rechtes Bedienfeld ) hinzugefügt wurden, deren Größenrichtlinien normalerweise auf QSizePolicy::Minimum festgelegt wurden, hat die DW beide Panel Widgets sichtbar. Wenn sich der DW in einem seitlichen Dock befindet, verbirgt ein Anwendungs-Slot (QMainWindow), der das Signal dockLocationChanged des DW verarbeitet, das linke Bedienfeld und ändert die Größe von DW->widget() auf die Größe des rechten Bedienfelds. Wenn der DW programmgesteuert in den unteren Dock-Bereich verschoben wird, wird leftPanel sichtbar und der DW füllt (natürlich) die gesamte Breite des Hauptfensters aus. Wenn der DW dann programmgesteuert in einen seitlichen Andockbereich verschoben wird, wird das linke Bedienfeld ausgeblendet und die Größe des DW verringert. Das funktioniert wie vorgesehen. Wenn der DW jedoch aus dem unteren Andockbereich in einen seitlichen Andockbereich gezogen wird, wird die Größe des DW nicht verringert, obwohl das linke Bedienfeld ausgeblendet ist und die Größenänderung wie zuvor angewendet wurde, wenn die Neupositionierung programmgesteuert durchgeführt wird. Sie können die Größe der DW manuell anpassen, indem Sie den Splitter-Handle zwischen der DW und dem zentralen Bereich des Hauptfensters ziehen. Beachten Sie, dass der zentrale Bereich des Hauptfensters ein QWidget mit einem QHBoxLayout mit Größenrichtlinien QSizePolicy::Expanding ist.

Das Aufrufen von adjustSize im Hauptfenster, nachdem die Größe des DW geändert wurde, hat keine Auswirkung. Dies, obwohl der DW sizeHint neu implementiert hat, um seine Mindestgröße zurückzugeben, abhängig davon, ob das linke Bedienfeld sichtbar ist oder nicht.

Entweder fehlt mir etwas, um die Größe von QDockWidget zu steuern (was angesichts der Schwierigkeiten, die ich beim Verstehen aller Interaktionen zwischen den Teilen des Layoutverwaltungssystems hatte, sehr wahrscheinlich ist), oder QMainWindow ignoriert das Layout oder überschreibt es Anweisungen, die es gegeben wird. Eine genaue Untersuchung des Ereignisstroms während der Neupositionierungsvorgänge von QDockWidget deutet auf Folgendes hin: Nachdem die Größenänderung des Signals dockLocationChanged abgeschlossen und in die Ereignisschleife zurückgekehrt ist, kann ich feststellen, dass QMainWindow beim Neupositionieren des Benutzers eine zusätzliche Größenänderung vornimmt Operationen auf dem betroffenen QDockWidget machen somit die Anwendungslogik rückgängig, die versucht, die Dockgröße zu steuern. Irgendetwas scheint im QMainWindow nicht zu stimmen ....

1
user674263

Das Problem beim Ändern der Größe von Dock-Widgets bei maximiertem MainWindow wird in QTBUG-16252 ( https://bugreports.qt.io/browse/QTBUG-16252 ) beschrieben.

Ich habe eine andere Problemumgehung gefunden. Funktioniert bei mir unter QT 5.4.1 minGW unter Windows7. Es sieht so aus, als ob einige Widget-Statuswiederherstellungsvorgänge eng mit der QApplication-Ereignisschleife zusammenhängen.

DockWidget-Größen werden NUR dann korrekt wiederhergestellt, wenn folgende Bedingungen erfüllt sind:

  1. restoreGeometry () wird aufgerufen, BEVOR QApplication :: exec () eingegeben wird (z. B. im Konstruktor Ihrer MainWindow-Klasse).

  2. restoreState () heißt AFTER exec () (z. B. über QTimer)

Hier ist mein Code:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    //...

    MainWindow mainWindow;
    mainWindow.show();

    return application.exec();
}

MainWindow::MainWindow(...) 
{
    ui->setupUi(this);

    //...
    QTimer* nt = new QTimer(this);

    nt->setSingleShot(true);
    nt->setInterval( 100 );

    connect(nt, SIGNAL(timeout()), SLOT(restoreWidgetSettings()));
    nt->connect(nt, SIGNAL(timeout()), SLOT(deleteLater()));

    nt->start();

    restoreWidgetSettings(true);
}

void MainWindow::restoreWidgetSettings(bool geometryOnly) {

    //...
    QByteArray geometry = getSettings();

    restoreGeometry(geometry);

    if(geometryOnly)
        return;

    //... //create dock widgets here

    restoreState(mainWindowState);

}
0
vrogach