Howto Change layout of a Widget



  • Good evening,

    I'm developing a Widget Mobile application for symbian, and have a question about Widgets and Boxlayouts.

    For designing my interface, I use an UI from. I placed some widgets on it and put them in a Vboxlayout. I Morphed this Vboxlayout to a Qwidget so I could re-size the Layout by code.. Now I am trying to change the layout of this QWidget from VBoxlayout to HBoxlayout by code. I tried this (look code below) but it didn't work.

    @QHBoxLayout *hlayout = new QHBoxLayout;

    ui->vwidget->setLayout(hlayout);@
    

    But the layout doesn't change. Is the current layout still active? or isn't this possible?

    Thanks in advance!

    Greets!
    Tristan



  • Try to:

    @
    ui->yourVboxLayout->removeWidget( ui->widget );
    delete ui->yourVboxLayout;

    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setObjectName(QString::fromUtf8("hlayout"));
    ui->mainLayout->addLayout( hlayout );
    ui->hlayout->addWidget( ui->widget );
    @

    Not tested, but i believe can help



  • As msx_br already mentioned you cannot set a layout on a widget that already has a layout.
    [quote]"QWidget::setLayout()":http://qt-project.org/doc/qt-4.8/qwidget.html#setLayout

    Sets the layout manager for this widget to layout.

    If there already is a layout manager installed on this widget, QWidget won't let you install another. You must first delete the existing layout manager (returned by layout()) before you can call setLayout() with the new layout.

    If layout is the layout manger on a different widget, setLayout() will reparent the layout and make it the layout manager for this widget.[/quote]



  • Thanks for reply Lukas and msx_br :) Okay, I have to remove the 'old' layout to set a new one. I have one more question if you don't mind.. In the code you gave me:

    @ui->yourVboxLayout->removeWidget( ui->widget );
    delete ui->yourVboxLayout;@

    This confuses me, because in my ui Designer I had one Vboxlayout which had other widgets placed on it.. Also in the designer I morphed this VBoxlayout into a QWidget, So I only have a Widget which can Vertically align its sub widgets.. there is no Vboxlayout anymore, only one QWidget called 'vwidget'. Is there a way to set the layout of this Widget to a Hboxlayout?

    also:
    ui->mainLayout->addLayout( hlayout );

    There is no mainlayout? only a stackedWidget :)

    I think I understand your code, but I cant delete Vboxlayout, because I would delete the whole widget then (I think) :)

    Sorry for, my lack of knowledge and English skills, but I looked trough the documentation, without any success (I'm relatively new to QT)



  • If you deleted the main layout of your vwidget, just add the new layout to it:

    @
    ui->yourVboxLayout->removeWidget( ui->widget );
    delete ui->yourVboxLayout;

    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setObjectName(QString::fromUtf8("hlayout"));
    ui->vwidget->setLayout( hlayout );  // Here you can set the widget's layout
    ui->hlayout->addWidget( ui->widget );
    

    @



  • Okay Thanks, its beginning to get clear :) but how do I delete my Vboxlayout form my 'Vwidget' if My Vboxlayout IS this widget? So what I can do is:

    @ui->vwidget->removeWidget( ui->widget );
    delete ui->vwidget;@

    But that would be wrong, wouldn't it? :)

    Thanks in advance,

    Tristan



  • We are close to solution, Tristan,

    You have a QWidget with a QLayout, you can remove this layout:

    @
    if( widget->layout() )
    {
    mainWidget->layout()->removeWidget( your_widget );
    delete mainWidget->layout();
    }
    @

    And if you want to create a new QLayout ( horziontal, vertical....) with your_widget:
    @
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setObjectName(QString::fromUtf8("hlayout"));
    mainWidget->setLayout( hlayout );
    hlayout->addWidget( your_widget );
    @

    As you see in the code:

    1 - If your main widget ( container of other widgets ) have a layout, then you remove the
    widgets from the layout, then delete the layout.

    2 - The widgets removed from layout (step 1) are orphans, so you can create a new layout,
    set this new layout as the layout of your mainWindget and add the orphans widgets to this layout.

    PS: I have changed the naming of the widgets to something more clean



  • Thanks for response :)

    My mainwidget is 'centralwidget' then comes my 'stackedwidget' and then my vwidget with the vlayout.

    So I did this, Like you said :)

    @if( ui->vwidget->layout())
    {
    ui->centralWidget->layout()->removeWidget( ui->vwidget );
    delete ui->centralWidget->layout();
    }

    QHBoxLayout *hlayout = new QHBoxLayout;
        hlayout->setObjectName(QString::fromUtf8("hlayout"));
        ui->centralWidget->setLayout(hlayout );
        hlayout->addWidget( ui->vwidget );@
    

    But after I try to run the program I get the following error:

    @Thread has crashed: A data abort exception has occurred accessing 0x0.@

    Did I deleted the wrong layout?

    Greets,
    Tristan



  • I'll make a test program to reproduce this.

    Actually i have 2 programs using this approach without problems.



  • Here is a simple appllication.
    @
    #include <QtGui/QApplication>
    #include "Dialog.h"
    #include <QDialog>
    #include <QBoxLayout>
    #include <QLabel>

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

    // Our dialog
    QDialog dialog;
    dialog.resize( 600, 400 );
    
    // Initial layout of the dialog, we will delete it later to reproduce your test
    QBoxLayout *mainLayout = new QBoxLayout( QBoxLayout::TopToBottom, &dialog );
    dialog.setLayout( mainLayout );
    
    // Create a label wich will be contained by the layout
    QLabel *label = new QLabel( "Layout Test", &dialog);
    label->setAlignment(Qt::AlignCenter);
    mainLayout->addWidget( label );
    
    // only to see the results, try to resize the dialog with the mouse
    // close the dialog to contiune...
    dialog.exec&#40;&#41;;
    
    // Here we start to "dynamic reparenting" of the label
    if( dialog.layout() )
    {
        dialog.layout()->removeWidget( label );  // remove the label from the undesired layout
        delete dialog.layout();                  // then delete the undesired layout
    }
    
    // At this point we have a only a dialog with a label
    // only to see the results, try to resize the dialog with the mouse
    // close the dialog to contiune...
    dialog.exec&#40;&#41;;
    
    // Create a new layout, wich will contain the label
    QHBoxLayout *hlayout = new QHBoxLayout;
    dialog.setLayout( hlayout );
    hlayout->addWidget( label );
    
    dialog.show();
    return a.exec&#40;&#41;;
    

    }
    @

    You can think the "dialog" as your vwidget.



  • Thanks!!

    This example of you really helped me! :) I finally got this layout working and I understand how these layouts work now! thanks to your help ;)

    This is the solution:

    @if( ui->vwidget->layout())
    {

        ui->vwidget->layout()->removeWidget( ui->vwidget1 );
        ui->vwidget->layout()->removeWidget( ui->vwidget2 );
        ui->vwidget->layout()->removeWidget( ui->hwidget1 );
        ui->vwidget->layout()->removeWidget( ui->vwidget2 );
        ui->vwidget->layout()->removeWidget( ui->line_3 );
        ui->vwidget->layout()->removeWidget( ui->line_4 );
        delete ui->vwidget->layout();
    }
    
    QHBoxLayout *hlayout = new QHBoxLayout;
        hlayout->setObjectName(QString::fromUtf8("hlayout"));
        ui->vwidget->setLayout(hlayout );
    
        hlayout->addWidget(ui->vwidget1 );
        hlayout->addWidget(ui->vwidget2 );
        hlayout->addWidget(ui->hwidget1 );
        hlayout->addWidget(ui->hwidget2 );
        hlayout->addWidget(ui->line_3 );
        hlayout->addWidget(ui->line_4 );
    
        ui->vwidget->setGeometry(QRect(0,0,640,360));
    

    @

    Goodnight ;) and thank you once again for your patience.

    Greets,

    Tristan


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.