QListWidget cannot add an item dynamically - c++

In my Qt application, I want to add a new item dynamically into a listview. Besides I also used Signal & Slot to transfer data between forms so I have created 2 following forms:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void ReceivedData(QString item);
private slots:
void on_btnAdd_clicked();
void on_btnCancel_clicked();
private:
Ui::MainWindow *ui;
void SetUpListName();
};
addform.h
class AddForm : public QDialog
{
Q_OBJECT
public:
explicit AddForm(QWidget *parent = 0);
~AddForm();
signals:
void SendData(QString item);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::AddForm *ui;
MainWindow *main_window;
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
SetUpListName();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::SetUpListName()
{
// Add 5 new elements
for (int i = 0; i < 5; i++) {
QString item = "Item " + QString::number(i);
ui->lwListItem->addItem(item);
}
}
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
add.setModal(true);
add.exec();
}
void MainWindow::on_btnCancel_clicked()
{
this->close();
}
void MainWindow::ReceivedData(QString item)
{
// Check to receive data
qDebug() << "Item: " << item;
// Add a new item to list items
ui->lwListItem->addItem(item);
}
addform.cpp
AddForm::AddForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::AddForm)
{
ui->setupUi(this);
main_window = new MainWindow();
connect(this, SIGNAL(SendData(QString)), main_window, SLOT(ReceivedData(QString)));
}
AddForm::~AddForm()
{
delete ui;
}
void AddForm::on_pushButton_clicked()
{
// Send data via Signal & Slot
emit SendData(ui->txtName->text());
}
void AddForm::on_pushButton_2_clicked()
{
this->close();
}
When I run the application, I got the data from Add form but the list view doesn’t add this item.
Does someone have any solutions?
Thanks!
P/S: You can download my source code at here

You are connecting the signal to the wrong object's slot. In the constructor of AddForm, you are creating a new MainWindow and connecting the signal to it's slot which means that the signal does not reach your real MainWindow, and the ReceivedData slot is adding the item to the wrong QListWidget. What you should do is this:
void MainWindow::on_btnAdd_clicked()
{
// Open Add Form
AddForm add;
connect(&add, SIGNAL(SendData(QString)), this, SLOT(ReceivedData(QString)));
add.setModal(true);
add.exec();
}
and remove the creation of a new MainWindow and corresponding connect call from the constructor of AddForm.

Related

i have creating a desktop application using Qt C++. Right click the QPush Button it opens the items like "BC,RT,MT. How to Write code for that

