PDA

View Full Version : QGroupBox Issues



ToddAtWSU
11th January 2007, 16:26
I have converted my Qt 4.2 project down to Qt 3.3 as I was tasked. Of course nothing appeared like it did in my Qt 4.2 project so now it's time to debug and get it back to the way it was, but at least I can compile and get something to display. In my Main GUI, I have a label at the top-right, label in the bottom-left and a QSplitter in the middle. On the right side of the splitter I plan for 4 QGroupBoxes and on the left one QTable. Right now I am trying to get my 4 group boxes to show, and the middle two boxes are empty in the beginning...stuff is entered into them based on user interactions later on. The first problem I have is I don't see any titles on the QGroupBoxes and some of the members of the bottom QGroupBox is in between members of the top QGroupBox. And since I can't see any QGroupBox titles, I don't know if my empty boxes are being drawn. Here are some snippets of my code:


Inside my function MainWindow::createGUI
QFrame *mainFrame = new QFrame( this );
QVBoxLayout *mainLayout = new QVBoxLayout( mainFrame );
QSplitter *mainSplitter = new QSplitter( Qt::Horizontal );

QFrame *constraintFrame = new QFrame( mainSplitter );
QVBoxLayout *constraintLayout = new QVBoxLayout( constraintFrame );

...

createBox1( );
createBox2( );
createBox3( );
createBox4( );

constraintLayout->addWidget( mpBox1 );
constraintLayout->addWidget( mpBox2 );
constraintLayout->addWidget( mpBox3 );
constraintLayout->addWidget( mpBox4 );

...

setCentralWidget( mainFrame );




bool MainWindow::createBox1( )
{
mpBox1 = new QGroupBox( tr( "Display Constraints" ) );
QGridLayout *layout1 = new QGridLayout( mpBox1 );
QLabel *collectorsLabel = new QLabel( tr( "Collectors" ), this );
QLabel *minLabel = new QLabal( tr( "Min1:" ), this );
QLabel *maxLabel = new QLabel( tr( "Max1:" ), this );
mCollectorsBox = new QComboBox( this );
mMinLineEdit = new QLineEdit( this );
mMaxLineEdit = new QLineEdit( this );

mCollectorsBox->insertItem( tr( "1" ) );
mCollectorsBox->insertItem( tr( "2" ) );
mCollectorsBox->insertItem( tr( "3" ) );
mCollectorsBox->insertItem( tr( "4" ) );
mCollectorsBox->insertItem( tr( "5" ) );

layout1->addMultiCellWidget( collectorsLabel, 0, 0, 0, 1 );
layout1->addMultiCellWidget( mCollectorsBox, 0, 0, 3, 3 );
layout1->addMultiCellWidget( minLabel, 1, 1, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMinLineEdit, 1, 1, 1, 3 );
layout1->addMultiCellWidget( maxLabel, 2, 2, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMaxLineEdit, 2, 2, 1, 3 );

return true;
}




bool MainWindow::createBox4( )
{
mpBox4 = new QGroupBox( tr( "Section Constraints" ) );
QGridLayout *layout4 = new QGridLayout( mpBox4 );
QLabel *minLabel = new QLabal( tr( "Min2:" ), this );
QLabel *maxLabel = new QLabel( tr( "Max2:" ), this );
mMinSectionLineEdit = new QLineEdit( this );
mMaxSectionLineEdit = new QLineEdit( this );

layout1->addMultiCellWidget( minLabel, 0, 0, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMinSectionLineEdit, 0, 0, 1, 1 );
layout1->addMultiCellWidget( maxLabel, 1, 1, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMaxSectionLineEdit, 1, 1, 1, 1 );

return true;
}


Any of the members that begin with "mp" are member-pointers of my class and any object that begins with "m" is a class member with the exception of minLabal and maxLabel. When I run the program the main part of my window looks like:

collectorsLabel mCollectorsBox
Min2: mMinSectionLineEdit


Min1: mMinLineEdit


Max2: mMaxSectionLineEdit
Max1: mMaxLineEdit


My plan is for it to look like:

GroupBox1
collectorsLabel mCollectorsBox
Min1: mMinLineEdit
Max1: mMaxLineEdit

GroupBox2

GroupBox3

GroupBox4
Min2: mMinSectionLineEdit
Max2: mMaxSectionLineEdit


Like I said GroupBox2 and GroupBox3 are empty when I first load the program but the boxes should still appear. Can you see anything from my code as to what I could be doing incorrectly? Thanks!

Glitch
11th January 2007, 17:13
QGroupBoxes are particularly nasty in Qt3. They were rewritten for Qt4 to work in the sane manner of "Create QGroupBox and set any layout you want". This was NOT the usage in t Qt3.

In Qt3 a GroupBox had an automatic layout assigned. QGroupBox by itself was a grid, QVGroupBox was a QVBoxLayout and QHBoxGroup had a QHBoxLayout. Infact there is really two layouts for each of these internally required to avoid widgets over the frame and label.

The best thing to do to make your code readable and reusable is to do something like this:


