How can I automatically add new objects in Qt5? - c++

For convenience, I created a function that helps me add new objects, but the MainWindow function doesn't accept them. So how can the MainWindow function receive the newly created object?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFrame>
#include <QVBoxLayout>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void CreateNewObj(int row, int column, int rowSpan, int columnSpan);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
for (int i = 0; i < 10; i++)
{
MainWindow::CreateNewObj(i,0,1,1);
}
// HERE
// this->ui->frame_1... IN HERE MainWindow function does not accept new object created by CreateNewObj function
// HERE
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::CreateNewObj(int row, int column, int rowSpan, int columnSpan)
{
QFrame *frame = new QFrame(this->ui->scrollAreaWidgetContents);
QVBoxLayout *verticalLayout;
verticalLayout = new QVBoxLayout(frame);
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout_") + QString::number(row));
frame->setObjectName(QString::fromUtf8("frame_") + QString::number(row));
frame->setMinimumSize(QSize(100, 100));
frame->setMaximumSize(QSize(16777215, 50));
frame->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 170, 127);"));
frame->setFrameShape(QFrame::StyledPanel);
frame->setFrameShadow(QFrame::Raised);
this->ui->gridLayout->addWidget(frame, row, column, rowSpan, columnSpan);
}
mainwindow.ui:

It should be something like:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
QVBoxLayout *verticalLayout = new QVBoxLayout(ui->scrollAreaWidgetContents());
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
for (int i = 0; i < 10; i++)
{
QFrame *frame = new QFrame(ui->scrollAreaWidgetContents());
frame->setObjectName(QString::fromUtf8("frame_") + QString::number(i));
frame->setMinimumSize(QSize(100, 100));
frame->setMaximumSize(QSize(16777215, 50));
frame->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 170, 127);"));
frame->setFrameShape(QFrame::StyledPanel);
frame->setFrameShadow(QFrame::Raised);
verticalLayout->addWidget(frame, i, 0, 1, 1);
}
}

Related

Qt passing a Value from one window to antother

I am quite new to programming, so hopefully someone can help me out. After calculating a value with a function and storing it into the variable with a setter, I want to call it in my viswindow.cpp to visualize it in a Graph. In the mainwindow the right value is calculated and stored by pressing a button, which also opens the viswindow. I tried to pass it with a pointer or with signals and slots, but it wouldn't work.
mainwindow.cpp:
double MainWindow::berechneFussabdruck(double strecke, int anzahl, double sfcWert)
{
if(strecke <= 1500 && strecke > 0){
double aequivalente_Co2 = (((sfcWert*3.116*50*(((0.0011235955)*(strecke-2*48.42))+0.233))*0.001)/anzahl);
setAequivalente(aequivalente_Co2);
}
else{
double aequivalente_Co2 = (((sfcWert*3.116*75*(((0.0011235955)*(strecke-2*208))+0.833))*0.001)/anzahl);
setAequivalente(aequivalente_Co2);
}
return aequivalente_Co2;
}
Button to open viswindow:
void MainWindow::on_pushButton_clicked()
{
MainWindow::berechneFussabdruck(strecke, anzahl, sfcWert);
visWindow = new VisWindow(this);
visWindow->show();
}
viswindow.cpp:
VisWindow::VisWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::VisWindow)
{
ui->setupUi(this);
...
*set0 << aequivalente_Co2 << aequivalente_Co2;
*set1 << 11.07 << 0;
*set2 << 0 << 0.49;
...
}
Thanks for helping!
Here are examples of:
Single time value transfer from MainWindow to VisWindow in constructor parameter.
Value update from MainWindow to VisWindow by slot-signal chain.
Value update from MainWindow to VisWindow by direct call of VisWindow->updateValue() slot as regular function.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "viswindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
signals:
void updatevalue(const double value);
private:
Ui::MainWindow *ui;
VisWindow * m_viswindow;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::on_pushButton_clicked() {
m_viswindow = new VisWindow(12.34, nullptr);
connect(this, &MainWindow::updatevalue,
m_viswindow, &VisWindow::updateValue);
m_viswindow->show();
}
void MainWindow::on_pushButton_2_clicked() {
emit updatevalue(23.45);
}
void MainWindow::on_pushButton_3_clicked() {
m_viswindow->updateValue(45.67);
}
viswindow.h
#ifndef VISWINDOW_H
#define VISWINDOW_H
#include <QWidget>
namespace Ui {
class VisWindow;
}
class VisWindow : public QWidget
{
Q_OBJECT
public:
explicit VisWindow(const double value, QWidget *parent = nullptr);
~VisWindow();
public slots:
void updateValue(const double value);
private:
Ui::VisWindow *ui;
};
#endif // VISWINDOW_H
viswindow.cpp
#include "viswindow.h"
#include "ui_viswindow.h"
VisWindow::VisWindow(const double value, QWidget *parent) :
QWidget(parent),
ui(new Ui::VisWindow)
{
ui->setupUi(this);
ui->lblValue->setText(QString::number(value,'f',2));
this->setWindowTitle("VisWindow");
}
VisWindow::~VisWindow() {
delete ui;
}
void VisWindow::updateValue(const double value) {
ui->lblValue->setText(QString::number(value,'f',2));
}

