[gelöst] QT: Splitter bei Größenänderung des Formulars nicht verschieben



  • Hallo

    ich habe auf einem Widget 2 TextEdit-Label-Paare plaziert. Die Label sollen die Überschrift zu den TextEdit abbilden.
    Die Elemente sollen die gesamte Widget-Fläche ausfüllen.

    Soweit bekomme ich das hin.
    Jedoch soll das untere TextEdit-Label-Paar (bei Änderung der Widgetgröße) eine konstante Höhe haben. Die Höhe soll nur vom User durch ein Splitter änderbar sein.

    Folgendermaßen bin ich vorgegangen (Designer QT4.7):

    • Label1 und TextEdit1 mit einem verticalLayout verbunden
    • Label2 und TextEdit2 mit einem verticalLayout verbunden
    • verticalLayout1 und verticalLayout2 mit einem Splitter verbunden (vertikal)
    • das Widget selbst auf "senkrecht anordnen" gesetzt

    So soll es etwa aussehen:
    `|-Widget--------------|

    |-Label1--------------|

    ||-TextEdit1---------||

    ||...................||

    ||-------------------||

    |-Splitter------------|

    |-Label2--------------|

    ||-TextEdit2---------||

    ||...................||

    ||-------------------||

    |---------------------|`

    Ich habe schon intensiv mit der sizePolicy-Eigenschaften herumgespielt aber offensichtlich noch nicht die richtigen Einstellungen gefunden. (Sofern das überhaupt der richtige Weg ist)

    Wie bekomme ich es also hin das das untere Label-TextEdit-Paar nicht automatisch die Höhe ändert?
    Schon mal vielen Dank 🙂



  • Kanns Sein das du da zwei Widgets unterschlagen hast? So müsste der Splitter ja 3 Splittings verursachen.

    So gehts:

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QSplitter * split = new QSplitter(Qt::Vertical);
        {
            QWidget   * eins  = new QWidget;
            {
                QVBoxLayout * vbl1= new QVBoxLayout (eins);
    
                QLabel    * la1   = new QLabel("eins");
                QTextEdit * te1   = new QTextEdit("eins edit");
    
                vbl1->addWidget(la1);
                vbl1->addWidget(te1);
            }
    
            QWidget   * zwei  = new QWidget;
            {
                QVBoxLayout * vbl2= new QVBoxLayout (zwei);
    
                QLabel    * la2   = new QLabel("zwei");
                QTextEdit * te2   = new QTextEdit("zwei edit");
    
                vbl2->addWidget(la2);
                vbl2->addWidget(te2);
            }
    
            split->addWidget(eins);
            split->addWidget(zwei);
        }
    
        split->setChildrenCollapsible(false);
        split->setStretchFactor(0,1000);         // <--- widget an pos 1 bekommt 1000 mal mehr von Größenänderungen als das an pos 2 (ungenau)
        split->setStretchFactor(0,1);         // <--- widget an pos 1 bekommt 1000 mal mehr von Größenänderungen als das an pos 2 (ungenau)
    
        QWidget w;
        {
            QHBoxLayout hbl(&w);
            hbl.addWidget(split);
        }
        w.show();
    
        return a.exec();
    }
    

    (vergiss nicht das [gelöst:] vorm Titel 😉 )



  • padreigh schrieb:

    Kanns Sein das du da zwei Widgets unterschlagen hast? So müsste der Splitter ja 3 Splittings verursachen.

    Nein, ich habe keine Widgets unterschlagen. Aber vielleicht ist ja genau das mein Problem. Soweit ich das sehe gibt es auch nur 1 Splitter. (zwischen den beiden Layouts der jeweiligen Label-TextEdit-Paare)

    padreigh schrieb:

    So gehts:
    ...

    zwei Änderungen habe ich vorgenommen damit es geht:

    Zeile 35 ersetzt durch:

    split->setStretchFactor(1,1);
    

    Zeile 39-40 ersetzt durch

    QHBoxLayout * layout = new QHBoxLayout;
            layout->addWidget(split);
            w.setLayout(layout);
    

    Sobald ich aber den Splitter verwendet habe wird der untere Bereich wieder (auch wenn nur geringfügig) in der Höhe angepasst wenn die Größe des Widgets geändert wird.

    padreigh schrieb:

    (vergiss nicht das [gelöst:] vorm Titel)

    Noch nicht ganz gelöst aber auf jeden Fall viel näher als ich bisher der Sache gekommen war. 😉
    Mal schauen ob ich das auch mit dem Designer hinbekomme. Oder ist das aussichtslos?



  • Zahlendreher, ich meinte (1,0) nicht (0,1) das würde ja (0,1000) wieder rückgängig machen ... du kannst statt 1000 ja 100000 machen ... irgendwann sollte sich das untere Widget nicht mehr (wahrnehmbar) in der Größe verändern. Versuch auch mal

    split->setStretchFactor(0,1000);     
    split->setStretchFactor(1,0);
    

    .. dann sollte das 2. (da stretch 0) keinen Anteil mehr an der Änderung haben. Mein QtCreator 1.3x kann noch keine Splitter ... schau halt mal in die Eigenschaften ob da sowas wie "stretch" vorkommt 🙂



  • padreigh schrieb:

    Zahlendreher, ich meinte (1,0) nicht (0,1)

    So klappt es mit der konstanten Höhe. Kannst du mir noch einen Tipp geben wie ich die Initialhöhe des unteren Bereiches setzen kann?

    Ich habe folgendes mal vor und mal nach Zeilen 29 & 30 probiert, leider ohne Erfolg:

    QRect geo = zwei->geometry();
    geo.setHeight(100);
    zwei->setGeometry(geo);
    

    padreigh schrieb:

    Mein QtCreator 1.3x kann noch keine Splitter ... schau halt mal in die Eigenschaften ob da sowas wie "stretch" vorkommt

    Beim Splitter selbst gibt es kein StretchFactor-Eigenschaft. Aber ich habe mir mal die Methode setStretchFactor angesehen. Wenn ich das richtig verstehe gibt diese die Werte an die dem Splitter zugeordneten Widgets weiter. Also habe ich die Werte im Designer direkt bei den Widgets eingetragen. Das funktioniert scheinbar auch.

    padreigh schrieb:

    du kannst statt 1000 ja 100000 machen

    Im Designer kann man max. 255 eingeben, aber das Ergebnis bleibt das Gleiche. 😉



  • du könntest dir mit

    QList<int> 	QSplitter::sizes () const
    

    eine Liste der Größen hohlen und die manuell anpassen ( das 2. auf 100 setzen, die differenz von bekommener größe und 100 auf das 1. aufschlagen und dann mit

    void 	QSplitter::setSizes ( const QList<int> & list )
    

    neu setzen).

    ... wenn der das allerdings auch nur durchreicht (so wie die stretch'es) dann würde es eventuell reichen einfach die größe des 2. widgets auf 100 zu setzen ...



  • Das war der Hinweis der mir fehlte:

    QList<int> QSplitter::sizes () const
    ...
    void QSplitter::setSizes ( const QList<int> & list )
    

    AnOnümUs schrieb:

    ... wenn der das allerdings auch nur durchreicht (so wie die stretch'es) dann würde es eventuell reichen einfach die größe des 2. widgets auf 100 zu setzen ...

    Das klappt leider nicht. Das hatte ich ja schon in meinem vorherigen Post geschrieben. Im Designer sind diese Werte auch deaktiviert wenn das Widget sich in einem Splitter befindet.
    Intern führt der Splitter scheinbar eine Liste: "QList<QSplitterLayoutStruct *> list" was auch dafür spricht das die Höhe des Widgets ignoriert wird.

    Über QSplitter::setSizes lassen sich die Initialwerte aber wunderbar setzen. (auch wenn das über den Designer bequemer wäre)

    Ein Stolperstein gab es noch wenn man mit dem Designer arbeitet. Ich hatte zunächst versucht die Höhe im Konstruktor des Widgets zu setzen. An dieser Stelle konnte ich aber noch nicht die aktuellen Maße des Widgets abrufen. Überschreiben des showEvents hat da aber geholfen.
    Die Methode sieht dann so aus:

    void WidgetGUI::showEvent(QShowEvent * event)
    {
        QList<int> sizes = ui->splitter->sizes();
    
        int sum = 0;
        int item;
        foreach(item, sizes) {
            sum += item;
        }
    
        if (sum > 100) {
            sizes.clear();
            sizes.append(sum - 100);
            sizes.append(100);
            ui->splitter->setSizes(sizes);
        }
    
        QWidget::showEvent(event);
    }
    

    Vielen Dank an padreigh und AnOnümUs.
    Jetzt gibt es auch ein [gelöst] im Titel. 😉
    Falls es doch einen Weg gibt die Initialhöhe über den Designer zu setzen dann würde ich mich natürlich noch über Hinweise freuen.



  • Hehe 🙂 gut das dir die Tipps geholfen haben ... jetzt musst du nur hoffen das du nie in die Lage kommst das das den Splitter beherbergende Widget 102 Pixel hoch wird -> Log 100 breit, Sichtfenster 2 LOL (also wohl setMininumHeigth(200) oder so 😉


Log in to reply