QVGroupBox* box = new QVGroupBox(usualParent);
QWidget* blankWidget = new QWidget(box);
// blankWidget has been auto added to the group box's layout

QGridLayout* gridLayout = new QGridLayout(blankWidget);
QComboBox* widgetApprearingInBox = new QComboBox(blankWidget);
gridLayout->addWidget(0,0,widgetApprearingInBox);

Its awkward, its confusing, it was rewritten for Qt4.... Try to convice your employer that Qt4 is far superior (and supportable).

--Justin

ToddAtWSU
11th January 2007, 18:25
I changed my createBox1 functions like this:



bool MainWindow::createBox1( )
{
// mpBox1 = new QGroupBox( tr( "Display Constraints" ) );
layout1 = new QVGroupBox( tr( "Display Constraints" ) );
QWidget *dummyWidget = new QWidget( mpVGroupBox );

// QGridLayout *layout1 = new QGridLayout( mpBox1 );
QGridLayout *layout1 = new QGridLayout( dummyWidget );

QLabel *collectorsLabel = new QLabel( tr( "Collectors" ), this );
QLabel *minLabel = new QLabal( tr( "Min1:" ), this );
QLabel *maxLabel = new QLabel( tr( "Max1:" ), this );
mCollectorsBox = new QComboBox( this );
mMinLineEdit = new QLineEdit( this );
mMaxLineEdit = new QLineEdit( this );

mCollectorsBox->insertItem( tr( "1" ) );
mCollectorsBox->insertItem( tr( "2" ) );
mCollectorsBox->insertItem( tr( "3" ) );
mCollectorsBox->insertItem( tr( "4" ) );
mCollectorsBox->insertItem( tr( "5" ) );

layout1->addMultiCellWidget( collectorsLabel, 0, 0, 0, 1 );
layout1->addMultiCellWidget( mCollectorsBox, 0, 0, 3, 3 );
layout1->addMultiCellWidget( minLabel, 1, 1, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMinLineEdit, 1, 1, 1, 3 );
layout1->addMultiCellWidget( maxLabel, 2, 2, 0, 0, Qt::AlignCenter );
layout1->addMultiCellWidget( mMaxLineEdit, 2, 2, 1, 3 );

return true;
}

I changed all of my boxes to look like this and I still don't see any box headers. I do get the items to sort of group together but some of them are off the screen or don't appear but the ones that do appear are in the correct order. I tried changing the parent of all the items to go into the QGridLayout to dummyWidget but then nothing at all appeared on the screen so at least I get some output with using this as the parent. Any other ideas? I have tried to get them to let me use Qt 4 but all they say is No.....:crying:

Glitch
11th January 2007, 21:37
How does this even compile? Aside from misspellings like "QLabal", layout1 is used twice with different types



// mpBox1 = new QGroupBox( tr( "Display Constraints" ) );
layout1 = new QVGroupBox( tr( "Display Constraints" ) );

QWidget *dummyWidget = new QWidget( mpVGroupBox );
// QGridLayout *layout1 = new QGridLayout( mpBox1 );
QGridLayout *layout1 = new QGridLayout( dummyWidget );

QLabel *collectorsLabel = new QLabel( tr( "Collectors" ), this );
QLabel *minLabel = new QLabal( tr( "Min1:" ), this );


You will need to set the parent of all things appearing inside the groupbox to dummyWidget. Make sure your parent/child relationships are right. That is what usually cause widget not to show up. I notice that layout1 = new QVGroupBox( tr( "Display Constraints" ) ); does not include a parent. Use parents in the constructor for all widgets and layouts in Qt3. It's required.

--Justin

ToddAtWSU
12th January 2007, 13:22
Sorry the computer I develop on is not hooked up to the internet so a typo is very easy to occur when I retype the code onto here. The first layout1 should be mpBox1 as it was in the commented line before it and yes QLabel is spelled wrong here but is correct on my developing machine. I will try to fix your ideas and see if that helps. I am also experimenting with the designer to see how they write their code. Thanks again!

ToddAtWSU
12th January 2007, 14:34
I decided to re-write the createGUI function and slowly debug the Qt 3 code so I can efficiently learn how to write Qt 3 code. Here is what my 2 functions look like.