Customized widget in scroll area cannot be scrolled up or down after setting setWidgetResizable to true in qt

I have a problem when working with QScrollArea. Mainly, I want to add a customized widget into a scroll area to reach:
scroll widget if widget's size is larger than parent(scroll)
customized widget can automatically resize its size to fill all space of scroll if it is smaller than scroll
But I failed. Setting setWidgetResizable to true can resize widget but cannot scroll. Otherwise, can scroll widget not resize.
I'm using qt-5.15.x. Here is the minimal example, I can scroll it if I comment out line scroll->setWidgetResizable(true);:
customwidget.h
#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
#include <QWidget>
#include <QSize>
#include <QResizeEvent>
class CustomWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomWidget(QWidget *parent = nullptr);
~CustomWidget()=default;
protected:
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
QSize sizeHint() const override;
private:
QVector<QRectF> _rects;
QSize _size;
};
#endif // CUSTOMWIDGET_H
customwidget.cpp
#include "customwidget.h"
#include <QPainter>
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
_size = QSize(120, 200);
for(int i = 0; i < 10; i++)
{
QRectF rect(QPointF(10, 60*i+2),QSize(100, 50));
_rects.push_back(rect);
}
}
void CustomWidget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
// background
painter.setBrush(QColor(130,130,130));
painter.drawRect(QRectF(QPointF(0,0), _size));
// items
for(int i = 0; i < 10; i++)
{
painter.setBrush(QColor(43,43,43));
painter.drawRect(_rects[i]);
painter.setPen(QColor(255,255,255));
painter.drawText(_rects[i], QString("ITEM %1").arg(QString::number(i)));
}
}
void CustomWidget::resizeEvent(QResizeEvent *e)
{
_size = e->size();
}
QSize CustomWidget::sizeHint() const
{
int rows = _rects.size();
int height = rows * 60+2;
height = std::max(height, parentWidget()->height());
int width = 120;
return QSize(width, height);
}
Add the mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QScrollArea>
#include "customwidget.h"
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setGeometry(0,0,300,200);
QVBoxLayout *layout = new QVBoxLayout(centralWidget());
layout->setContentsMargins(0,0,0,0);
CustomWidget *cw = new CustomWidget();
QScrollArea *scroll = new QScrollArea(this);
scroll->setWidgetResizable(true);
scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll->setStyleSheet("QScrollArea{background:rgb(0,0,0);border:none;}");
scroll->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
scroll->setWidget(cw);
layout->addWidget(scroll);
}
MainWindow::~MainWindow()
{
delete ui;
}
A possible solution is to set the sizePolicy to Minimum:
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
_size = QSize(120, 200);
for(int i = 0; i < 10; i++)
{
QRectF rect(QPointF(10, 60*i+2),QSize(100, 50));
_rects.push_back(rect);
}
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}

