1

I am working to create a GUI with Qt and C++.

I have create dynamically some couples of buddies (QLabel + QSpinBox) in order to refresh the number of errors that my program makes in the last thousand round to my loop.

My code to create this:

if((num_fotos % 1000) == 0){
    if(num_layouts < NUM_FAIL_COUNT){
        for(int i = 0; i < (buffer->length()-1); i++){
            sum_100_fallos += int(buffer->at(i));
        }
        QLabel * label_1000 = new QLabel();
        label_1000->setText("Fallos 1000_" + QString::number(num_fotos/1000) + ": ");
        label_1000->setMinimumHeight(24);
        QSpinBox * spinBox_1000 = new QSpinBox();
        //newElements->append(label_1000);
        spinBox_1000->setReadOnly(true);
        spinBox_1000->setRange(0, 1000);
        spinBox_1000->setMinimumHeight(24);
        new_layouts[num_layouts] = new QHBoxLayout;
        //newElements->append(spinBox_1000);
        new_layouts[num_layouts]->addWidget(label_1000);
        new_layouts[num_layouts]->addWidget(spinBox_1000);
        spinBox_1000->setValue(num_fallos_1000);
        num_fallos_1000 = 0;

        ui->verticalLayout_5->addLayout(new_layouts[num_layouts]);
        num_layouts++;
    }else{
        aux = num_layouts % NUM_FAIL_COUNT;
        delete new_layouts[aux];
        for(int i = 0; i < (buffer->length()-1); i++){
            sum_100_fallos += int(buffer->at(i));
        }
        QLabel * label_1000 = new QLabel();
        label_1000->setText("Fallos 1000_" + QString::number(num_fotos/1000) + ": ");
        label_1000->setMinimumHeight(24);
        QSpinBox * spinBox_1000 = new QSpinBox();
        //newElements->append(label_1000);
        spinBox_1000->setReadOnly(true);
        spinBox_1000->setRange(0, 1000);
        spinBox_1000->setMinimumHeight(24);
        new_layouts[aux] = new QHBoxLayout;
        //newElements->append(spinBox_1000);
        new_layouts[aux]->addWidget(label_1000);
        new_layouts[aux]->addWidget(spinBox_1000);
        spinBox_1000->setValue(num_fallos_1000);
        num_fallos_1000 = 0;

        ui->verticalLayout_5->addLayout(new_layouts[aux]);
        num_layouts++;
    }   
}

NUM_FAIL_COUNT is the numbers of (QLabels + QLineEdit) to show simultaneously. If there is less than NUM_FAIL_COUNT, I create new layouts and add them to the view.

View with NUM_FAIL_COUNT equals five

As you can see, this is what I am creating dynamically. But, if there are more than NUM_FAIL_COUNT, I want to remove the entire first layout, with its children in order to add the new one at the bottom. What happens is that the first layout is removed, but not its children, overlapping the QLabel + QLineEdit.

Overlapping in first couple of buddies

I have tried accessing to it by children() call, with pointers, deleteLater(), and trying to clearing layout previously to its deletion.

What am I thinking wrong? Thanks for your answer.

César HM
  • 198
  • 2
  • 16
  • You can `take` or `remove` from a `QLayout` if you have references to the previous items. – Mad Physicist May 23 '17 at 16:33
  • Ok.. and what about to remove all elements? I have the reference to the QLayout in new_layouts[aux] but cannot remove them.. – César HM May 23 '17 at 17:25
  • Why do you not reuse your `QLabel` and `QSpinBox`? – m7913d May 23 '17 at 19:31
  • Possible duplicate of [Qt - Clear all widgets from inside a QWidget's layout](https://stackoverflow.com/questions/22643853/qt-clear-all-widgets-from-inside-a-qwidgets-layout) – m7913d May 23 '17 at 20:30
  • I could reuse this pointers, but the result is the same. I am not sure if this is a duplicate of that question. I do not want to remove all my widgets, but only the first QLabel every loop. Anyway I am going to read deeper the answer to the other question in case it gives me any clue. – César HM May 24 '17 at 08:55

1 Answers1

0

You could create a QList and store pointers to the created QWidgets. Here is a minimal example:

mainwindow.hpp:

#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);

private:
    QList<QWidget*> widgets;
};

#endif // MAINWINDOW_HPP

mainwindow.cpp:

#include "mainwindow.hpp"
#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QVBoxLayout *mainLayout = new QVBoxLayout;
    QVBoxLayout *widgetLayout = new QVBoxLayout;
    QHBoxLayout *buttonLayout = new QHBoxLayout;
    QPushButton *add = new QPushButton("Add", this);
    QPushButton *remove = new QPushButton("Remove", this);
    buttonLayout->addWidget(add);
    buttonLayout->addWidget(remove);

    mainLayout->addLayout(widgetLayout);
    mainLayout->addLayout(buttonLayout);

    setCentralWidget(new QWidget(this));
    centralWidget()->setLayout(mainLayout);

    connect(remove, &QPushButton::clicked, [=](){
        if (widgets.size() > 0) {
            QWidget *widget = widgets.takeLast();
            widgetLayout->removeWidget(widget);

            widget->deleteLater();
        }
    });
    connect(add, &QPushButton::clicked, [=](){
        QWidget *widget = new QLabel("Test " + QString::number(widgets.size()), this);
        widgetLayout->addWidget(widget);
        widgets.append(widget);
    });
}

Best regards

  • Ok, that was helpful. The point is that I am executing this program in a while loop which starts with the play button on the image, and stops with the stop button. This loops ends with a "qApp->processEvents();" but still does not delete in real time the label, just when I click stop. – César HM May 24 '17 at 08:22
  • You can't solve it that way. Your loop is blocking, hence you'll only see the changes after everything is done. You should look for a solution using a worker thread and updating the UI from time to time. Something like that https://stackoverflow.com/questions/16501284/qt-updating-main-window-with-second-thread –  May 24 '17 at 15:43