My UI MainWindow has a QListWidget and , upon clicking of its items ,a corresponding QDialog box must pop up , which prompts the user to enter some values in QDialog box, The values entered into line_edits of QDialog box must stored into a QString variable and this variable should be accessed/used in a function of MainWindow,
for Example: I have a QListWidget, with 3 items "New York","Glasgow","Mumbai", and when i double click item named "New York", a pop-up shows up asking me this
and after i enter 3 and Hilton , the item in QListWidget which was initially "New York" must be changed to
"New York -3 , The safehouse is in Hilton"
my code for MainWindow.cpp is
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include <QtGui>
#include <sstream>
#include <QtWidgets/qmessagebox.h>
#include <QtWidgets/qlistwidget.h>
using namespace std;
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->My_listwidget->addItem("New York");
ui->My_listwidget->addItem("Glasgow");
ui->My_listwidget->addItem("Mumbai");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_My_listwidget_itemDoubleClicked(QListWidgetItem* item)
{
QString test = item->text();
std::string test_s = test.toStdString();
if (test_s.find("New York") != std::string::npos) // check if item contains text "New York"
{
WinApp winApp;
winApp.setModal(true); //Displaying the window here
winApp.exec();
}
if (test_s.find("Glasgow") != std::string::npos)
{
// show another dialog box asking some questions
}
if (test_s.find("Mumbai") != std::string::npos)
{
// show another dialog box asking some questions
}
}
My code for mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtWidgets/QMainWindow>
#include "ExecutionContext.h"
#include <QtWidgets/qlistwidget.h>
//#include "secdialog.h"
#include <qregexp.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT //Used to handle events
public:
MainWindow(QWidget* parent = 0);
~MainWindow(); //Destructor used to free resources
private slots:
void on_xml_scripts_textbox_itemDoubleClicked(QListWidgetItem* item);
Ui::MainWindow* ui; // pointing to UI class
private:
};
#endif // MAINWINDOW_H
my code for WinApp.h , winapp is the name of my dialog
#include <QtWidgets/qdialog.h>
#include "ui_WinApp.h"
class WinApp : public QDialog, public Ui::WinApp
{
Q_OBJECT
public:
WinApp(QWidget *parent = Q_NULLPTR);
~WinApp();
private slots:
private:
Ui::WinApp ui;
};
WinApp.cpp
#include "WinApp.h"
WinApp::WinApp(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
}
WinApp::~WinApp()
{
}
you need to add in the WinApp dialog class the test getter, it should be something like:
QString getFavouriteHotel() const {
return ui.<favourite-hotel-label>.text()
}
In the MainWindow after the line winApp.exec(); I suggest adding an if to check if the user accepted or declined the dialog (docs). If the user accepted the dialog then you can retrieve the text with the getters you just added.
Tips: avoid using exec, as said in the docs use the open
-- UPDATE -- QDialog accept --
Always check the docs
connect(&WinApp, &QDialog::finished, this, [this](int result) {
if(result == QDialog::Accepted){
// do aswomness
return
}
});
Have the function initiating the QDialog object pass the QString argument in the constructor and override accept().
#include <QtWidgets/qdialog.h>
#include "ui_WinApp.h"
class WinApp : public QDialog, public Ui::WinApp
{
Q_OBJECT
public:
WinApp(QString& stringToModify, QWidget *parent = Q_NULLPTR);
~WinApp();
private slots:
void accept() override;
private:
Ui::WinApp ui;
};
and define the acccept() slot which will get the QString from lineEdit and update the stringToModify with it.
void WinApp::accept(){
//do stuff with QString
this->close();
}
Related
I have 2 UIs and I am trying to update one from the other. I have the classes phone, user_ui, test_ui, and user_transmitter. The user_ui is the one that a user can interact with such as if the user pressed the toggle button on the UI of the user_ui then the status should be displayed on the UI of the test_ui. The user_transmitter transmits the inputs and outputs and that's its only job, there is no UI to it. The phone class just contains the variables and nothing else.
user_ui.h:
#ifndef USER_UI_H
#define USER_UI_H
#include <QMainWindow>
#include <QTimer>
#include <phone.h>
#include "user_transmitter.h"
#include "test_ui.h"
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class user_ui; }
QT_END_NAMESPACE
class user_ui : public QMainWindow
{
Q_OBJECT
public:
user_ui(QWidget *parent = nullptr);
~user_ui();
Phone phone;
QTimer *timer;
private:
Ui::user_ui *ui;
user_transmitter user_t;
void updateUI();
void connections();
signals:
void toggeButton(int);
private slots:
void toggleButton1();
void update();
};
#endif // USER_UI_H
user_ui.cpp:
#include "user_ui.h"
#include "ui_user_ui.h"
#include <QMessageBox>
user_ui::user_ui(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::user_ui)
{
ui->setupUi(this);
update();
connections();
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
user_ui::~user_ui()
{
delete ui;
}
void user_ui::update()
{
ui->status->setText((phone.status) ? "On" : "Off");
}
void user_ui::connections() {
QObject::connect(this, &user_ui::toggleButton, &user_t, &user_transmitter::toggleButton);
connect(ui->button, SIGNAL(released()), this, SLOT(toggleButton1()));
}
void user_ui::toggleButton1() {
phone.status= !phone.status;
emit toggleButton(1);
}
user_transmitter.h:
#ifndef USER_TRANSMITTER_H
#define USER_TRANSMITTER_H
#include <vector>
#include "phone.h"
#include "test_ui.h"
class user_transmitter : public QObject
{
Q_OBJECT
public:
explicit user_transmitter(QObject *parent = nullptr);
Phone phones;
public slots:
void toggleButton(int);
private:
void setUpSignals();
test_ui test;
signals:
void button(int,bool);
};
#endif // USER_TRANSMITTER_H
user_transmitter.cpp:
#include "user_transmitter.h"
user_transmitter::user_transmitter(QObject *parent) : QObject(parent)
{
setUpSignals();
}
void user_transmitter::setUpSignals(){
QObject::connect(this, &user_transmitter::button, &test, &test_ui::button);
}
void user_transmitter::button(int index)
{
phones.status = !phones.status;
cout << "From transmitter: " << phones.status<< endl;
emit button(index, phones.status);
}
test_ui.h:
#ifndef TEST_UI_H
#define TEST_UI_H
#include <QWidget>
namespace Ui {
class test_ui;
}
class test_ui : public QWidget
{
Q_OBJECT
public:
explicit test_ui(QWidget *parent = nullptr);
~test_ui();
QTimer *timer;
public slots:
void button(int,bool);
private:
Ui::test_ui *ui;
signals:
};
#endif // TEST_UI_H
test_ui.cpp:
#include "test_ui.h"
#include "ui_test_ui.h"
test_ui::test_ui(QWidget *parent) :
QWidget(parent),
ui(new Ui::test_ui)
{
ui->setupUi(this);
}
test_ui::~test_ui()
{
delete ui;
}
void test_ui::button(int index, bool status){
qDebug() << "From test: " << status;
ui->status->setText((status) ? "On" : "Off");
}
My problem is that when I press the toggle button of user_ui's UI, the "on" or "off" status should display on the user UI and the test_ui. It displays on the user UI but not the test_ui. The qdebug line in the transmitter and the test class print but the UI of the test does not get updated so I am guessing that the function is getting called. So, I am not sure if it's a signal slot problem since the qdebug line is printing or if it's a timing problem.
I tested out my test UI by trying to print something in the QLineEdit box from a different function in that class and it works so there is no problem there.
I was able to solve my problem by simply adding my Signal and Slot connections from the 2 classes (user_ui & user_transmitter) to my main.cpp.
I'm new to QtCreator and created a button on the mainwindow that opens a dialog. In the dialog i added QLineEdit and a button. When i click on this button, i want the input text to be displayed on a Qlabel in the mainwindow.
I found another question which is basicly the same, but for me it has to work the other way around.
So In the header of MainWindow.h i have added to public:
void setLabelText(QString str);
I created the getter/setter function and added it to MainWindow.cpp:
void MainWindow::setLabelText(QString str)
{
ui->label->setText(str);//it is label dialog
}
And in the windowdialog.cpp i have added under button click() slot:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
MainWindow MainWindow;
MainWindow.setLabelText(str);
}
It compiles without errors. Yet when i click on the button in the dialog, it won't print the results in the mainwindow... I have been trying to find another examples about how to do this, but couldn't really find one yet. So what am i missing? Or how do i make this work?
You can use signals and slots for this. https://doc.qt.io/qt-5/signalsandslots.html
you would need to connect the signal to a slot by using this command
connect(dlg,&DialogWindow::transmit,this,&MainWindow::update);
anytime you want to call the update function you would just need to emit the signal.
emit transmit(ui->lineEdit->text());
I created a dialog window class in this example.
Dialog.h
#ifndef DIALOGWINDOW_H
#define DIALOGWINDOW_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class DialogWindow : public QDialog
{
Q_OBJECT
public:
DialogWindow(QWidget *parent = nullptr);
~DialogWindow();
signals:
void transmit(QString txt);
private slots:
void on_buttonBox_accepted();
private:
Ui::Dialog *ui;
};
#endif // DIALOGWINDOW_H
Dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
DialogWindow::DialogWindow(QWidget *parent)
: QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
DialogWindow::~DialogWindow()
{
}
void DialogWindow::on_buttonBox_accepted()
{
emit transmit(ui->lineEdit->text());
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "dialog.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 update(QString txt);
private:
Ui::MainWindow *ui;
DialogWindow *dlg;
};
#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);
dlg = new DialogWindow(NULL);
connect(dlg,&DialogWindow::transmit,this,&MainWindow::update);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dlg->show();
}
void MainWindow::update(QString txt)
{
ui->label->setText(txt);
}
In this line MainWindow MainWindow;, you create a new MainWindow, but you want to set the text on your existing MainWindow.
Instead you might want to pass a reference or pointer to the MainWindow to the dialog, once you create it.
If you pass your MainWindow as the parent of the QDialog, you could do it this way:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
static_cast<MainWindow*>(parent())->setLabelText(str);
}
A safer version using dynamic_cast:
void WindowDialog::on_pushButton_clicked()
{
QString str = ui->lineEdit->text();
MainWindow* window = dynamic_cast<MainWindow*>(parent());
if (!window) {
throw std::runtime_error{"Parent was not a MainWindow"};
}
window->setLabelText(str);
}
I am new to qt and I am trying to create a program where the MainWindow calls a QDialog to enter some data.
The problem is that the parent() at my QDialog does not have any access to the public methods of the MainWindow in our case the
void save_city(const City *city); //public method of MainWindow
The code is actually big so here is some of the code.Thanks.
mainwindow.h
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMainWindow>
#include <QTextStream>
#include <QVector>
#include <QDebug>
#include <QFile>
#include "dialog_add_city.h"
#include "street.h"
#include "city.h"
#include "map.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//main Window constructor
explicit MainWindow(QWidget *parent = 0);
//main Window deconstructor
~MainWindow();
/*utility function to save the city
*the function is public so that also QDialogs
*data saves can */
//////////////
//here is the public function
void save_city(const City *city);
private slots:
private:
Map mainMap;
Ui::MainWindow *ui;
QGraphicsView view;
QGraphicsScene scene;
};
dialog_add_city.h
#ifndef DIALOG_ADD_CITY_H
#define DIALOG_ADD_CITY_H
#include <QDialog>
#include "mainwindow.h"
#include "City.h"
namespace Ui {
class Dialog_Add_City;
}
class Dialog_Add_City : public QDialog
{
Q_OBJECT
public:
explicit Dialog_Add_City(QWidget *parent = 0);
~Dialog_Add_City();
private slots:
//Add New City Button clicked-Adds an new city to our city_locations.txt
void on_PushButton_Add_New_City_clicked();
private:
Ui::Dialog_Add_City *ui;
};
#endif // DIALOG_ADD_CITY_H
dialog_add_city.cpp
#include "dialog_add_city.h"
#include "ui_dialog_add_city.h"
Dialog_Add_City::Dialog_Add_City(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog_Add_City)
{
ui->setupUi(this);
}
Dialog_Add_City::~Dialog_Add_City()
{
delete ui;
}
void Dialog_Add_City::on_PushButton_Add_New_City_clicked()
{
City *city=new City(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
qDebug() << ui->lineEdit_cityName->text()
<< ui->lineEdit_X_Ko->text()
<< ui->lineEdit_Y_Ko->text();
/////////////////////////////
//HERE IS THE PROBLEM
parent()->save_city(city);
}
Any other suggestions are welcomed!
The Problem is that parent() will return a pointer the parent object as QObject.
QObject Documentation
As dreschrjm pointed out you could try to cast the object via
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
from The Meta-Object System
Suggestion: Use Qt's signal/slot mechanism to avoid a backward reference to the parent.
Declare save_city as signal in Dialog_Add_City.
Declare save_city in MainWindow as slot
Connect both where the dialog is created:
e.g.
void MainWindow::show_add_city_dialog()
{
Dialog_Add_city dialog;
connect(&dialog, &Dialog_Add_city::save_city, this, &MainWindow::save_city);
dialog.exec();
}
Replace parent()->save_city(city); in Dialog_Add_City with emit save_city(city);
Ensure that the new city object doesn't leak, I think a better design would be to create the City object elsewhere not in the dialog.
so
emit save_city(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
and the slot
void MainWindow::save_city(const QString &cityName, double x, double y)
{
City *city=new City(cityName, x, y);
// do some interresting things with city.
}
Everytime i click my QPushButton which I have added with the UI Designer, the button stays clicked and the application crashes. When I remove the slot which the 'clicked()' signal of the button is connected to, I can click the button and the application behaves normal.
This is the header of the class that uses the UI:
#ifndef DARLEHENSRECHNER_H
#define DARLEHENSRECHNER_H
#include <QMainWindow>
#include "Darlehensgeber.h"
namespace Ui {
class Darlehensrechner;
}
class Darlehensrechner : public QMainWindow
{
Q_OBJECT
public:
explicit Darlehensrechner(QWidget *parent = 0);
~Darlehensrechner();
private slots:
void on_berechnenButton_clicked();
private:
Ui::Darlehensrechner *ui;
Darlehensgeber dg;
};
#endif // DARLEHENSRECHNER_H
And this is the cpp:
#include "darlehensrechner.h"
#include "ui_darlehensrechner.h"
Darlehensrechner::Darlehensrechner(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Darlehensrechner),
dg()
{
ui->setupUi(this);
}
Darlehensrechner::~Darlehensrechner()
{
delete ui;
}
void Darlehensrechner::on_berechnenButton_clicked()
{
dg.takeLoan(ui->kreditEdit->text().toFloat(),
ui->ratenEdit->text().toFloat(),
ui->zinsEdit->text().toFloat());
ui->dauerLabel_2->setText(QString::number(dg.getAmountOfInstallments()));
ui->betragLabel_2->setText(QString::number(dg.getAmount()));
}
There are two files:
mainwindow.cpp and editorplain.cpp
editorplain.cpp is dialog as widget.
Problem: Send text data to label on another dialog.
mainwidnow.cpp
Action on triggered from menu call a new dialog:
er will return string from mainwindow.
void MainWindow::on_actionRoot_files_triggered()
{
QString er = ui->selected_filename->text();
Editorplain editorplainwidget;
// HERE IS WHAT I WANT SEND A DATA TO ANOTHER DIALOG `editorplain`
editorplainwidget.exec();
}
When opening dialog I want a grab data from string er:
Editorplain::setData(myType myData)
{
ui->label_2->setText(myData.textForEdit);
}
Let's explain my problem. On mywindow I have a string er which returns some string as result. This er should send on dialog editorplain and set as label for example: ui->label->setText(er). Label is QLabel made on QDialog.
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_actionOpen_triggered();
void on_actionExit_triggered();
void on_actionRoot_files_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
editorplain.cpp file:
#include "editorplain.h"
#include "ui_editorplain.h"
#include "mainwindow.h"
Editorplain::Editorplain(QWidget *parent) :
QDialog(parent),
ui(new Ui::Editorplain)
{
ui->setupUi(this);
// SHOULD PASS ON THIS CONTRUCTOR?
}
Editorplain::~Editorplain()
{
delete ui;
}
Editorplain::setData(myType myData)
{
ui->label_2->setText(myData.textForEdit);
}
If its a custom QDialog just make the function setData() public . That way you can call the function from MainWindow passing your string before showing the dialog. You do not then need to pass anything through the constructor.
Something like in editorplain.h
public:
void setData(const QString &labelText);
and editorplain.cpp
void Editorplain::setData(const QString &labelText) {
ui->label_2->setText(labelText);
}
Now in mainwindow.cpp
void MainWindow::on_actionRoot_files_triggered()
{
QString er = ui->selected_filename->text();
Editorplain editorplainwidget;
editorplainwidget.setData(er);
editorplainwidget.exec();
}
You can just pass that string to Editorplain constructor, if that isn't a problem.