How to move widgets inside QLayout if their position is greater than the screen size?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMainWindow>
#include <QTableWidget>
#include <QHeaderView>
#include <QGridLayout>
#include <QWidget>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWidget *widget = new QWidget(this);
QGridLayout *layout = new QGridLayout();
layout->setSizeConstraint(QLayout::SetFixedSize);
for (int i = 0; i < 10; ++i) {
QTableWidget *table = new QTableWidget(this);
InitializeQtableWidget(table, 3, 5);
layout->addWidget(table);
}
widget->setLayout(layout);
setCentralWidget(widget);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::InitializeQtableWidget(QTableWidget *table, const int &rows, const int &columns)
{
table->setRowCount(rows);
table->setColumnCount(columns);
const int tableColumnWidth = 60;
const int tableRowHeight = 35;
for(int i = 0; i < columns; ++i)
table->setColumnWidth(i, tableColumnWidth);
table->verticalHeader()->setFixedWidth(tableColumnWidth);
table->horizontalHeader()->setFixedHeight(tableRowHeight + 5);
table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
table->setFixedSize(table->horizontalHeader()->length() + table->verticalHeader()->width(),
table->verticalHeader()->length() + table->horizontalHeader()->height());
}
You need to write your own layout implementation for that. Or you may check some open-source solutions and adapt for your needs. Take a look at this one.

updating value from mainwindow to dialog

I have a mainwindow that generates random int numbers every second in "numbers" and I have a button that opens a new dialog. In that dialog is a button "Get Number" and a qlabel. If I press "Get Number" I want the current generated number from the mainwindow set to the dialog label text. I tried to write a member function in the mainwindow class that returns the actual value but I cant call it from the dialog and I think that's the wrong way. How can I get this current generated int "numbers" into the dialog? My plain code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void generateNumbers();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"
#include <QTimer>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()), this, SLOT(generateNumbers()));
timer->start(1000);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
Dialog dialog;
dialog.setModal(true);
dialog.exec();
}
void MainWindow::generateNumbers()
{
int numbers = qrand() % 100;
qDebug() << numbers;
}
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
On mainwindow.h, add a signal:
signals:
void update_number(int);
On mainwindow.cpp, emit that signal everytime you generate a new number:
void MainWindow::generateNumbers()
{
int numbers = qrand() % 100;
emit update_number(numbers); // signals that a new number has been generated
qDebug() << numbers;
}
and your on_pushButton_clicked() should look like this:
void MainWindow::on_pushButton_clicked()
{
Dialog dialog(this); // main window as the parent of dialog
dialog.setModal(true);
dialog.exec();
}
On dialog.h, add an attribute called number_ and add the following slot:
public slots:
void on_update_number(int number); // updates the number_
private:
int number_; // it will be updated with the most recent number
Ui::Dialog *ui;
On dialog.cpp, connect the signal to the slot:
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
connect(parent, SIGNAL(update_number(int)), this, SLOT(on_update_number(int)));
}
add the slot code:
void Dialog::on_update_number(int number)
{
number_ = number;
}
Finally, when the user clicks the button "Get Number" in the dialog, set the label text:
void Dialog::on_pushButton_clicked()
{
ui->label->setText(QString::number(number_));
}
For more information on Signals & Slots go here.

QT : Memory Leakage and SubClassing (Custom QWidget) Issue

