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.
}
Related
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();
}
I have a QMainWindow Application which also includes an QStackedWidget.
The pages of the QstackedWidget are promoted to ui widgets for example heating_widget.ui
If I use a button slot on my QMainWindow I can use this to get my application to fullscreen:
void SmartHome::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
But how can I do this from a button which is in the heating_widget.cpp file?
Using:
void heating_widget::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
obviously doesn't work and throws this error at me:
cannot call member function 'void
QWidget::setWindowState(Qt::WindowStates)' without object
SmartHome::setWindowState(Qt::WindowFullScreen);
I know this has something to do with parent() but I can't get it to work.
Do you have any idea?
My smarthome.h file:
#ifndef SMARTHOME_H
#define SMARTHOME_H
#include <QTime>
#include <QMainWindow>
namespace Ui {
class SmartHome;
}
class SmartHome : public QMainWindow
{
Q_OBJECT
public:
explicit SmartHome(QWidget *parent = 0);
~SmartHome();
private slots:
void on_Info_Button_clicked();
void on_News_Button_clicked();
void on_Heating_clicked();
void timerslot();
void on_Config_clicked();
void on_About_clicked();
public slots:
void setFullscreen();
private:
Ui::SmartHome *ui;
QTimer* myTimer;
};
#endif // SMARTHOME_H
My heating_widget.h :
#ifndef HEATING_WIDGET_H
#define HEATING_WIDGET_H
#include "smarthome.h"
#include <QWidget>
namespace Ui {
class heating_widget;
class SmartHome;
}
class heating_widget : public QWidget
{
Q_OBJECT
public:
explicit heating_widget(QWidget *parent = 0);
~heating_widget();
private slots:
void on_fullscreen_on_clicked();
private:
Ui::heating_widget *ui;
};
#endif // HEATING_WIDGET_H
and my heating.widget.cpp:
#include "heating_widget.h"
#include "ui_heating_widget.h"
#include "smarthome.h"
#include "iostream"
heating_widget::heating_widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::heating_widget)
{
ui->setupUi(this);
QObject::connect(ui->fullscreen_on, SIGNAL(clicked()), this , SLOT(SmartHome::setFullscreen()));
}
heating_widget::~heating_widget()
{
delete ui;
}
void heating_widget::on_fullscreen_on_clicked()
{
parentWidget()->setWindowState(Qt::WindowFullScreen);
std::cout<<"clicked"<<std::endl;
}
I would do it in the following way:
void heating_widget::on_fullscreen_on_clicked()
{
foreach(QWidget *widget, QApplication::topLevelWidgets()) {
if (auto mainWindow = qobject_cast<SmartHome *>(widget)) {
mainWindow->setWindowState(Qt::WindowFullScreen);
}
}
}
The idea is finding your main window among application top level widgets and change its state. This code can be called from anywhere in your application regardless of the windows hierarchy.
I would like to make some modifications of the main window from another file.
I created another ui file Form1Window (which open when a button is cliked in the MainWindow).
I want to call from the class Form1Window a function named test() of the MainWindow class
I succeed in calling function test() but I can't execute the whole content of the function (I can display a message but can't execute the part where I want to clear an edittext)
MainWindow.h
#include "form1window.h"
public slots:
void nettoyer();
private slots:
void openFrom1();
private:
Ui::MainWindow *ui;
From1Window *uiFrom1;
};
MainWindow.cpp
void MainWindow::openFrom1()
{
uiFrom1 = new From1Window(this);
uiFrom1->show();
}
void MainWindow::nettoyer(){
QMessageBox msgBox;
msgBox.setText("test");
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
ui->auteur->clear();
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
}
form1window.cpp
#include "mainwindow.h"
#include "ui_form1window.h"
void From1Window::on_supprimer_clicked()
{
MainWindow *a=new MainWindow ();
a->test();
close();
}
I've read about the role of the pointer of MainWindow class (C++ /Qt Proper way to access ui from another class in qt //Edited) and I've also tried connect()
Thank for your help
//THIS LINE HAS NO EFFECT WHEN CALLED FROM THE OTHER CLASS
this->ui->auteur->clear();
The line will never executed unless you dismiss QMessageBox. This is because you triggered QMessageBox with exec() function. This function has its own event queue and does not return until finishes. You may set QMessageBox as modal and display it with show() method. In that case QMessageBox will not block execution of the the flow.
This problem can also happen with QDialog(s) if you display them with exec().
I provide you a simple two window signal/slot example:
main.cpp
#include "mainwindow.h"
#include "form.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Form f;
f.show();
return a.exec();
}
form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QPushButton>
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
private:
QPushButton *pb;
};
#endif // FORM_H
form.cpp
#include "form.h"
#include "mainwindow.h"
#include <QDebug>
Form::Form(QWidget *parent) : QWidget(parent)
{
MainWindow *mw = new MainWindow();
pb = new QPushButton("clickME", this);
QObject::connect(pb, SIGNAL(clicked()), mw, SLOT(test()));
mw->show();
}
Form::~Form()
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void test();
private:
QLabel *l;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
l = new QLabel("test", this);
}
MainWindow::~MainWindow()
{
}
void MainWindow::test() {
qDebug() << "test called!" << endl;
l->setText("text changed");
}
This works for me.
output
i'm trying to change the label text of Class A via Class B using Qt but i can't get it working, here's my codes:
Class A:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "loldata.h"
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LoLData *lold = new LoLData();
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(updateData()));
QObject::connect(lold, SIGNAL(updatePlayerID(QString)), ui->label, SLOT(setText(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
Class A: (.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <string>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void updateData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Class B:
#include "loldata.h"
#include "mainwindow.h"
using namespace std;
int LoLData::getSummonerData(QString playerName)
{
emit updatePlayerID("playerName");
return 0;
}
Class B: (.h)
#ifndef DEF_LOLDATA
#define DEF_LOLDATA
#include <QApplication>
#include <QObject>
#include <string>
class LoLData : public QObject
{
Q_OBJECT
public:
int getSummonerData(QString playerName);
signals:
void updatePlayerID(QString playerName);
private:
};
#endif
You can see that i tried to use slots and signals but the text of the label is not changing, i saw a lot of examples on internet but i can't get them working
Thanks for your reply.
You are creating a new instance of LoLData here:
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
This instance of LoLData named summoner is not connected to your label's setText slot.
LoLData *lold = new LoLData(); - this instance of LolData is connected to you label's setText slot.
What should yo do?
It depends on what you want to accomplish:
either connect your summoner instance to the label by inserting a QObject::connect(&summoner...) inside yourupdateData` method;
or you don't instantiate a new LolData variable and use lold inside your updateData function:
void MainWindow::updateData()
{
lold->getSummonerData("Snylerr");
}
Also in this case you have to put lold as a member variable.
In your MainWindow constructor, you connect your lold object to the setText slot.
But in updateData, you use an other object (summoner) which is not connect to anything. So when you use getSummonerData on summoner, the signal updatePlayerID is emitted nut they is no slot connected to it.
I am trying to call a method called display_txt() from my_class. This method is supposed to change some text in a label. But the method doesn't make any changes to the ui. I know the method runs due to the qDebug(). No errors occur, but the label just doesn't change to "text changed". display_txt() works fine and changes the label when called from the main widget class. There is a similar question in the forums but I couldn't use those solutions. I make an object when the button btn is pressed.
Here is the code:
widget.h
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void display_txt();
private slots:
void on_btn_clicked();
private:
Ui::Widget *ui;
};
my_class.h
#include <QWidget>
#include "widget.h"
class my_class : public QWidget
{
Q_OBJECT
public:
explicit my_class(QWidget *parent = 0);
void test(Ui::Widget ui1);
signals:
private:
Widget *wo = new Widget;
};
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "my_class.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//display_txt();
qDebug() << "Widget object created";
}
void Widget::display_txt(){
ui->lbl->setText("text changes!!!!!");
qDebug() << "display_txt() method finished";
}
void Widget::on_btn_clicked()
{
my_class mc;
}
my_class.cpp
#include "my_class.h"
#include "QDebug"
my_class::my_class(QWidget *parent) : QWidget(parent)
{
qDebug() << "myclass ran";
wo->display_txt();
}