Динамический QGridLayout для QPushButton С++

после часового поиска решения, чтобы построить сетку, которая динамически добавляет и удаляет кнопки, она не удаляет предыдущие при переходе на следующую страницу.

У меня есть поиск здесь, и я нашел «некоторые» решения, но они не работают.

Это мой код.

Это код для заполнения вектора myQpushButtons (добавлено 3 метода, которые мне нужны для кнопки)

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);

Это способ заполнить сетку, а затем добавить ее в макет виджета.

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();
}

И этот он вызывается, когда я нажимаю следующий или предыдущий, чтобы заполнить сетку новыми кнопками.

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();
}

Этот вызывает другой метод, чтобы удалить все элементы из макета (в данном случае сетки) из виджета, так как я видел это решение на этом сайте, в котором говорится, что нам нужно удалить все элементы перед удалением макета виджета.

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;
}
}

Но это не работает, когда я нажимаю «Далее» (чтобы удалить все предыдущие кнопки и добавить новые из вектора), они будут включены, кроме новых кнопок, не знаю почему, если я удалю их и удалю макет и добавление нового.

Любые мысли по этому поводу?


person Camadas    schedule 24.09.2014    source источник


Ответы (1)


Вы удаляете элементы из макета, но не удаляете кнопки. Если вы хотите полностью избавиться от кнопок, вам придется удалить и их. Или вы можете просто скрыть их, если вы не хотите их удалять (вы можете просто сделать это, нет смысла удалять их из макета, если вы это сделаете, не так ли?). В противном случае они будут видны внутри своего родительского виджета. Вы можете использовать QLayoutItem::widget, чтобы получить виджет.

Возможно, лучшим решением для вас будет использовать QStackedLayout. Вот пример из документации:

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);

И чтобы изменить страницу stackedlayout с помощью 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)));

Если вам очень нужно убрать кнопки из макета, вот небольшой пример, как это сделать:

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;
}
person thuga    schedule 24.09.2014
comment
Это не сработает, так как у него может быть 1 страница или 10 страниц, и во время программы они могут добавить больше кнопок в одно и то же семейство. Предположим, что последняя страница этого семейства полна кнопок, и я добавляю новую, мне также нужно создать для нее новую страницу. Удаление макета и добавление нового идеально подойдет для того, что я хочу. А по поводу кнопки удалить не хочу, пробую и убрать информацию той кнопки вектора хочу просто из лейаута, но все равно на память - person Camadas; 24.09.2014
comment
@ user3310091 Тогда удаление кнопок из макета кажется бессмысленным. Просто скройте кнопки, которые не должны быть видны. Когда вы удаляете виджеты из макета, они все равно остаются видимыми. Когда вы добавляете их в макет, он автоматически переустанавливает их. И когда вы удалите их из макета, они останутся видимыми внутри родителя. Вам все равно нужно их спрятать. Я просто не понимаю смысла удалять их из макета. Может быть, если есть проблемы с позициями внутри макета сетки. - person thuga; 24.09.2014
comment
Не проще ли было бы просто их удалить?!?! Они могут понадобиться мне сейчас, но не до конца дня, или они могут понадобиться мне весь день. Вот почему я хочу, чтобы они были в векторе, и вызываю их только тогда, когда они мне нужны. Вот почему я пытаюсь удалить их из макета (сетка, которая входит в виджет-›макет) и создать новую сетку для следующей страницы. - person Camadas; 24.09.2014
comment
@ user3310091 Если вам действительно нужно удалить их из макета, сделайте это. Но не забудьте скрыть и их (button->setHidden(true); или layoutItem->widget()->setHidden(true);). Они по-прежнему останутся видимыми, даже если они не находятся внутри макета. Вам не нужно размещать виджеты внутри макета, чтобы они были видны. - person thuga; 24.09.2014
comment
Так в чем разница между скрытым и видимым? Мне это нужно, чтобы занимать как можно меньше памяти и ходить быстро, вот почему я пытаюсь, но все кнопки в памяти, чтобы он не создавал их каждый раз, когда они мне нужны, у меня просто есть вектор со всеми информация (включая следующую и предыдущую кнопки, когда это необходимо). Вот почему я хотел создать сетку всего с 25 кнопками (например), и только они внутри сетки, остальные в памяти, когда мне нужно добавить в сетку и поместить их. Вот почему я создаю и удаляю сетку на лету, ну, по крайней мере, пытаюсь, хе-хе :D - person Camadas; 24.09.2014
comment
@user3310091 user3310091 Я добавил в свой ответ пример того, как удалить виджеты из макета, чтобы они не оставались видимыми. - person thuga; 24.09.2014
comment
Кстати, если производительность является проблемой, вы думали о том, чтобы иметь только 25 кнопок и вместо того, чтобы удалять/добавлять их в макет, просто обновлять текст (и другие данные, которые у вас есть) кнопки? - person thuga; 24.09.2014
comment
Да, я пытался заменить кнопки (соберите по умолчанию в beguin и просто замените их с помощью ui-›grid-›replaceWidget(oldButton, newButton); ), но не сработало, не знаю почему. Но да, скрытие/показ работает как шарм, и для повышения производительности я мог бы построить все сетки в начале и просто вызвать их, но, сделав это, чтобы обновить их, если я добавлю новую кнопку в середину. нужно снова перестроить сетку и вектор (скажем, у него 500 продуктов, и я добавляю еще 1, я должен сделать 501), а не 25, как я хотел - person Camadas; 24.09.2014