PDA

View Full Version : How to work with the replaceWidget function from QGridLayout



KeineAhnung
29th April 2014, 12:08
Hi there,

I created a QGridLayout and willed it with several GroupBoxes. To update the boxes I planned to replace them since I could not find a possibility to change a label within the GroupBox that is part of the QGridLayout.
In the documentation I found this: QLayoutItem * QLayout::replaceWidget(QWidget * from, QWidget * to, Qt::FindChildOptions options = Qt::FindChildrenRecursively) but I do not understand it. *to is clear, this is my newly created widget but how do I get the *from widget? I know the position in the grid but there is no function that gives me a widget, they only give me items, which is not working.
Can anybody post some example code that shows how this function is used?

Thanks a lot!

anda_skoa
29th April 2014, 13:09
Can you elaborate why changing a label inside a groupbox would not work just because the groupbox is in a gridlayout?

Cheers,
_

KeineAhnung
29th April 2014, 13:47
Because they are created during a PushButton event:


propLabel[stationIndex] = new QLabel(updateStation(stationIndex));

And propLabel[sationIndex]->setText(updateStation(index)); in a different PushButton event does not work:


.../mainwindow.cpp:150: Fehler: no member named 'propLabel' in 'Ui::MainWindow'
ui->propLabel[activeIndex]->setText(updateStation(activeIndex));
~~ ^

anda_skoa
29th April 2014, 17:00
You are trying to address a list, vector or array inside the instance pointed to by "ui", which does not have a variable of the name "propLabel"

The code for creating the label works then you have that variable in some other instance.

Cheers,
_

KeineAhnung
29th April 2014, 17:36
Hi,

thanks _ for the support so far. I am completely lost here.

As I said the label is within a group box that is added to the grid layout here:


ui->cardLayout->addWidget(stationCard[stationIndex], stationIndex/4, stationIndex%4);

While the program runs these cards need to be updated but so far I was not able to find a way to do that. The only thing that worked was adding a new card to the same coordinates but I guess that stacks them rather than updating them. I was not able to figure out how this replaceWidget function works or how I can access on of the cards.

anda_skoa
29th April 2014, 18:41
Well, you seem to have all your station widgets (groupboxes) in a container named stationCard, probably an array, a vector or a list.

So given you have a stationIndex for which you want to update a label, you should always be able to get the station card for that index from that container.
If the class of the station card widget in there has a setter that internally accesses the label, then you should also be able to change the label's text.

Lets assume your station card widget it something like this


class StationCard : public QGroupBox
{
public:
void setStationName(const QString &name)
{
m_nameLabel->setText(name);
}

private:
QLabel *m_nameLabel;
};



stationCard[stationIndex]->setStationName(someStationNameString);


Cheers,
_

KeineAhnung
30th April 2014, 00:34
Hi _,

thanks for the hint. Actually I do not have a container. The stationCard is the widget and is passed directly to the layout, it is not stored in a container first. I guess the layout does not work as container...
As you suggested I will create a new class first and add this class to a vector and than have the vector displayed in the layout. Actually this was one of my questions I posted in another thread, how to combine different UI elements in a class.

anda_skoa
30th April 2014, 08:42
thanks for the hint. Actually I do not have a container. The stationCard is the widget and is passed directly to the layout, it is not stored in a container first. I guess the layout does not work as container...

The layout is a kind of container, just not as easily addressable by index.
But your code had stationCard (and previously propLabel) as a container, it is accessed by index in your code snippets.

Cheers,
_

KeineAhnung
30th April 2014, 09:36
So I tired to redo my code but either I get QLayout: Cannot add null widget to QGridLayout/cardLayout or the program crashes.

From the beginning. I created a new class StationCard. This class is based on the QGroupBox and adds a QLabel to it, right?
.h


#ifndef STATIONCARD_H
#define STATIONCARD_H

#include <QLabel>
#include <QGroupBox>
#include <QLayout>

class StationCard : public QGroupBox{
public:
StationCard();
QLabel *propLabel;

private:

};

#endif // STATIONCARD_H

.cpp


#include "stationcard.h"

StationCard::StationCard(){
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(propLabel, 10, Qt::AlignRight);
setLayout(layout);
}

In my main window .h I added the .h file of the new class and crated a vector:


QVector<StationCard*> stationVector;

In my main window .cpp I first want to fill my grid with empty cards:


stationVector.resize(8);
int k = 0;
for(int i = 0; i < 2; ++i){
ui->cardLayout->setRowMinimumHeight(i,200);
for(int j = 0; j < 4; ++j){
ui->cardLayout->setColumnMinimumWidth(j, 150);
ui->cardLayout->addWidget(stationVector[k], i, j);
k++;
}
}

But this already gives me QLayout: Cannot add null widget to QGridLayout/cardLayout and if I want to fill it, the program crashes. If I say stationVector.resize(8), does this not create an array with eight elements of my custom group box class? If I try to do stationVector[k] = new StationCard, it crashes right away. =(

Added after 5 minutes:



But your code had stationCard (and previously propLabel) as a container, it is accessed by index in your code snippets.
_
Actually no. I followed a tutorial here where they created several buttons using a for-loop. http://doc.qt.digia.com/4.4/layouts-basiclayouts.html

stampede
30th April 2014, 10:10
QLayout: Cannot add null widget to QGridLayout/cardLayout or the program crashes.
Because you have to create the label instance


StationCard::StationCard(){
QHBoxLayout *layout = new QHBoxLayout;

propLabel = new QLabel(/*parameters*/);

layout->addWidget(propLabel, 10, Qt::AlignRight);
setLayout(layout);
}

anda_skoa
30th April 2014, 10:15
As you found out yourself already, you need of course create instances of StationCard before you can add them.



stationVector[k] = new StationCard


You experience a crash because your StationCard constructor tries to add an uninitialized pointer (propLabel) to a layout.
Create a QLabel instance first :)

Cheers,
_

P.S.: you can do the StationCard in designer if you want to, just use the widget template for a designer form and add the "ui" pointer and related code lines manually to your class

KeineAhnung
30th April 2014, 10:44
Thanks for the help! Now the program is running and I can tackle the next step to connect the checkbox from the group box. As you can see I am missing a lot of the basic stuff but I am just not good at reading books. I always try to start in the middle...

anda_skoa
30th April 2014, 12:33
You can "forward" signals



class StationCard : public QGroupBox
{
signals:
void somethingToggled(bool on);
};


StationCard::StationCard()
{
connect(someCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(somethingToggled(bool)));
}


Cheers,
_