My problem was right-clicking the Qpushbutton it will show the items in it. how can we write this code using Qt C++? before I kept a combo box for the menu but now I need to keep the pushbutton Rightclick event to open the items?
""""""".h"""""""""
class MainWindow: public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
Bc *open;
Rt *open1;
Mt * open2;
//QRightclickbutton *open3;
//QRightClickButton(QWidget *parent = 0);
~MainWindow();
//protected:
//void mousePressEvent(QMouseEvent *e);
signals:
void rightClicked();
protected:
// void mousePressEvent(QMouseEvent * event);
void pushbutton(QWidget *parent);
void mousePressEvent(QMouseEvent *e);
private slots:
//bool eventFilter(QObject *obj, QEvent *e);
void on_pb1_clicked();
void on_pb2_clicked();
void on_pb3_clicked();
void on_pb4_clicked();
// void on_pushButton_clicked();
// void on_pushButton_clicked(bool checked);
void on_pb_rightclicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H`
""Mainwindow.cpp""
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("Unical Project Title");
QMenu *menu = new QMenu(this);
menu->addAction("BC");
menu->addAction("RT");
menu->addAction("MT");
ui-> pb->setMenu(menu);
// connect(ui->pushButton, SIGNAL(Rightclicked), this, SLOT(play()));
// ui->pushButton->viewport()-> installEventFilter(this);
open = new Bc;
open1= new Rt;
open2= new Mt;
QObject *w = new QObject;
// QString *select = new QString;
ui->device0->addItem("Set as ");
ui->device0->addItem("BC");
ui->device0->addItem("RT");
ui->device0->addItem("MT");
//QObject::connect(ui->device0, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
// open->show();
ui->device1->addItem("Set as");
ui->device1->addItem("BC");
ui->device1->addItem("RT");
ui->device1->addItem("MT");
ui->device2->addItem("Set as");
ui->device2->addItem("BC");
ui->device2->addItem("RT");
ui->device2->addItem("MT");
ui->device3->addItem("Set as");
ui->device3->addItem("BC");
ui->device3->addItem("RT");
ui->device3->addItem("MT");
// int row= 7;
// int column= 2;
for (int row =0; row<=ui->tablewidget->rowCount(); row++)
{
QCheckBox * cb = new QCheckBox(this);
cb->setCheckState(Qt::Checked);
QWidget *w =new QWidget ();
QHBoxLayout *hLayout =new QHBoxLayout();
hLayout->addWidget(cb);
hLayout->setMargin(0);
hLayout->setAlignment(cb,Qt::AlignCenter);
w->setLayout(hLayout);
ui->tablewidget->setCellWidget(row,2,w);
}
}
MainWindow::~MainWindow()
{
delete UI;
}
void MainWindow::on_pb1_clicked()
{
ui->device0->currentText();
if(ui->device0->currentText() == "BC")
{
QObject::connect(ui->device0, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open->show();
}
if (ui->device0->currentText() == "RT")
{
QObject::connect(ui->device0, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open1->show();
}
if (ui->device0->currentText() == "MT")
{
QObject::connect(ui->device0, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open2->show();
}
}
void MainWindow::on_pb2_clicked()
{
ui->device1->currentText();
if(ui->device1->currentText() == "BC")
{
QObject::connect(ui->device1, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open->show();
}
if (ui->device1->currentText() == "RT")
{
QObject::connect(ui->device1, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open1->show();
}
if (ui->device1->currentText() == "MT")
{
QObject::connect(ui->device1, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open2->show();
}
}
void MainWindow::on_pb3_clicked()
{
ui->device2->currentText();
if(ui->device2->currentText() == "BC")
{
QObject::connect(ui->device2, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open->show();
}
if (ui->device2->currentText() == "RT")
{
QObject::connect(ui->device2, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open1->show();
}
if (ui->device2->currentText() == "MT")
{
QObject::connect(ui->device2, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open2->show();
}
}
void MainWindow::on_pb4_clicked()
{
ui->device3->currentText();
if(ui->device3->currentText() == "BC")
{
QObject::connect(ui->device3, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open->show();
}
if (ui->device3->currentText() == "RT")
{
QObject::connect(ui->device0, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open1->show();
}
if (ui->device3->currentText() == "MT")
{
QObject::connect(ui->device3, SIGNAL(currentTextChanged(QString)),this,SLOT(setText(QString)));
open2->show();
}
}
//void MainWindow::on_pushButton_clicked(bool checked)
//{
// QMouseEvent *button= new QMouseEvent(this);
// ui->pushButton->button;
// connect(button, SIGNAL(rightClicked()), this, SLOT(()));
// qDebug()<<"right clicked";
//}
void pushbutton ::on_pb_rightclicked()
{
connect(ui->pushButton, SIGNAL(rightClicked),this, SLOT (menuBar(show())));
}
//void pushbutton::on_pb_clicked()
//{
//}
what I want is while Rightclick the Qpushbutton it shows the items in it and please help me to do this. thank you
You could use a custom context menu for the QPushButton.
First, you will need to assign the button context menu policy. So when you initialize your MainWindow, you should also:
ui->pushButton->setContextMenuPolicy(Qt::CustomContextMenu);
Then create a slot for when the custom context menu is requested (when the button is right-clicked):
//Your .h
private slots:
void on_pushButton_customContextMenuRequested(const QPoint &pos);
// Your .cpp
void MainWindow::on_pushButton_customContextMenuRequested(const QPoint &pos)
{
QMenu contextMenu(tr("Context menu"), this);
QAction action1("BC", this);
connect(&action1, &QAction::triggered,
[]{qDebug() << "User selected BC";});
contextMenu.addAction(&action1);
QAction action2("RT", this);
connect(&action2, &QAction::triggered,
[]{qDebug() << "User selected RT";});
contextMenu.addAction(&action2);
QAction action3("MT", this);
connect(&action3, &QAction::triggered,
[]{qDebug() << "User selected MT";});
contextMenu.addAction(&action3);
contextMenu.exec(mapToGlobal(pos));
}
I'm not sure what you want to have done when the user selects an item from the context menu, so the above uses a lambda function when each action is triggered. Alternately you could use a traditional signal/slot connection.
In the future, please try to include only the code for a MRE

Qt QTreeview currentChange is not emitted

I am trying to run some code when I select a new index in a QTreeView
In RoverPlanner.h
namespace Ui {
class RoverPlanner;
}
class RoverPlanner : public QWidget
{
Q_OBJECT
public:
explicit RoverPlanner(QWidget *parent = nullptr);
void save_paths_from_tree(QTreeView* treeView);
void load_paths_into_tree(QTreeView* treeView);
std::vector<cuarl_path::Path> get_paths(const char* filename) const;
void update_segment_editor();
cuarl_path::Segment* addSegment();
~RoverPlanner();
private Q_SLOTS:
void treeSelectionChanged(const QModelIndex& prevIndex, const QModelIndex& nextIndex);
private:
Ui::RoverPlanner *ui;
};
In RoverPlanner.cpp
RoverPlanner::RoverPlanner(QWidget *parent) :
QWidget(parent),
ui(new Ui::RoverPlanner)
{
ui->setupUi(this);
QPushButton* btnLoadPaths = this->findChild<QPushButton*>("btn_load_paths");
QPushButton* btnSavePaths = this->findChild<QPushButton*>("btn_save_paths");
QPushButton* btnExecutePath = this->findChild<QPushButton*>("btn_execute_path" );
QPushButton* btnAddSegment = this->findChild<QPushButton*>("btn_add_to_path");
QTreeView* treeView = this->findChild<QTreeView*>("tree_paths");
connect(btnLoadPaths, &QPushButton::clicked, this, [=]() { load_paths_into_tree(treeView); });
connect(treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &RoverPlanner::treeSelectionChanged); // This does not seem to properly bind the index chan
}
void RoverPlanner::treeSelectionChanged(const QModelIndex &prevIndex, const QModelIndex &nextIndex) {
std::cout << "Test" << std::endl;
}
//other functions
When I click on the items, it does not output anything in the console
I'm confused because this seems to be the way to correctly connect the treeview selected index changed. What did I do wrong?
selectionModel gets replaced each time a new model is set for QTreeView.
void QAbstractItemView::setModel(QAbstractItemModel *model):
This function will create and set a new selection model, replacing any model that was previously set with setSelectionModel().
That means you need to reconnect the &QItemSelectionModel::currentChanged signal each time you set a new model.

Qt signal and slots do not work if called from QRunnable or another thread

I am trying to learn how to use Multi-threading in Qt and put it to use in QtWidget applications. So I have setup this simple test case.
MainWindow
This form has some buttons and each button will execute another form (a Dialog for that matter).
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnShowCalibrationDialog, &QPushButton::clicked,
this, [&](){
CalibrationDialog dlg;
dlg.exec();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
CalibrationDialog This dialog has a QPushButton and a QTextEdit. When the button is clicked I will run a QRunnable class (comes next!)
calibrationdialog.h (I have spared you the includes and guards!)
class CalibrationDialog : public QDialog
{
Q_OBJECT
public:
explicit CalibrationDialog(QWidget *parent = nullptr);
~CalibrationDialog();
public slots:
void onBeginWorkRequested();
void onReceiveData(int data);
private:
Ui::CalibrationDialog *ui;
};
calibrationdialog.cpp
#include "worker.h"
CalibrationDialog::CalibrationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CalibrationDialog)
{
ui->setupUi(this);
connect(ui->btnBegin, &QPushButton::clicked,
this, &CalibrationDialog::onBeginWorkRequested);
}
CalibrationDialog::~CalibrationDialog()
{
delete ui;
}
void CalibrationDialog::onBeginWorkRequested()
{
qDebug() << "CalibrationDialog::onBeginWorkRequested()" << "on" << QThread::currentThreadId();
Worker* worker = new Worker();
QThreadPool* pool = QThreadPool::globalInstance();
connect(worker, &Worker::reportProgress,
this, &CalibrationDialog::onReceiveData);
pool->start(worker);
pool->waitForDone();
}
void CalibrationDialog::onReceiveData(int data)
{
ui->teResults->append(QString::number(data));
ui->teResults->ensureCursorVisible();
}
Worker And this is some runnable...I want to report the progress so that is shows up in the textedit of the dialog in a reponsive manner!
worker.h
class Worker : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
void run() override;
private:
int mProgress = 0;
signals:
void reportProgress(int progress);
};
worker.cpp
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::run()
{
qDebug() << "Worker is running #" << QThread::currentThreadId();
while(true) {
mProgress += 100;
emit reportProgress(mProgress);
QThread::msleep(500);
}
}
I see in the debugger that control goes in to the while loop...but the signal is not being handled by the dialog! I mean the textedit stays empty!
I tried to read documentationand search online...I came to the conclusion that my problem lies in the waste land of thread affinity....but I have no idea if that is the case and if that is, how to solve it. Please assist!
remove pool->waitForDone();, never use waitForX methods in a GUI since they are blocking preventing signals from doing their job.

Signal and slot wrong value sending(Qt c++)

I have written a small program to send data from one form(MainWindow) to another(Dialog) upon a button click. When the button is clicked the value written in the lineEdit of MainWindow is to be displayed on a label in Dialog form!
When I click the button a value is displayed on the label but it is not the same as the value entered in the line edit!
following are the respective codes in the 2 header and 2 cpp files!
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
void sendIntData(int data);
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
}
MainWIndow.cpp
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
dialog1->setModal(true);
dialog1->exec();
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
}
Dialog.h
class Dialog : public QDialog
{
Q_OBJECT
public slots:
void setIntData(int data);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
}
Dialog.cpp
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::DIalog)
{
ui->setupUi(this);
QString value=QString::number(index);
ui->label->setText(value);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::setIntData(int data)
{
index=data;
}
eg-When I click 3 and press the button I get a value 7237481! How can I correct this?
Replace connect and emit in on_pushButton_clicked()
void MainWindow::on_pushButton_clicked()
{
Dialog *dialog1=new Dialog(this);
dialog1->setModal(true);
dialog1->exec();
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
}
If only once we convey our dialogue, the importance of signal and slot is not necessary.
It is possible to give this value to the constructor or to do the initialize function and to give it the values.
//way 1:
void MainWindow::on_pushButton_clicked(){
Dialog *dlg = new Dialog();
connect(this, SIGNAL(SendData(int)), dlg, SLOT(slotData(int)));
emit SendData(ui->lineEdit->text().toInt());
dlg->exec();
}
void Dialog::slotData(int arg1)
{
ui->label->setText(QString::number(arg1));
}
//way 2:
void MainWindow::on_pushButton_clicked(){
Dialog* dlg = new Dialog(ui->lineEdit->text().toInt());
dlg->exec();
}
//way 3:
#include "dialog.h"
#include "ui_dialog.h"
#include "QDebug"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::initialize(int value)
{
ui->label->setText(QString::number(value));
}
void MainWindow::on_pushButton_clicked(){
Dialog *dlg = new Dialog();
dlg->initialize(ui->lineEdit->text().toInt());
dlg->exec();
}
I think you are showing int value which not initialized.
emit signal:
int o=ui->lineEdit->text().toInt();
connect(this, SIGNAL(sendIntData(int)),dialog1, SLOT(setIntData(int)));
emit sendIntData(o);
Show value:
void Dialog::setIntData(int data)
{
ui->label->setText(QString::number(data));
}

Embed a QWebEngineView process inside QTabWidget

I'm trying to integrate a QWebEngineView widget that runs as a separate process(QProcess) inside a QTabWidget page. So far the QWebEngineView process is being started properly but its showing the webpage in a separate window instead of showing it inside the QTabWidget in the MainWindow application.
This is the Widget that is being added to the QTabWidget.
BrokersTerminal.h
class BrokersTerminal : public QWidget
{
Q_OBJECT
public:
explicit BrokersTerminal(QWidget *parent = 0);
~BrokersTerminal();
void startTerminal();
public slots:
void brokersTerminalStarted();
private:
Ui::BrokersTerminal *ui;
QProcess *brokers_process;
QString brokers_program_path;
QStringList arguments;
};
BrokersTerminal.cpp
BrokersTerminal::BrokersTerminal(QWidget *parent) :
QWidget(parent),
ui(new Ui::BrokersTerminal)
{
ui->setupUi(this);
brokers_process = new QProcess( this );
brokers_program_path = QApplication::applicationFilePath();
arguments << "--b";
connect( brokers_process, &QProcess::started, this , &BrokersTerminal::brokersTerminalStarted );
}
BrokersTerminal::~BrokersTerminal()
{
delete ui;
}
void BrokersTerminal::startTerminal()
{
brokers_process->start( brokers_program_path, arguments );
brokers_process->waitForStarted();
}
void BrokersTerminal::brokersTerminalStarted()
{
qDebug() << "Brokers terminal started";
}
This is the WebView Widget that is responsible for displaying the brokers website.
BrokersWebWidget.h
class BrokersWebWidget : public QWidget
{
Q_OBJECT
public:
explicit BrokersWebWidget(QWidget *parent = 0);
~BrokersWebWidget();
private:
Ui::BrokersWebWidget *ui;
QUrl brokers_url;
QWebEngineView *web_browser;
};
BrokersWebWidget.cpp
BrokersWebWidget::BrokersWebWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::BrokersWebWidget)
{
ui->setupUi(this);
brokers_url = "https://siteofbrokersapi.com/";
web_browser = new QWebEngineView( this );
web_browser->load( brokers_url );
}
BrokersWebWidget::~BrokersWebWidget()
{
delete ui;
}
Right now this BrokersWebWidget starts properly as a separate process but it opens in a separate window , but how can this be added in the BrokersTerminal Widget ?
Please let me know of any possible solutions. Thanks.
You cannot embed a widget running in one process into a window run in another. QWidgets can only work with widgets run in the GUI thread in the same process.