Solved Access an existing class and use QDialog::accept in a connect() to pass a QString value param?
-
Hello, wondering if you folks can give me some tips on a few issues I ran into while hobby coding during this pandemic. I currently have a Mainwindow that has a pushbutton and a QTreeWidget with items in it and tooltips added. Thank you so much.
- Is there a way to access an existing class? I use for example the Mainwindow *mainwindow; but it complains it's not right.
void Dialog::getItemText() { // todo: capture QTreeWidget selected item and pass it to: void MainWindow::showItemTextDialog() MainWindow * mainWindow; // todo: how to grab existing instance of MainWindow? mainWindow->show(); }
- Is there a way for a QDialog::accept() to pass a QString value as a param in a connect to a signal that requires it in another class?
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &Dialog::getItemText);
I've included the source code below, hope that's okay?
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(); signals: void showItemText(QString scenario); private slots: void showItemTextDialog(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <dialog.h> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::showItemTextDialog() { Dialog * dialog = new Dialog(); dialog->show(); // SIGNAL &Dialog::getItemText doesn't have a passed QString value as a param // but SLOT &MainWindow::showItemText has one as a param connect(dialog, &Dialog::getItemText, this, &MainWindow::showItemText); }
dialog.h #ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QDebug> #include <QTreeWidgetItem> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = nullptr); ~Dialog(); public slots: void getItemText(); void loadTreeItemText(QTreeWidgetItem* item, int column); private: Ui::Dialog *ui; QString treeItemName; }; #endif // DIALOG_H
dialog.cpp #include "dialog.h" #include "ui_dialog.h" #include "mainwindow.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &Dialog::loadTreeItemText); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &Dialog::getItemText); } Dialog::~Dialog() { delete ui; } void Dialog::getItemText() { // todo: capture QTreeWidget selected item and pass it to: void MainWindow::showItemTextDialog() MainWindow * mainWindow; // todo: how to grab existing instance of MainWindow? mainWindow->show(); } void Dialog::loadTreeItemText(QTreeWidgetItem* item, int column) { treeItemName = item->toolTip(column); qDebug() << "filePath: " << treeItemName; }
-
@Calicoder
Are you using QtCreator ?
If not , install it and start with creating New Project -> Qt Widget Application.
It builds "an Application" which is an unfortunate name for the Qt GUI code which processes the Qt implementation of "callback(s)" - "connect" SIGNAL / SLOTS .
In basic Qt Widget Application it "wraps" around the GUI - the "top layer " being "main window (form) " .
Then your can build your "dialog" sort-of eternally / independent to the "main window / process " and "connect" your dialog using its SIGNAL /SLOT to the main window.
Or even simpler - you could make your dialog a member of "Main Window " .
The key is - you need the "Application" to process the SIGNAL/SLOT.Best of luck coding
-
Hi, and welcome!
@Calicoder said in Access an existing class and use QDialog::accept in a connect() to pass a QString value param?:
// todo: how to grab existing instance of MainWindow?
At the time when you construct your Dialog, you can pass a pointer to your MainWindow instance to your Dialog instance. The Dialog can store the pointer as a member variable.
Some possible approaches are:
- Make the Dialog constructor accept a
MainWindow *
parameter, or - Create a dedicated function like
void Dialog::setTargetWindow(MainWindow *window)
and call it after you construct your Dialog.
// SIGNAL &Dialog::getItemText doesn't have a passed QString value as a param // but SLOT &MainWindow::showItemText has one as a param
You can't connect a signal with 0 parameters to a slot with 1 parameter. Instead, you can connect the signal to a lambda expression.
See here for an example: https://doc.qt.io/qt-5/signalsandslots-syntaxes.html#making-connections-to-lambda-expressions
Is there a way for a QDialog::accept() to pass a QString value as a param in a connect to a signal that requires it in another class?
A signal parameter must be emitted with the signal. For example, your
MainWindow
has a signal,void showItemText(QString scenario)
. To use this, write the following line somewhere in aMainWindow
function:emit showItemText("My Scenario");
When this line is run, the parameter value, "My Scenario" will be passed to all slots that are connected to the "showItemText" signal.
I've included the source code below, hope that's okay?
That's perfectly OK. In fact, we prefer it when users include source code because really helps us to understand your current code and understand your issue.
- Make the Dialog constructor accept a
-
Ok perfect, getting a good start. Tried to figure out the QDialog:accept signal and passing a QString param but no luck so far. I've broken down the code to this if it helps:
Dialog * dialog = new Dialog(); connect(dialog, &Dialog::accepted, this, &Widget::loadText); // &Widget::loadText(QString text)
As you can see the Widget::loadText() method takes a QString param, is there a another way to pass one from the &Dialog::accepted signal?
-
@Calicoder Like @JKSH suggested use a lambda:
connect(dialog, &Dialog::accepted, [this, yourText]() { loadText(yourText); });
But here yourText must be defined when you call connect(). You also could add a custom signal to your Dialog which will have QString parameter. Then in your Dialog when user accepts you emit that custom signal.
-
@Calicoder
Although the preceding answers are all "correct", I don't know why nobody has given you 2 simple answers to your questions:-
In
Dialog
you simply should not be trying to access yourMainWindow
. Your main main window can display a dialog, but the dialog should never access anything in the main window, or even know about it. -
The usual way of getting, say, a string back from a dialog it invokes does not involve any signal/slot. Instead the dialog should expose a getter. Typical code from main window will look like:
Dialog dialog; if (dialog.exec()) // checks for `accepted()` qDebug() << dialog.getItemText();
-
-
@Calicoder said in Access an existing class and use QDialog::accept in a connect() to pass a QString value param?:
Ok perfect, getting a good start.
Please follow @JonB suggestion. No need for signals and code is easier to follow and maintain in that case.
-
Thanks everyone, I ended up slowly reading the https://doc.qt.io/qt-5/signalsandslots.html Signals and Slots intro and ended up using the top example they showed and it works.