I am new to QtCreator. I am trying to make a slider and dynamically remove and recreate labels when I move the slider. I am able to create labels dynamically when I call it from constructor, but for some reason when I do the same via moving he slider it does not work.
I intend that everytime slider is moved all the labels are deleted and the created fresh. I am not sure if it is the deletion prosess that messes this or something else. When I run this in debug mode it seems that new QLabel*
are inserted into labels_?
vector, but for some reason they are not visible.
Here is my code:
mainwindow.cpp:
#include "mainwindow.hh"
#include "ui_mainwindow.h"
#include <QLabel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->horizontalSlider->setRange(1,10);
ui->horizontalSlider->setValue(5);
connect(ui->horizontalSlider, &QSlider::sliderMoved, this, &MainWindow::move_slider);
// This works
//create_label(50);
// This works
// for (auto i = 0 ; i < ui->horizontalSlider->value(); i++) {
// labels_.push_back(create_label(i*item_width_));
// }
}
MainWindow::~MainWindow()
{
delete ui;
}
QLabel* MainWindow::create_label(int x)
{
QLabel* label = new QLabel(ui->frame);
label->setGeometry(x, 0, item_width_, item_width_);
label->setText(QString::number(ui->horizontalSlider->value()));
return label;
}
// This method is called when silder moves. It seems to remove labels,
// but does not make new labels.
void MainWindow::move_slider()
{
// Remove labels and reset
for (QLabel* label: labels_) {
delete label;
}
labels_.clear();
// Create labels
for (auto i = 0 ; i < ui->horizontalSlider->value(); i++) {
labels_.push_back(create_label(i*item_width_));
}
}
mainwindow.hh
#ifndef MAINWINDOW_HH
#define MAINWINDOW_HH
#include <QMainWindow>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
int item_width_ = 20;
std::vector<QLabel*> labels_;
QLabel* create_label(int x);
void move_slider();
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_HH
contents of labels_ after moving slider as seen in debug window:
EDIT:
I tried to disconect slider from move_slider()
and instead created PushButton and connected it with:
//connect(ui->horizontalSlider, &QSlider::sliderMoved, this, MainWindow::move_slider);
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::move_slider);
This also calls the method on clicked and removes labels out of sight, but does not return them.
Another thing I tried is just running this in constructor without any button presses or slider movement:
// Create labels
for (auto i = 0 ; i < ui->horizontalSlider->value(); i++) {
labels_.push_back(create_label(i*item_width_));
}
// Remove labels and reset
for (QLabel* label: labels_) {
delete label;
}
labels_.clear();
// Create labels again
for (auto i = 0 ; i < ui->horizontalSlider->value(); i++) {
labels_.push_back(create_label(i*item_width_));
}
It shows the labels correctly. So I think this my deletion should work (at least this line above seems to work in constructor), but simply either being part of either a method or constructor seems to be key difference in wheter or not new labels can be shown, even though it shouldn't.
Quote from the Qt Docs of QWidget constructor:
If you add a child widget to an already visible widget you must explicitly show the child to make it visible.
Just add label->setVisible(true);
to your create_label
method:
QLabel* MainWindow::create_label(int x)
{
QLabel* label = new QLabel(ui->frame);
label->setGeometry(x, 0, item_width_, item_width_);
label->setText(QString::number(ui->horizontalSlider->value()));
label->setVisible(true); // Add this
return label;
}
It works in the constructor, because your window is not visible at that moment.