Scrollable view as TabWidget - c++

Here is my problem, I display Buttons and Labels manually with setGeometry() method.
MyClass which inherits from QWidget
Here is my code :
void MyClass::function() {
QLabel *imgP;
QLabel *name;
QPushButton *newConv;
QPixmap *profilPic;
std::stringstream ss;
int j = 0;
int i = 0;
for (int tmp = 0; tmp < 15; tmp++)
{
if (i % 7 == 0 && i != 0)
{
i = 0;
j++;
}
ss << "Username " << tmp;
name = new QLabel(tr(ss.str().c_str()), this);
name->setAlignment(Qt::AlignCenter);
name->setGeometry((30 * (i + 1) + 240 * i), (30 + 390 * j),
240, 60);
profilPic = new QPixmap("./gui/img/avatar1.png");
imgP = new QLabel(this);
imgP->setPixmap(profilPic->scaled(240, 240));
imgP->setGeometry((30 * (i + 1) + 240 * i), (90 + 390 * j),
240, 240);
newConv = new QPushButton(tr("Chat"), this);
newConv->setGeometry((30 * (i + 1) + 240 * i), (330 + 390 * j),
240, 60);
newConv->setFocusPolicy(Qt::NoFocus);
connect(newConv, SIGNAL(released()), this, SLOT(addTab()));
ss.str("");
ss.clear();
i++;
}
}
It may be a bit more complicated than it should, but it works just the way I wanted ..
it looks like this :
As you can see, the result is good, I have my contacts displayed, but the 15th element is hidden because the window is too small. So my question is :
How can I make a ScrollView when this happens ?
I already know QScrollArea, but I would have to work with QBoxLayout, and I don't think this will do the job.
Thanks for your help !
EDIT
This is my MainWidget class which displays the window :
class QTabBar;
MainWidget::MainWidget(QWidget *parent) : QWidget(parent)
{
setFixedSize(1920, 1200);
setWindowTitle(tr("Babel"));
QVBoxLayout *mainLayout = new QVBoxLayout;
QTabBar *tb;
UiContact *contact = new UiContact(this);
QScrollArea *contactScrollArea = new QScrollArea();
contactScrollArea->setWidget(contact);
_tabWidget = new QTabWidget;
tb = _tabWidget->tabBar();
_tabWidget->addTab(new Home(), tr("Home"));
_tabWidget->addTab(contactScrollArea, tr("Contact"));
std::ostringstream oss;
_tabWidget->setTabsClosable(true);
connect(_tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
tb->tabButton(0, QTabBar::RightSide)->hide();
tb->tabButton(1, QTabBar::RightSide)->hide();
_tabWidget->setFocusPolicy(Qt::NoFocus);
mainLayout->addWidget(_tabWidget);
setLayout(mainLayout);
}

QScrollArea is certainly the way to go. It is not necessary to use a layout, it's only necessary to force the widget to be the size it needs to be. A QScrollArea can handle any QWidget derived class, and it will display its scrollbars as needed.
Practically: if you can calculate how much space you need (which I think you can do), and set the size constraints of the containing widget accordingly, the QScrollArea will show the scrollbars automatically. You can use QWidget::setMinimumSize for that purpose, a simple setMinimumSize(itemWidth*7,itemHeight*(count%7)) should suffice.
This method does allow the widget to grow as large as to fill the QScrollArea. Also, it's possible to disable the frame around the QScrollArea if preferred.
edit:
You probably have something like this:
MyClass *myClass = new MyClass();
...
tabs->insertTab(1,myClass,"Contact");
An example implementation in that situation would be:
MyClass *myClass = new MyClass();
...
QScrollArea* contactScrollArea = new QScrollArea();
contactScrollArea->setWidget(myClass);
tabs->insertTab(1,contactScrollArea,"Contact");
It will place a scroll area inside the tab widget and put the instance of MyClass inside it
A QScrollArea is used as a relatively high container class. Think of a QScrollArea as a widget which can embed another widget inside it. By default it creates an empty widget, which can get a layout. But by using setWidget, you can literally place anything you want in it. A possible "combination" is a QLabel with a large licence text or any other widget that can potentially grow too large (like your widget).
Now, just some extra information:
When you draw stuff yourself (not creating several widgets and code your own layout stuff), you may use QAbstractScrollArea. It would give you full control. It gives scrollbars and a separate middle widget to which you can draw during paintEvent. But I think that's beyond the scope of this.
Now, for sake of clean coding. I would actually suggest you create a separate class ContactItem. It would consist of that label, image and pushbutton, held together with a QVBoxLayout (which makes them neatly packed above eachother). This "item" can be put inside a QGridLayout. This way, you don't need to concern yourself with arranging the items. If you set a minimum size on the picture, it will make sure the items are your preferred width/height. The label size constraints make sure that font differences don't affect the presentation (same goes for the buttons). Last but not least, your list is suddenly resizable. (By using setRowStretch and setColumnStretch you can make sure your list is centered, or top aligned, in case the window is larger than your list takes up.
Functional interpretation
Here I have a possible implementation (it isn't my best code) from what I got from the screenshot and given code.
It consists of a 'Widget' which is responsible for the tab layout:
mainwidget.h
#include <QWidget>
#include "uicontact.h"
class QTabWidget;
class MainWidget : public QWidget
{
Q_OBJECT
QTabWidget *_tabWidget;
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
public slots:
void addChatTab();
};
mainwidget.cpp
#include "mainwidget.h"
#include <QScrollArea>
#include <QTabWidget>
#include <QTabBar>
#include <QVBoxLayout>
#include "home.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(1920,1200);
setWindowTitle(tr("Babel"));
QVBoxLayout *mainLayout = new QVBoxLayout;
QTabBar *tb;
UiContact *contact = new UiContact(this);
QScrollArea *contactScrollArea = new QScrollArea();
contactScrollArea->setWidget(contact);
_tabWidget = new QTabWidget;
tb = _tabWidget->tabBar();
_tabWidget->addTab(new Home(), tr("Home"));
_tabWidget->addTab(contactScrollArea, tr("Contact"));
_tabWidget->setTabsClosable(true);
connect(_tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
tb->tabButton(0, QTabBar::RightSide)->hide();
tb->tabButton(1, QTabBar::RightSide)->hide();
_tabWidget->setFocusPolicy(Qt::NoFocus);
mainLayout->addWidget(_tabWidget);
setLayout(mainLayout);
}
MainWidget::~MainWidget()
{
}
void MainWidget::addChatTab()
{
_tabWidget->addTab(new QWidget, tr("Number %1").arg(_tabWidget->count()-2));
}
The class MyClass is responsible for creating the 'contact' tab:
uicontact.cpp
#include "uicontact.h"
#include "mainwidget.h"
#include <QLabel>
#include <QPushButton>
UiContact::UiContact(MainWidget *owner,QWidget *parent) : QWidget(parent)
{
QLabel *imgP;
QLabel *name;
QPushButton *newConv;
QPixmap *profilPic;
int j = 0;
int i = 0;
for (int tmp = 0; tmp < 15; tmp++)
{
if (i % 7 == 0 && i != 0)
{
i = 0;
j++;
}
name = new QLabel(tr("Username %1").arg(tmp), this);
name->setAlignment(Qt::AlignCenter);
name->setGeometry((30 * (i + 1) + 240 * i), (30 + 390 * j),
240, 60);
profilPic = new QPixmap("./gui/img/avatar1.png");
imgP = new QLabel(this);
imgP->setPixmap(profilPic->scaled(240, 240));
imgP->setGeometry((30 * (i + 1) + 240 * i), (90 + 390 * j),
240, 240);
newConv = new QPushButton(tr("Chat"), this);
newConv->setGeometry((30 * (i + 1) + 240 * i), (330 + 390 * j),
240, 60);
newConv->setFocusPolicy(Qt::NoFocus);
connect(newConv, SIGNAL(clicked(bool)), owner, SLOT(addChatTab()));
i++;
}
setMinimumSize(270*7,420*(15/7+1));
}
The uicontact.h file is very trivial so omitted.
A few things to note: MyClass receives an 'owner' pointer, this allows it to talk directly to the top level widget responsible for adding tabs. Probably you want to look at QSignalMapper to be able to map the individual QPushButtons to a more known value. With QSignalMapper, you can map the button to an integer, string, QWidget* or QObject*.
Also note the tr("Contact %1").arg(tmp) which is the correct way to make your program locale aware.

Related

QListWidget items consistent positioning problem

I'm new to Qt framework. In new application I want to create list with customised items. These items are quite simple and must contain title label, thumbnail and description label (picture here)
For now I don't want to play with custom drawing and all that stuff becuase I think it's easier to do items I want with proper widget/layout so I decided to use QListwidget and subclassed QAbstractItemModel (KeyframeModel) and QListWidgetItem (TileWidgetItem).
After some coding it looks how I wanted but strange thing happens to QListWidget (grid mode) when I add some items. In my case a QListWidget is resizable (due to how it's embedded inside main layout) and number of columns should be dependent on list and items width. Items are fixed size (at least for now).
But when I resize the list one of the items at some list's width is misaligned and not I don't know what's going on. Below are te screenshots from app:
Pic. 1 List initial state (right after start)
Pic. 2 List after resizing #1
Pic. 3 List after resizing #2
Resizing #2 is a few pixels wider than resizing #1 and resizing #1 is hard to get (border case) - few pixels width less and I've got 2 columns (it's okay) but some pixels more and I end up with case #2.
In all cases number of columns is okay.
Sometimes also last item is misaligned after program start right-away like here (right after start like in pic. 1 but as you can see different result despite same list width).
I wonder why is it so inconsistent after start-up.
Do I missing something? Do I must do some parts in different way?
Or is it just some glitches in debug mode?
Below I post some code:
Application:
// Source file
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
//--------------------------------------------------------------------------------
// Add elements to the list
TileWidgetItem *item = new TileWidgetItem();
item->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Long title"));
item->setData(TileWidgetItem::TileRole::DescriptionRole, QVariant("My long info"));
item->setText("My super text");
qDebug() << "Widget size hint: " << item->sizeHint();
ui.listWidget_moves->addItem(item);
item->updateView();
TileWidgetItem *item1 = new TileWidgetItem();
item1->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Item #2"));
item1->setText("Tile #2");
ui.listWidget_moves->addItem(item1);
item1->updateView();
TileWidgetItem *item2 = new TileWidgetItem();
ui.listWidget_moves->addItem(item2);
item2->updateView();
TileWidgetItem *item3 = new TileWidgetItem();
ui.listWidget_moves->addItem(item3);
item3->updateView();
//--------------------------------------------------------------------------------
// Adjust cell size
QSize cellSize;
for (uint i = 0; i < ui.listWidget_moves->count(); i++)
{
int dim = ui.listWidget_moves->item(i)->sizeHint().height();
if (dim > cellSize.height())
cellSize.setHeight(dim);
dim = ui.listWidget_moves->item(i)->sizeHint().width();
if (dim > cellSize.width())
cellSize.setWidth(dim);
}
ui.listWidget_moves->setGridSize(cellSize);
}
Item widget:
// Source file
constexpr int MAX_THUMB_SIZE = 100;
TileWidgetItem::TileWidgetItem(QListWidget *listview)
: QListWidgetItem(listview, ItemType::UserType)
{
/* Prepare main widget */
QWidget *view = new QWidget();
view->setObjectName("tile");
view->setStyleSheet(
"QWidget#tile { margin: 4 8; background-color: #404040; border: 1 solid rgba(0,0,0,30%); border-radius: 4px }\n"
"QWidget#tile::hover { border: 1 solid #EEE; background-color: #484848 }\n"
"QWidget#tile[selected=true] { background-color: #00F }"
);
//-----------------------------------------------------------
/* Prepare layout */
QVBoxLayout *layout = new QVBoxLayout();
layout->setSizeConstraint(QLayout::SizeConstraint::SetFixedSize);
//-----------------------------------------------------------
/* Prepare title with icon */
QHBoxLayout *titleLayout = new QHBoxLayout();
QLabel *titleIcon = new QLabel();
titleIcon->setObjectName("titleIcon");
titleIcon->setStyleSheet("background-color: black");
titleIcon->setFixedSize(QSize(16, 16));
titleLayout->addWidget(titleIcon);
QLabel *title = new QLabel("Title");
title->setObjectName("title");
title->setMinimumWidth(60);
title->setStyleSheet("background-color: #800;");
titleLayout->addWidget(title);
QWidget *titleWidget = new QWidget();
titleWidget->setStyleSheet("background-color: #080");
titleWidget->setLayout(titleLayout);
layout->addWidget(titleWidget);
//-----------------------------------------------------------
/* Prepare thumbnail */
QLabel *thumbnail = new QLabel();
thumbnail->setObjectName("thumbnail");
thumbnail->setStyleSheet("background-color: black; border: 1 solid #F00");
thumbnail->setFixedSize(QSize(MAX_THUMB_SIZE, MAX_THUMB_SIZE * 0.7f));
thumbnail->setPixmap(QPixmap("Resources/moto.jpg").scaledToWidth(MAX_THUMB_SIZE));
layout->addWidget(thumbnail);
//-----------------------------------------------------------
/* Preparing additional info */
QLabel *description = new QLabel("Description");
description->setObjectName("description");
//description->setToolTip("Custom info tip");
description->setContentsMargins(4, 2, 4, 2);
layout->addWidget(description);
//-----------------------------------------------------------
view->setLayout(layout);
_customView = view;
_titleView = title;
_descriptionView = description;
setSizeHint(_customView->sizeHint());
updateView();
}
TileWidgetItem::~TileWidgetItem()
{
}
void TileWidgetItem::setData(int role, const QVariant &value)
{
QListWidgetItem::setData(role, value);
if (value.type() == QVariant::Type::String)
{
if (role == TileRole::TitleRole)
{
this->_titleView->setText(value.toString());
}
else if (role == TileRole::DescriptionRole)
{
this->_descriptionView->setText(value.toString());
}
setSizeHint(_customView->sizeHint());
}
}
void TileWidgetItem::updateView()
{
if (listWidget() != nullptr)
{
listWidget()->setItemWidget(this, this->_customView);
}
}
// Header file
class TileWidgetItem : public QListWidgetItem
{
public:
enum TileRole
{
TitleRole = Qt::UserRole + 1,
DescriptionRole,
ThumbnailRole
};
public:
TileWidgetItem(QListWidget *listview = nullptr);
~TileWidgetItem();
void setData(int role, const QVariant &value) override;
void updateView();
QWidget *customView() const { return _customView; };
QString getTitle() const { return _titleView->text(); };
QString getInfo() const { return _descriptionView->text(); };
private:
QWidget *_customView;
QLabel *_titleView;
QLabel *_descriptionView;
};
Platform: Windows 10
Qt version: 5.14.2
IDE: Visual Studio 2019 (with Qt VS Tools)
In the end I just used custom delegates which solved problems.
I wanted to overuse system and in I was defeated :)

Setting minimum width of QPushButton while keeping default minimumSizeHint behavior

In my application, I need all QPushButtons to have a width of at least 150px, but bigger if needed.
To do so, I am using a global stylesheet (which contains many other properties) with this simple constraint :
QPushButton {
min-width: 150px;
}
The thing is, I also want buttons with a text that doesn't fit inside 150px to be unable to shrink to a width below which the whole text wouldn't be displayed.
This is supposed to be the normal behavior for a QPushButton, but the problem is that, as explained in the documentation for minimumSizeHint() :
QLayout will never resize a widget to a size smaller than the minimum size hint unless minimumSize() is set or the size policy is set to QSizePolicy::Ignore. If minimumSize() is set, the minimum size hint will be ignored.
This leads to some cases where buttons with long texts are displayed at the right size at startup, but when shrinking the window, the button gets too small to display all the text.
I have prepared a simple example that shows this behavior :
#include <QWidget>
#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *w = new QWidget();
QLayout* layout = new QHBoxLayout(w);
QPushButton* buttonA = new QPushButton("A", w);
QPushButton* buttonB = new QPushButton("B", w);
buttonB->setStyleSheet("min-width: 150px");
QPushButton* buttonC = new QPushButton("Long long text that doesn't fit in 150px", w);
QPushButton* buttonD = new QPushButton("Very very very long text that doesn't fit in 150px", w);
buttonD->setStyleSheet("min-width: 150px");
layout->addWidget(buttonA);
layout->addWidget(buttonB);
layout->addWidget(buttonC);
layout->addWidget(buttonD);
w->show();
return a.exec();
}
I thought about using dynamic properties to set the minimum width constraint only to buttons that have a base width < 150px, but this doesn't seem to be doable.
Is there a way to do what I want with stylesheets, or do I have to subclass QPushButton and override the minimumSizeHint() method (which I'd like to avoid as I would have to replace a lot of buttons in my app)?
It would be better if you sub-class QPushButton. But there are 2 work around for this problem:
You can strip the long text to specific numbers of characters and use setToolTip(QString) function to show full text when mouse will enter the button.
You can override parent widget resizeEvent and can check the widths and go for approach number 1 if the size is getting really small.
Use Elide Text example to get idea about elide for QPushButton. Not sure if this will work.
I haven't been able to find a way to do this using only stylesheets, but here is the solution I came up with by subclassing QPushButton
MyPushButton.h
#include <QPushButton>
class MyPushButton
: public QPushButton
{
Q_OBJECT
Q_PROPERTY(int minWidth READ minWidth WRITE setMinWidth)
public:
MyPushButton(QWidget* parent = nullptr);
virtual ~MyPushButton();
int minWidth() const;
void setMinWidth(int width);
virtual QSize minimumSizeHint() const override;
private:
int _minWidth;
};
MyPushButton.cpp
#include "MyPushButton.h"
MyPushButton::MyPushButton(QWidget* parent)
: QPushButton(parent)
, _minWidth(0)
{
}
MyPushButton::~MyPushButton()
{
}
int MyPushButton::minWidth() const
{
return _minWidth;
}
void MyPushButton::setMinWidth(int width)
{
_minWidth = width;
}
QSize MyPushButton::minimumSizeHint() const
{
// if the minimum width is less than minWidth, set it to minWidth
// else return the default minimumSizeHint
return QSize(qMax(QPushButton::minimumSizeHint().width(), _minWidth),
QPushButton::minimumSizeHint().height());
}
stylesheet.qss
MyPushButton {
qproperty-minWidth: 150;
}
Buttons with a minimumSizeHint width lower than 150px will be forced to that size, bigger ones will keep the default behavior of QPushButton.

Add HMI in QScrollArea, but ScrollArea won't scroll

in my project, I have a QScrollArea in a QTabWidget , in this QTabWidget i had few IHM. I would like to put two IHM per line, and when you arrive at the end of QTabWidget , the scrollbar scroll .
This is my class diagram :
My code in MainWindow where i created the QScrollBar :
//Here I create the QScrollArea
QScrollArea *scrollArea = new QScrollArea();
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//I had the QScrollBar in the Tab of my QTabWidget
ui->tabWidget->addTab(scrollArea,"Plateau " + ControleSpecial.at(i).toElement().attribute("ID"));
//I call my class Plateau (i'm french ^^)
Plateau *plt = new Plateau(ui->tabWidget);
plt->Rajouter(ControleSpecial.at(i),scrollArea,ui->InfoPlt,column,row);
this->nPlateau.append(plt);
My class Analyse , where i had this IHM :
the code :
{
//I create the layout and ScrollWidget
QGridLayout *layout = new QGridLayout;
QWidget *scrollwidget = new QWidget;
int row = 0;
int column = 0;
QDomNode Analyse;
for(int i=1;i<plateau.childNodes().count()+1;++i)
{
Analyse = plateau.childNodes().at(i-1);
QString nomAnalyse = Analyse.toElement().attribute("Type");
vTypeAnalyse.append(nomAnalyse);
if(nomAnalyse == "Traction_Perpendiculaire")
{
Traction_Perpendiculaire* TP = new Traction_Perpendiculaire();
QGroupBox* analyse = TP->recuperationAnalyse();
//I add the analyse IHM in the layout
layout->addWidget(TP,row,column);
//I don't think my problem it's here
vButtonAnalyse.append(TP->recuperationButton());
connect(vButtonAnalyse[vButtonAnalyse.size()-1],SIGNAL(clicked()),this,SLOT(Recuperation()));
vButtonAnalyse[vButtonAnalyse.size()-1]->setAccessibleName(QString::number(i-1));
Eprouvette *blocEprouvette = new Eprouvette(analyse);
this->vbloceprouvette.append(blocEprouvette);
blocEprouvette->Rajouter(Analyse);
}
if(i%2 == 0)
{
column = 0;
row += 1;
}
else
{
column += 1;
}
}
//And I had the layout in scrollWidget and ScrollWidget in scrollArea
scrollwidget->setLayout(layout);
scrollArea->setWidget(scrollwidget);
//tab->widget(index)
}
And i obtain that:
So if you have any ideas , any ideas would be well come.
Thank you in advance. (sorry for my bad english)
Ok so , when i had the HMI in the layout it's don't work but when i had the QGroupBox it's work. So i resolve it like this :
layout->addWidget(TP,row,column);
//to :
layout->addWidget(TP->MyGroupBox(),row,column);

Spacing between widgets in QHBoxLayout

I'm trying to create a GUI with QtCreator. For this GUI, I need to display several images with different sizes next to each other. These images should be touching each other.
I use a QWidget with a QHBoxLayout, where I add the labels (with different sizes) containing the images.
According to related questions, I should use setSpacing and setContentsMargin to remove these spaces, but that won't work; I tried several times.
Here's the code:
QWidget *widget = new QWidget(ui->tagcloud);
QHBoxLayout * l = new QHBoxLayout(widget);
ui->tagcloud->setWidget(widget);
for(int i=0;i<list.size();++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
l->setSpacing(0);
}
However, when I run this, the spacing remains the same (i.e. definitely not zero).
If I add more labels to the layout, the spacing seems to get smaller.
Can anyone explain or help me? Thanks!
Setting spacing to 0 and adding stretch before and after works for me :
l->addStretch();
for(int i = 0; i < list.size(); ++i)
{
QLabel *lab = new QLabel;
QPixmap pic((list[i].imgPath).c_str()); //This fetches the image
int sizeChange = 50 + (2*list[i].percent); //Calculates the size of the image
lab->setFixedSize(QSize(sizeChange, sizeChange));
lab->setPixmap(pic);
lab->setScaledContents(true);
l->addWidget(lab);
}
l->addStretch();
l->setSpacing(0);
Also this works I think
l->setSizeConstraint(QLayout::SetMaximumSize);

Delete A Row From QGridLayout

All, I am maintaining a QGridLayout of QLabels which show the coefficients of a polynomial. I represent my polynomial using QList<double>.
Each time I update my coefficients, I update my labels. When changing the size of the list, my method does not works well. QGridLayout::rowCount() doesn't update correctly. I am wondering if there's a way to remove rows from a QGridLayout.
Code follows, updating the QGridLayout size with more (or less) QLabels
int count = coefficients->count(); //coefficients is a QList<double> *
if(count != (m_informational->rowCount() - 1)) //m_information is a QGridLayout
{
SetFitMethod(0);
for(int i = 0; i < count; ++i)
{
QLabel * new_coeff = new QLabel(this);
new_coeff->setAlignment(Qt::AlignRight);
m_informational->addWidget(new_coeff, i+1, 0);
QLabel * param = new QLabel(this);
param->setAlignment(Qt::AlignLeft);
param->setText(QString("<b><i>x</i><sup>%2</sup></b>").arg(count-i-1));
m_informational->addWidget(param, i+1, 1);
QSpacerItem * space = new QSpacerItem(0,0,QSizePolicy::Expanding);
m_informational->addItem(space, i+1, 1);
}
m_informational->setColumnStretch(0, 3);
m_informational->setColumnStretch(1, 1);
m_informational->setColumnStretch(2, 1);
}
The SetFitMethod (it's an initial mockup)
void SetFitMethod(int method)
{
ClearInformational();
switch(method)
{
case 0: //Polynomial fit
QLabel * title = new QLabel(this);
title->setText("<b> <u> Coefficients </u> </b>");
title->setAlignment(Qt::AlignHCenter);
m_informational->addWidget(title,0,0,1,3, Qt::AlignHCenter);
}
}
The Clearing Method:
void ClearInformational()
{
while(m_informational->count())
{
QLayoutItem * cur_item = m_informational->takeAt(0);
if(cur_item->widget())
delete cur_item->widget();
delete cur_item;
}
}
The issue is that QGridLayout::rowCount() doesn't actually return the number of rows that you can see, it actually returns the number of rows that QGridLayout has internally allocated for rows of data (yes, this isn't very obvious and isn't documented).
To get around this you can either delete the QGridLayout and recreate it, or if you're convinced that your column count won't change, you can do something like this:
int rowCount = m_informational->count()/m_informational->columnCount();
I solved this by creating a QVBoxLayout (for rows) and within this I was adding QHBoxLayout (for columns). In the QHBoxLayout I was then inserting my widgets (in one row). This way I was able to nicely remove rows - overall row count was working as it should be. Additionally to this I got also an insert method, thanks to which I was able to insert new rows into specific locations (everything was correctly reordered/renumbered).
Example (only from head):
QVBoxLayout *vBox= new QVBoxLayout(this);
//creating row 1
QHBoxLayout *row1 = new QHBoxLayout();
QPushButton *btn1x1 = new QPushButton("1x1");
QPushButton *btn1x2 = new QPushButton("1x2");
row1->addWidget(btn1x1);
row1->addWidget(btn1x2);
//adding to vBox - here you can use also insertLayout() for insert to specific location
vBox->addlayout(row1);
//creating row 2
QHBoxLayout *row2 = new QHBoxLayout();
QPushButton *btn2x1 = new QPushButton("2x1");
QPushButton *btn2x2 = new QPushButton("2x2");
row2->addWidget(btn2x1);
row2->addWidget(btn2x2);
//adding to vBox - here you can use also insertLayout() for insert to specific location
vBox->addlayout(row2);
Well, my solution was to also delete the QGridLayout in ClearInformational