I have an mainwindow app, with 3 main modules and each modules have 6 sub-modules. Each submodel consists of different kind of Gui widgets (like Qlineedit, Qlabel, QPushbutton,QGroupBox etc…).
I would subclass all each main and sub-modules (inheriths QWidget). Each main and sub module is created dynamically. For ex, when the 1st main module is constructed, it also allocates for the 6 submodules. But, when the app is closed, it doesn’t free all 6 submodules. There may be a leakage problem but I didn’t figure out. why. I think I have a problem with subclassing of my modules.
My app is too big to post here so I would post 2 benchmark codes. To show the issue, this mainwindow app has 100 my custom QLineEdit object (I know it is weird but it adresses my problem well). But when the app is closed, doesn’t free all the 100 custom Qlineedit objects. (Here, my custom QLineedit class represents my modules…)
I have tried 2 kind of subclassing to understand the problem. 1. BcInputBox inherits QLineEdit 2. BcInputBox inherits QWidget
I’ve tried both of them separately but the issue is the same. I’ve spent more than 1 week but I haven’t figured it out yet.
Which approach would be better? What is the mistake about my design?
1st Benchmark
// #####################################################
// Benchmark 1 //
// #####################################################
//
//BcInputBox.h
#ifndef BCINPUTBOX_H
#define BBCINPUTBOX_H
#include <QLineEdit>
namespace BC {
const bool ReadOnly = true;
const bool Edit = false;
const bool Double = true;
const bool Name = false;
}
class BcInputBox: public QWidget
{
Q_OBJECT
public:
explicit BcInputBox(QWidget *parent = 0, bool editInfo = BC::Edit, bool inputInfo = BC::Double);
~BcInputBox();
void setEditInfo(bool editInfo);
void setInputInfo(bool inputInfo);
QLineEdit *getInputBox() const;
static int objCounter;
private:
QLineEdit *inputBox;
};
#endif // BCINPUTBOX_H
//******************************************
//BcInputBox.cpp
#include <QDebug>
#include <QHBoxLayout>
#include <QValidator>
#include "BcInputBox.h"
#include "BcDoubleValidator.h"
int BcInputBox :: objCounter = 0;
BcInputBox::BcInputBox(QWidget *parent, bool editInfo, bool inputInfo):QWidget(parent)
{
QHBoxLayout *hlay = new QHBoxLayout(this);
inputBox = new QLineEdit(this);
setEditInfo(editInfo);
setInputInfo(inputInfo);
hlay -> addWidget(inputBox);
inputBox -> setStyleSheet("background-color: yellow;"
"border-radius: 8px;");
qDebug() << objCounter++ << "BcInputBox()";
}
BcInputBox :: ~BcInputBox()
{
//qDebug() << objCounter ;
qDebug() << "~BcInputBox";
delete inputBox;
}
void BcInputBox :: setEditInfo(bool editInfo)
{
inputBox -> setReadOnly(editInfo);
}
void BcInputBox :: setInputInfo(bool inputInfo)
{
if (!inputInfo){
QRegExp rExp ("[A-Za-z0-9]{1,16}");
inputBox -> setValidator(new QRegExpValidator(rExp, inputBox));
}
else {
inputBox -> setValidator( new BcDoubleValidator( 0.0, 1000, 3,inputBox));
}
}
QLineEdit *BcInputBox :: getInputBox() const
{
return inputBox;
}
//******************************************
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
#include "subconsmod1.h"
#include "BcInputBox.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
BcInputBox *subSection[100];
};
#endif // MAINWINDOW_H
//******************************************
//MainWindow.cpp
#include <QtCore>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout *hlay = new QVBoxLayout(ui->centralWidget);
for (int i = 0; i < 100; ++i ){
subSection[i] = new BcInputBox (ui->centralWidget);
hlay -> addWidget(subSection[i]);}
ui->centralWidget ->setLayout(hlay);
}
MainWindow::~MainWindow()
{
delete ui;
}
2nd Benchmark
// #####################################################
// Benchmark 2 //
// #####################################################
//
//BcInput.h
#ifndef BCINPUT_H
#define BCINPUT_H
#include <QLineEdit>
class BcInput : public QLineEdit
{
Q_OBJECT
public:
explicit BcInput(QWidget *parent = 0);
~BcInput();
static int counter;
signals:
public slots:
};
#endif // BCINPUT_H
//******************************************
//BcInput.cpp
#include <QDebug>
#include "bcinput.h"
int BcInput :: counter = 0;
BcInput::BcInput(QWidget *parent) :
QLineEdit(parent)
{
qDebug() << "BcInput()";
qDebug() << counter++;
}
BcInput :: ~BcInput()
{
qDebug() << "~BcInput()";
}
//******************************************
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "bcinput.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
BcInput *subSection[100];
};
#endif // MAINWINDOW_H
//******************************************
//MainWindow.cpp
#include <QtGui>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "bcinput.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout *hlay = new QVBoxLayout(ui->centralWidget);
for(int i = 0; i<100;i++){
subSection[i] = new BcInput(ui->centralWidget);
hlay->addWidget(subSection[i]);}
ui->centralWidget->setLayout(hlay);
}
MainWindow::~MainWindow()
{
for(int i = 0; i<100;i++)
delete subSection[i];
delete ui;
}