0

after spend hour's searching for a solution, to build a grid that dynamic adds and removes buttons it doesn't remove the previus ones when going to the next page.

I have search here, and found "some" solutions but they aren't working.

This is my code.

This is the code to fill a vector with myQpushButtons ( added 3 method that I needed on the button )

QString famId = ui->comboBox->itemData(index).toString();
if (vectButtons.size() > 0)
{
    vectButtons.clear();
}
int totalPerPage = gridRow * gridColl;
int countPage = 0;
int totalButtons = 0;
double counterProd = 1.0;
qDebug() << idbConnect.get_Familia(famId)->get_FamProd()->count();
for (pair<QString, Produto> prod : idbConnect.get_Familia(famId)->get_FamProd()->toStdMap())
{
    if (counterProd == totalPerPage)
    {
        countPage++;
        counterProd = 2.0;
        buttons = new myQPushButton();
        buttons->setText("Proximo");
        buttons->set_Tipo(1);
        buttons->set_Pagina((totalPerPage * countPage));
        connect(buttons,SIGNAL(released()),this,SLOT(handleButton()));
        vectButtons.push_back(buttons);
        // #####################################################
        buttons = new myQPushButton();
        buttons->setText("Anterior");
        buttons->set_Tipo(1);
        buttons->set_Pagina((totalPerPage * (countPage - 1)));
        connect(buttons,SIGNAL(released()),this,SLOT(handleButton()));
        vectButtons.push_back(buttons);
        // #####################################################
    }
    buttons = new myQPushButton();
    buttons->setText(prod.second.get_Nome());
    buttons->set_id_Prod(prod.first);
    buttons->set_Tipo(0);
    connect(buttons,SIGNAL(released()),this,SLOT(handleButton()));
    vectButtons.push_back(buttons);
    counterProd++;
    totalButtons++;
}
fillGrid(0);

This is the method to fill the grid, and then add to the layout of thw widget

void MainWindow::fillGrid(int start)
{
grid = new QGridLayout;
for (int i = 0; i < gridRow; i++)
{
    for (int y = 0; y < gridColl; y++)
    {
        grid->addWidget(vectButtons.at(start),i,y);
        start++;
    }
}
ui->widget->setLayout(grid);
ui->widget->repaint();
ui->widget->show();
}

And this one it is called when I click next or previus, to fill the grid with new buttons.

void MainWindow::replaceGrid(int start)
{
/*QLayout *temp;
temp = ui->widget->layout();
temp->deleteLater();
delete temp;
grid->deleteLater();
delete grid;
ui->widget->layout()->deleteLater();
delete ui->widget->layout();*/
removeLayout(ui->widget);
ui->widget->layout()->deleteLater();
delete ui->widget->layout();
grid = new QGridLayout;
for (int i = 0; i < gridRow; i++)
{
    for (int y = 0; y < gridColl; y++)
    {
        if (start < vectButtons.size())
        {
            grid->addWidget(vectButtons.at(start),i,y);
            start++;
        }
    }
}
ui->widget->setLayout(grid);
ui->widget->repaint();
ui->widget->show();
}

This one calls other method, to remove all items from the layout ( in this case a grid ) from the widget, since I saw this solution on this site, saying that we need to remove all items before deleting the layout of an widget.

void MainWindow::removeLayout(QWidget* widget)
{
QLayout* layout = widget->layout();
if (layout != 0)
{
    QLayoutItem *item;
    while ((item = layout->takeAt(0)) != 0)
    {
        layout->removeItem(item);
    }
    delete layout;
}
}

But this doesn't work, when I click next ( to remove all previus buttons and add new ones from the vector ) it will have them on beyend the new buttons don't know why, if I'm removing them and deleting the layout and adding a new one.

Any thought's on this?

Camadas
  • 509
  • 1
  • 5
  • 21

1 Answers1

2

You remove the items from the layout, but you don't delete the buttons. If you want to get rid of the buttons completely, you will have to delete them as well. Or you can just hide them, if you don't want to delete them (you can just do this, no point removing them from the layout if you do this, is there?). Otherwise they will be visible inside their parent widget. You can use QLayoutItem::widget to get the widget.

Maybe a better solution for you is to use QStackedLayout. Here is an example from the docs:

