PDA

View Full Version : Connecting different GUI sections



ajb
13th May 2009, 00:28
I'm currently learning Qt/C++, and trying to write an app which consists of the following widget structure:

A (main window)
- B (left panel)
--- C (multiple widgets based on QLabel - allows user to mock up an optical circuit)
- D (right panel)
--- E (line edit boxes on form, containing details of currently selected 'C')

When the user clicks on a particular instance of widget C, I'd like to update the various form elements in E with the details stored within the selected widget (e.g. ID code). What's the best way to connect the two GUI regions together to achieve this?

So far I've tried the following:

[1] - Signals/Slots: I've put the following into B:

connect(instanceOfC, SIGNAL(clicked(int ID)), parentWidget(), SLOT(updateID(int ID)));
Widget A contains the updateID() method, which contains the following code:

instanceOfD->instanceofE->setText(...);
When this line is executed, the application produces a segmentation fault.

[2] - I've put an eventFilter in A to catch MouseButtonPress events in C. I then get the same segmentation fault described above when I try to update the fields in E, and I also don't know how to transfer parameters stored in C this way.

I hope this makes some sense. Any suggestions would be greatly appreciated!

aamer4yu
13th May 2009, 05:39
First ,


connect(instanceOfC, SIGNAL(clicked(int ID)), parentWidget(), SLOT(updateID(int ID)));
You dont have to pass argument name in SIGNAL and SLOT, only the signature.. Like -



connect(instanceOfC, SIGNAL(clicked(int )), parentWidget(), SLOT(updateID(int )));

Second, some code would help us identify the problem better.

Third, if C is QLabel, does it have clicked() signal ? I guess clicked() is for QPushButton. :confused:

wagmare
13th May 2009, 07:59
in your C class re implement your mousepress event and emit your own signal as
emit setValue("IP"); which is setValue(const QString &) ..

in your E class connect


(C, SIGNAL(setValue(const QString &)), this, SLOT(getValue(const QString &)));

in slot of E class


::getValue(const QString &message)
setText(message);

faldzip
13th May 2009, 09:11
if you have seg fault here:


instanceOfD->instanceofE->setText(...);
that means that one of those pointers: "instanceOfD" or "instanceofE" is invalid, maybe you forgot about creating object with new or forgot that you have deleted it with delete. Pasting your code here would be helpful in finding the problem. Another thing is that debugger is the right tool to investigate such problems, so you can give it a try :]

ajb
13th May 2009, 11:47
Thanks very much for the advice! The segmentation faults were because I was accidentally reinitialising my objects in the constructor after defining them in the header - that's now fixed - thanks faldżip.

I've got it working now so that the code passes messages from C to E. However the current implementation is pretty inefficient, because I have to set up new connections for each new instance of C (the Mirror class). I've done it this way because I'm not sure how objects talk to each other - this way, B creates lots of C, and can communicate back to A which knows all about D and E, so it seemed the easiest place to set up the connections.

The relevant parts of the code are shown below. I like the idea of what wagmare suggested, i.e. putting the connection code into D/E to listen to any signals from C. I don't know how to implement this though, as I'm not sure how to tell D/E that C exists, and how to listen to any instance of C.

Here's the relevant code:

A (MainView - instantiated once)
- B (DesignView - instantiated once)
--- C (Mirror - lots of these, created by user - the main part of the app)
- D (PropertyView - instantiated once)
--- E (line edit boxes on form)

The idea of the app, a tool for designing optical mirror/lens arrangements, is that the user sets up as many instances of C as they want, links them together in a user-defined order, and can click on any instance of C to reveal their properties in E.

[A] MainView.h

class MainView : public QWidget
{
Q_OBJECT

public:
MainView(QWidget *parent = 0);

public slots:
void changeID(const QString &);

private:
PropertyView *propertypane;

};

[A] Mainview.cpp

MainView::MainView(QWidget *parent) : QWidget(parent)
{
QHBoxLayout *mainLayout = new QHBoxLayout;
DesignView *designpane = new DesignView(this);
propertypane = new PropertyView(this);
mainLayout->addWidget(designpane);
mainLayout->addWidget(propertypane);
setLayout(mainLayout);
}

void MainView::changeID(const QString &message)
{
propertypane->setID(message);
}

[B] DesignView.h

class DesignView : public QWidget
{
Q_OBJECT

public:
DesignView(QWidget *parent = 0);

};

[B] DesignView.cpp

DesignView::DesignView(QWidget *parent) : QWidget(parent)
{
QGridLayout *grid = new QGridLayout;
Mirror *firstMirror = new Mirror(this,0,1);
grid->addWidget(firstMirror,1,0);
setLayout(grid);

// have to do this for each mirror if defined here - not ideal...
connect(firstMirror, SIGNAL(setID(const QString &)), parentWidget(), SLOT(changeID(const QString &)) );
}

[C] Mirror.h

class Mirror : public QLabel
{
Q_OBJECT

public:
Mirror(QWidget *parent = 0);

signals:
void setID(const QString &);

private:
void mousePressEvent(QMouseEvent* event);
int intID;

};

[C] Mirror.cpp

Mirror::Mirror(QWidget *parent) : QLabel(parent)
{
// code to set up unique ID number
intID = ...;
}

void Mirror::mousePressEvent(QMouseEvent *event)
{
if ( event->buttons() == Qt::LeftButton )
{
// code to convert int to QString
QVariant v = intID;
strID = v.toString();
emit setID(strID);
}
}


[D] PropertyView.h

class PropertyView : public QWidget
{
Q_OBJECT

public:
PropertyView(QWidget *parent = 0);
void setID(QString strTest);

private:
QFormLayout *formLayout;
QLineEdit *idLineEdit;

};

[D] PropertyView.cpp

PropertyView::PropertyView(QWidget *parent) : QWidget(parent)
{
formLayout = new QFormLayout;
idLineEdit = new QLineEdit;
formLayout->addRow("ID:", idLineEdit);
setLayout(formLayout);
}

void PropertyView::setID(QString strID)
{
idLineEdit->setText(strID);
}


Finally [E] is the QLineEdit instance (idLineEdit).

Any thoughts? Thanks again for the advice so far. : )