bool MainWindow::createGUI
{
setCentralWidget( new QWidget( this ) );

QFrame *mainFrame = new QFrame( centralWidget( ) );

QWidget *layoutWidget = new QWidget( mainFrame );
QVBoxLayout *mainLayout = new QVBoxLayout( layoutWidget );

mpTopLabal = new QLabel( tr( "Hello" ), layoutWidget );
mpTopLabel->setAlignment( Qt::AlignRight );
mpTopLabel->setMaximumHeight( 30 );
mainLayout->addWidget( mpTopLabel );

QSplitter *mainSplitter = new QSPlitter( QSplitter::Horizontal, layoutWidget );

QFrame *constraintFrame = new QFrame( mainSplitter );
QWidget *constraintWidget = new QWidget( constraintFrame );
QVBoxLayout *constraintLayout = new QVBoxLayout( constraintWidget );

mpDisplayBox = new QVGroupBox( tr( "Display Constraints:" ), constraintWidget );
createDisplayBox( );
constraintLayout->addWidget( mpDisplayBox );

// I will work with the table later but I want to add the 2nd item to the splitter.
// A splitter with just one item seems pretty useless and I will have a 2nd item
// once the left side is done.
QFrame *tableFrame = new QFrame( mainSplitter );

mainLayout->addWidget( mainSplitter );

mpBottomLabel = new QLabel( tr( "Bye" ), layoutWidget );
mpBottomLabel->setAlignment( Qt::AlignLeft );
mpBottomLabel->setMaximumHeight( 30 );
mainLayout->addWidget( mpBottomLabel );

return true;
}




bool MainWindow::createDisplayBox( )
{
QWidget *dummyWidget = new QWidget( mpDisplayBox );
QGridLayout *displayLayout = new QGridLayout( dummyWidget );

QLabel *collectorsLabel = new QLabel( tr( "Collectors: ), dummyWidget );
QLabel *minLabal = new QLabel( tr( "Min:" ), dummyWidget );
QLabel *maxLabel = new QLabel( tr( "Max:" ), dummyWidget );
mpCollectorsBox = new QComboBox( dummyWidget );
mpMinLineEdit = new QLineEdit( dummyWidget );
mpMaxLineEdit = new QLineEdit( dummyWidget );

mpCollectorsBox->insertItem( tr( "1" ) );
mpCollectorsBox->insertItem( tr( "2" ) );
mpCollectorsBox->insertItem( tr( "3" ) );
mpCollectorsBox->insertItem( tr( "4" ) );
mpCollectorsBox->insertItem( tr( "5" ) );

displayLayout->addMultiCellWidget( collectorsLabel, 0, 0, 0, 1 );
displayLayout->addMutliCellWidget( mpCollectorsBox, 0, 0, 3, 3 );
displayLayout->addMutliCellWidget( minLabel, 1, 1, 0, 0 );
displayLayout->addMutliCellWidget( mpMinLineEdit, 1, 1, 1, 3 );
displayLayout->addMutliCellWidget( maxLabel, 2, 2, 0, 0 );
displayLayout->addMutliCellWidget( mpMaxLineEdit, 2, 2, 1, 3 );

displayLayout->setColStretch( 0, 0 );
displayLayout->setColStretch( 1, 5 );
displayLayout->setColStretch( 2, 5 );

return true;
}


The only thing I see on my window is "Hello" which is right-aligned and immediately below it is the label "Bye" which is left-aligned. There is a small dot in between the two labels and I can see the splitter-icon and click and drag it but nothing is appearing inside the splitter which I believe my QGroupBox should be drawing inside. It's as if my GroupBox is not being drawn. Can you see what I am doing wrong? I feel like I am getting a better grasp on Qt 3 and can say I enjoy programming in Qt 4 on my own time better than this stuff! Thanks yet again!

Edit: I have also noticed that this area is just a tiny portion in the top-left of the QMainWindow. After I call createGUI( ) in my constructor I call resize( 800, 600 ) but the GUI doesn't seem to notice. How do I get mainFrame and all its children to recognize that they should fill the entire QMainWindow and not just a tiny portion in the top-left? If I resize the QMainWindow manually when the program is running, the window resizes but my labels don't seem to be affected by it at all. I am guessing this is another improvement from Qt 3 to Qt 4 but how I do I get it to behave the way I want in Qt 3? Thanks again!

Glitch
14th January 2007, 18:40
setCentralWidget( new QWidget( this ) )

Here in lies your problem. While Qt4 has a better API than Qt3, Qt3 was a very good toolkit. The issues you are seeing are problems with not following the Qt3 rules. This program would also be broken in Qt4.

The problem is your central widget has no layout and this does not know how to layout its childern. The children by default are bieing left in the upper lefthand corner. Same thing would happen in Qt4. You want to remove the above line and change:
QFrame *mainFrame = new QFrame( centralWidget( ) ) to
QFrame *mainFrame = new QFrame( this )

At the end of your createUI add
setCentralWidget(mainFrame);

Make sure every widget has a parent AND is added to a layout.

--Justin

ToddAtWSU
15th January 2007, 13:58
Thanks. I now realize that QtDesigner could do setCentralWidget( new QWidget( this ) ) because they use setGeometry( ) for everything. I made the changes you suggested (and how I had done it in Qt4) but I still don't see much changes. I resize my QMainWindow to 800x600 but stuff stays in the top-left. However, if I manually call resize( ) on mainFrame and layoutWidget and set them to 800x600 I start to see a lot more of my GUI. Is there a reason why I have to manually call resize to get my widgets to resize or is there a way to get the widgets to resize to fit the window automatically like they did in Qt4? Thanks again!

ToddAtWSU
16th January 2007, 13:45
I will post my last resize question under a different topic since it really has nothing to do with the groupboxes. Thanks for all your help!