nimrod
5th February 2006, 20:55
This is my first major project using Qt, and I have a bit of a problem.
I subclassed QMainWindow for my program, and got the layout and menus to work.
The layout is made of QSplitters and in the main view I have a QWidgetStack.
I wanted to keep the widget stack id's in integer variables, so I added two variables in the class definition,and tried:
widgetStackItemId=mainview->id(wigetPointer);
And later used:
mainview->raiseWidget(widgetStackItemId);
Now, this worked with one of the variables, but as soon as I tried using another variable, it started giving me segmentation faults.
At first, I thought it was related to the QWidgetStack, but it seems that as soon as I assign a value to the second variable (can be just a number), the program crashes with a seg fault.
I think I made a mistake with a pointer, but I don't know which one. Here is a code based on my real code. I changed variable and function names, and shortened some boring bits (menu items). The code works like that, I think the bug is a matter of scale.
Header (mymainwindow.h):
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <qmainwindow.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qsplitter.h>
#include <qlistbox.h>
#include <qtable.h>
#include <qscrollview.h>
#include <qwidgetstack.h>
#include <qstringlist.h>
#include <qtextedit.h>
class MyMainWindow: public QMainWindow
{
Q_OBJECT
public:
MyMainWindow(QWidget *parent=0,const char *name=0);
protected:
//CloseEvent is called whenever the user closes the program's window.
void CloseEvent(QCloseEvent *event);
private slots:
bool mnuFileQuit();
void mnuViewItem();
void leftPane1Changed();
private:
void initLayout();
void initMenus();
void createMainWidget1();
void createMainWidget2();
QSplitter *mainsplitter;
QSplitter *leftsplitter;
QWidgetStack *mainview;
QListBox *leftPane1;
QListBox *leftPane2;
//id's in the widget stack:
int widgetstackid1;
int widgetstackid2;
//Now actual menu items (rather than their functions) are defined:
QPopupMenu *fileMenu;
QPopupMenu *viewMenu;
};
#endif
Implementation:
#include "mymainwindow.h"
#include <qapplication.h>
MyMainWindow::MyMainWindow(QWidget *parent,const char *name):QMainWindow(parent,name){
widgetstackid1=0;
widgetstackid2=0; //In the real program, this line causes a seg fault.
initLayout();
initMenus();
}
void MyMainWindow::initLayout(){
mainsplitter=new QSplitter(Qt::Horizontal,this);
setCentralWidget(mainsplitter);
leftsplitter=new QSplitter(Qt::Vertical,mainsplitter);
leftPane1=new QListBox(leftsplitter);
leftPane1->insertItem("Item 0");
leftPane1->insertItem("Item 1");
connect(leftPane1,SIGNAL(currentChanged ( QListBoxItem * )),this,SLOT(leftPane1Changed()));
leftPane2=new QListBox(leftsplitter);
mainview=new QWidgetStack(mainsplitter);
createMainWidget1();
createMainWidget2();
}
void MyMainWindow::initMenus(){
fileMenu=new QPopupMenu (this);
viewMenu=new QPopupMenu(this);
fileMenu->insertItem("&Quit",this,SLOT(mnuFileQuit()));
viewMenu->insertItem("View Menu Item",this,SLOT(mnuViewItem()));
menuBar()->insertItem("&File",fileMenu);
menuBar()->insertItem("&View",viewMenu);
}
void MyMainWindow::createMainWidget1(){
QTable *mainWidget1Table = new QTable( 4, 2, mainview );
mainWidget1Table->setLeftMargin(0);
mainWidget1Table->setReadOnly(true);
QStringList labels;
labels.append("col 1");
labels.append("col 2");
int i;
for(i=0;i<2;i++){
mainWidget1Table->setColumnWidth(i,60);
}
mainWidget1Table->setColumnLabels(labels);
mainWidget1Table->setSorting(true);
mainview->addWidget(mainWidget1Table);
widgetstackid1=mainview->id(mainWidget1Table);
}
void MyMainWindow::createMainWidget2(){
QTextEdit *mainWidget2Text;
mainWidget2Text=new QTextEdit(mainview);
mainWidget2Text->setReadOnly(true);
mainWidget2Text->setText("<h1>hello</h1>world.");
mainview->addWidget(mainWidget2Text);
widgetstackid2=mainview->id(mainWidget2Text); //In the real program, this line causes a seg fault.
}
//Menu functions
void MyMainWindow::mnuViewItem(){
qWarning("mnuViewItem() called.");
}
bool MyMainWindow::mnuFileQuit(){
return (close(true));
}
void MyMainWindow::leftPane1Changed(){
int currentItem=leftPane1->currentItem();
switch(currentItem){
case 0:
mainview->raiseWidget(widgetstackid1);
break;
case 1:
mainview->raiseWidget(widgetstackid2);
break;
}
}
//Main program
int main(int argc,char *argv[]){
QApplication app(argc,argv);
MyMainWindow windowThing;
app.setMainWidget(&windowThing);
windowThing.show();
return app.exec();
}
I subclassed QMainWindow for my program, and got the layout and menus to work.
The layout is made of QSplitters and in the main view I have a QWidgetStack.
I wanted to keep the widget stack id's in integer variables, so I added two variables in the class definition,and tried:
widgetStackItemId=mainview->id(wigetPointer);
And later used:
mainview->raiseWidget(widgetStackItemId);
Now, this worked with one of the variables, but as soon as I tried using another variable, it started giving me segmentation faults.
At first, I thought it was related to the QWidgetStack, but it seems that as soon as I assign a value to the second variable (can be just a number), the program crashes with a seg fault.
I think I made a mistake with a pointer, but I don't know which one. Here is a code based on my real code. I changed variable and function names, and shortened some boring bits (menu items). The code works like that, I think the bug is a matter of scale.
Header (mymainwindow.h):
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <qmainwindow.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qsplitter.h>
#include <qlistbox.h>
#include <qtable.h>
#include <qscrollview.h>
#include <qwidgetstack.h>
#include <qstringlist.h>
#include <qtextedit.h>
class MyMainWindow: public QMainWindow
{
Q_OBJECT
public:
MyMainWindow(QWidget *parent=0,const char *name=0);
protected:
//CloseEvent is called whenever the user closes the program's window.
void CloseEvent(QCloseEvent *event);
private slots:
bool mnuFileQuit();
void mnuViewItem();
void leftPane1Changed();
private:
void initLayout();
void initMenus();
void createMainWidget1();
void createMainWidget2();
QSplitter *mainsplitter;
QSplitter *leftsplitter;
QWidgetStack *mainview;
QListBox *leftPane1;
QListBox *leftPane2;
//id's in the widget stack:
int widgetstackid1;
int widgetstackid2;
//Now actual menu items (rather than their functions) are defined:
QPopupMenu *fileMenu;
QPopupMenu *viewMenu;
};
#endif
Implementation:
#include "mymainwindow.h"
#include <qapplication.h>
MyMainWindow::MyMainWindow(QWidget *parent,const char *name):QMainWindow(parent,name){
widgetstackid1=0;
widgetstackid2=0; //In the real program, this line causes a seg fault.
initLayout();
initMenus();
}
void MyMainWindow::initLayout(){
mainsplitter=new QSplitter(Qt::Horizontal,this);
setCentralWidget(mainsplitter);
leftsplitter=new QSplitter(Qt::Vertical,mainsplitter);
leftPane1=new QListBox(leftsplitter);
leftPane1->insertItem("Item 0");
leftPane1->insertItem("Item 1");
connect(leftPane1,SIGNAL(currentChanged ( QListBoxItem * )),this,SLOT(leftPane1Changed()));
leftPane2=new QListBox(leftsplitter);
mainview=new QWidgetStack(mainsplitter);
createMainWidget1();
createMainWidget2();
}
void MyMainWindow::initMenus(){
fileMenu=new QPopupMenu (this);
viewMenu=new QPopupMenu(this);
fileMenu->insertItem("&Quit",this,SLOT(mnuFileQuit()));
viewMenu->insertItem("View Menu Item",this,SLOT(mnuViewItem()));
menuBar()->insertItem("&File",fileMenu);
menuBar()->insertItem("&View",viewMenu);
}
void MyMainWindow::createMainWidget1(){
QTable *mainWidget1Table = new QTable( 4, 2, mainview );
mainWidget1Table->setLeftMargin(0);
mainWidget1Table->setReadOnly(true);
QStringList labels;
labels.append("col 1");
labels.append("col 2");
int i;
for(i=0;i<2;i++){
mainWidget1Table->setColumnWidth(i,60);
}
mainWidget1Table->setColumnLabels(labels);
mainWidget1Table->setSorting(true);
mainview->addWidget(mainWidget1Table);
widgetstackid1=mainview->id(mainWidget1Table);
}
void MyMainWindow::createMainWidget2(){
QTextEdit *mainWidget2Text;
mainWidget2Text=new QTextEdit(mainview);
mainWidget2Text->setReadOnly(true);
mainWidget2Text->setText("<h1>hello</h1>world.");
mainview->addWidget(mainWidget2Text);
widgetstackid2=mainview->id(mainWidget2Text); //In the real program, this line causes a seg fault.
}
//Menu functions
void MyMainWindow::mnuViewItem(){
qWarning("mnuViewItem() called.");
}
bool MyMainWindow::mnuFileQuit(){
return (close(true));
}
void MyMainWindow::leftPane1Changed(){
int currentItem=leftPane1->currentItem();
switch(currentItem){
case 0:
mainview->raiseWidget(widgetstackid1);
break;
case 1:
mainview->raiseWidget(widgetstackid2);
break;
}
}
//Main program
int main(int argc,char *argv[]){
QApplication app(argc,argv);
MyMainWindow windowThing;
app.setMainWidget(&windowThing);
windowThing.show();
return app.exec();
}