QWidget *firstPageWidget = new QWidget;
QWidget *secondPageWidget = new QWidget;
QWidget *thirdPageWidget = new QWidget;

QStackedLayout *stackedLayout = new QStackedLayout;
stackedLayout->addWidget(firstPageWidget);
stackedLayout->addWidget(secondPageWidget);
stackedLayout->addWidget(thirdPageWidget);

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(stackedLayout);
setLayout(mainLayout);

And to change the page of the stackedlayout using a QComboBox:

QComboBox *pageComboBox = new QComboBox;
pageComboBox->addItem(tr("Page 1"));
pageComboBox->addItem(tr("Page 2"));
pageComboBox->addItem(tr("Page 3"));
connect(pageComboBox, SIGNAL(activated(int)),
        stackedLayout, SLOT(setCurrentIndex(int)));

If you really need to remove the buttons from the layout, here is a small example how to do it:

centralWidget()->setLayout(new QVBoxLayout);
for(int i = 0; i < 10; i++)
{
    centralWidget()->layout()->addWidget(new QLabel(QString("LABEL%1").arg(i)));
}
QLayoutItem *item;
while((item= centralWidget()->layout()->takeAt(0)) != 0)
{
//        item->widget()->setHidden(true);
    item->widget()->setParent(0); // you can use this or setHidden... up to you
    delete item;
}
thuga
  • 12,601
  • 42
  • 52
  • That would not work, since it can have 1 page or 10 pages, and during the program they can add more buttons to the same family. Lets say that the last page of that family its full of buttons and I add a new one, I need to also create a new page for it. By deleting the layout and adding a new one would work perfect for what I want. And about the delete button I don't want that, I try it and remove the information of that button of the vector I just want it out of the layout, but still be on memory – Camadas Sep 24 '14 at 13:04
  • @user3310091 Then removing the buttons from the layout seems pointless. Just hide the buttons you don't need to be visible. When you remove widgets from the layout, they will still remain visible. When you add them to a layout it reparents them automatically. And when you remove them from the layout, they will remain visible inside the parent. You still need to hide them. I just don't get the point of removing them from the layout. Maybe if there is problems with the positions inside a grid layout. – thuga Sep 24 '14 at 13:11
  • Would not be more easy just to remove them ?!?! I can need them now, but not for the rest of the day, or I could need them all day. Thats why I want to have them on the vector, and call them only when I need them visible. Thats why I'm trying to delete them from the layout ( the grid that goes into the widget->layout ) and make a new grid for the next page – Camadas Sep 24 '14 at 13:19
  • @user3310091 If you really need to remove them from the layout, then do so. But remember to hide them as well (`button->setHidden(true);` or `layoutItem->widget()->setHidden(true);`). They will still remain visible even though they are not inside a layout. You don't need to put widgets inside a layout to have them visible. – thuga Sep 24 '14 at 13:20
  • So what is the diference BTW the hidden and the visibility? I need this to ocupy the less memory as possible, and goes fast, thats why I'm trying to but all buttons on the memory, so he doesn't create them every time I need them, I just have a vector with all the info ( including the next and previus button when needed ). Thats why I wanted to create the grid with just 25 buttons ( for example ) and only them inside an grid, the rest in memory just when I need to add on a grid and put them. Thats why I'm creating and deleting a grid on the fly, well at least trying hehe :D – Camadas Sep 24 '14 at 13:32
  • @user3310091 I added an example in my answer of how to remove widgets from a layout so that they don't remain visible. – thuga Sep 24 '14 at 13:39
  • By the way, if performance is an issue, have you thought of only having 25 buttons and instead of removing/adding them to a layout, just update the text(and other data you have) of the button? – thuga Sep 24 '14 at 13:48
  • Yep I did try to do a replace of the buttons ( build de default at beguin, and just replace them using the ui->grid->replaceWidget(oldButton, newButton); ) but did not work, don't know why. But yes the hide/show works like a charm, and to improve performance, I could build all grids at the beguining and just call them, but by doing this, to update them, If I add a new button to the middle of It I have to rebuild the grid again and vector ( lets say it have 500 products and I add 1 more I have to make 501 ) and not 25 like I wanted – Camadas Sep 24 '14 at 14:20