How do I edit QMainWindow UI Widget From Another Class? - c++

I need to edit a QLabel from MainWindow's UI in another source file. I've tried messing around with singals and slots, but honestly I'm completely lost and the Qt documentation doesn't help me in this exact situation. I understand that this has been asked in the past, but I have not found a solution that works for me. I'm new to Qt, and C++ in general.
I have the following code (greatly simplified):
"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();
void setFoo(char* text);
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);
this->statusBar()->setSizeGripEnabled(false);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::setFoo(char* text) {
ui->fooLabel->setText(text);
}
"secondwindow.h"
#ifndef SECONDWINDOW_H
#define SECONDWINDOW_H
#include <QWidget>
namespace Ui {
class SecondWindow;
}
class SecondWindow: public QWidget {
Q_OBJECT
public:
explicit SecondWindow(QWidget *parent = 0);
~SecondWindow();
private:
Ui::SecondWindow*ui;
}
#endif // SecondWindow_H
"secondwindow.cpp"
#include "secondwinodw.h"
#include "ui_secondwinodw.h"
#include "mainwindow.h"
SecondWindow::SecondWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecondWindow) {
ui->setupUi(this);
}
SecondWindow::~SecondWindow() {
delete ui;
}
void SecondWindow::on_fooButton_clicked() {
MainWindow::setFoo("example");//The method is private so this is not possible, but this is my goal
}
When a user clicks on fooButton, I need to access and edit the MainWindow's UI QLabel(or a public method that does this).
The secondwindow is not being created in the main() function
void MainWindow::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_A:
if (event->modifiers()==Qt::ShiftModifier) {
SecondWindow*secwind= new SecondWindow();
secwind->show();
}
break;
}
}

In OOP the ones that interact are the objects, not the classes or the files, that is, the following expression:I need to edit QLabel from MainWindow's UI in another source file It does not make sense, what you should say is that an object of the MainWindow class is modified by another object of the SecondWindow class. The files do not make the program, the interaction between objects do it.
I'm assuming that both objects are created in the main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
SecondWindow w2;
w1.show();
w2.show();
return a.exec();
}
Now if I go to attack the main problem, Qt handles the concept of signals and slots, so we will use it, as the action to a SecondWindow object will cause the information to be sent, I will create a signal that carries that information:
secondwindow.h
#ifndef SECONDWINDOW_H
#define SECONDWINDOW_H
#include <QWidget>
namespace Ui {
class SecondWindow;
}
class SecondWindow: public QWidget {
Q_OBJECT
public:
explicit SecondWindow(QWidget *parent = 0);
~SecondWindow();
signals:
void messageChanged(const QString & message); // <---
private slots:
void void SecondWindow::on_fooButton_clicked();
private:
Ui::SecondWindow*ui;
}
#endif // SecondWindow_H
when the button is pressed, the signal with the information must be emitted
secondwindow.cpp
...
void SecondWindow::on_fooButton_clicked() {
emit messageChanged("example");//The method is private so this is not possible, but this is my goal
}
Now we go to the receiver's side, how will we get a slots, you have done it but do not use char *, that's C, we're using C++ and much better we're using Qt, it's best to use QString:
mainwindow.h
....
void setFoo(const QString & text);
mainwindow.cpp
...
void MainWindow::setFoo(const QString & text) {
ui->fooLabel->setText(text);
}
And finally we make the connections:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
SecondWindow w2;
QObject::connect(&w2, &SecondWindow::messageChanged, &w1, &MainWindow::setFoo);
w1.show();
w2.show();
return a.exec();
}
update:
void MainWindow::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_A:
if (event->modifiers()==Qt::ShiftModifier) {
SecondWindow*secwind= new SecondWindow();
connect(secwind, &SecondWindow::messageChanged, this, &MainWindow::setFoo);
secwind->show();
}
break;
}
}

Related

Thread and GUI handling

In my App I have some problems with threads and GUI messages like QMessageBox or a new dialog. To reproduce I made a small app to show the problem:
mainwindow.cpp
#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
void ThreadAddTree::run() {
//mClass->addTreeEx();
bool b = false;
emit addTree(&b);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString path = "";
mThreadAddTree = new ThreadAddTree(this, path);
connect(mThreadAddTree, SIGNAL(addTree(bool*)), this, SLOT(on_add_tree(bool*)), Qt::BlockingQueuedConnection);
//,Qt::DirectConnection
mThreadAddTree->start();
}
void MainWindow::on_add_tree(bool* newData) {
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
*newData = true;
}
void MainWindow::addTreeEx()
{
QMessageBox::information(this, tr("Information"),
tr("Button click!"));
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWidgets>
#include <QThread>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class ThreadAddTree : public QThread
{
Q_OBJECT
public:
ThreadAddTree(class MainWindow *nClass, const QString &path) {
mPath = path;
mClass = nClass;
}
signals:
void addTree(bool*);
protected:
void run();
QString mPath;
class MainWindow *mClass;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
friend class ThreadAddTree;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void addTreeEx();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
protected:
ThreadAddTree *mThreadAddTree;
protected Q_SLOTS:
void on_add_tree(bool* newData);
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
If I use in Thread the call: mClass->addTreeEx(); the app will crash, in case of non main GUI thread. Understood.
So I uncouple the call with emit a message emit addTree(&b); works well. Messagebox is shown and no crash.
But now it becomes complicated for me. I need to call mClass->addTreeEx(); in my app because it will do a couple of operations. The same function is also used outside an additional thread.
But in one case, the mClass->addTreeEx(); that is running inside the thread need to call the Messagebox.
So my question is here, how to manage, that I can emit the emit addTree(&b); from the function mClass->addTreeEx(); if it was called from the thread and the app will not crash in case of no GUI thread?
Interpreting the code author's intent (to degree) and open to be corrected.
The signal parameter of type bool* in void addTree(bool*); makes not much sense especially for the case with signal sender having the boolean variable on the stack. Either make it void addTree(bool) and send immediate value or just void addTree() and handle the boolean atomic flag on the slot side as std::atomic_bool thread_safe_flag; so checking on that flag will be as actual as possible if (thread_safe_flag). But such handling requires even more to ensure the signal delivered at the right time in sync with the value. This is irrelevant to Qt, though: Why do I need to acquire a lock to modify a shared "atomic" variable before notifying condition_variable and can be done either with or without Qt.
The problem of message box on UI thread preventing the other message box from appearing (this is again an interpretation of the author's problem with the code). We obviously need to have a handle operate the message box, say, dismiss it, in case if it is open already:
QMessageBox* m_msgBoxPtr{nullptr};
std::atomic_bool m_threadSafeFlag;
void UI_Class::mySlotToHandleMsgBox()
{
if (m_msgBoxPtr != nullptr) {
m_msgBoxPtr->close();
m_msgBoxPtr->deleteLater();
m_msgBoxPtr = nullptr;
mySlotToHandleMsgBox();
}
else {
m_msgBoxPtr = new QMessageBox(QMessageBox::Information, title, message);
m_msgBoxPtr->exec(); // assuming we want modal dialog as QMessageBox::information()
// otherwise do m_msgBoxPtr->show()
// if this is set on UI thread only then and no
// "waits" for it on other threads then it being atomic is enough;
// then don't bother with any sync "complications"
m_threadSafeFlag = true;
}
}
mainworker.h
#ifndef MAINWORKER_H
#define MAINWORKER_H
#include <QObject>
class MainWorker : public QObject
{
Q_OBJECT
signals:
void completed(void);
public slots:
void run(void);
};
#endif // MAINWORKER_H
mainworker.cpp
#include "mainworker.h"
#include <QThread>
void MainWorker::run(void)
{
QThread::sleep(1);
emit completed();
}
mainthread.h
#ifndef MAINTHREAD_H
#define MAINTHREAD_H
#include <QThread>
class MainThread : public QThread
{
Q_OBJECT
public:
MainThread(void);
};
#endif // MAINTHREAD_H
mainthread.cpp
#include "mainthread.h"
MainThread::MainThread(void)
: QThread(nullptr)
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(void);
signals:
void runJob(void);
public slots:
void jobCompleted(void);
private:
QPushButton m_runButton;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(void)
: QMainWindow(nullptr),
m_runButton(this)
{
connect(&m_runButton, SIGNAL(released()), this, SIGNAL(runJob()));
m_runButton.setText("RUN!");
setCentralWidget(&m_runButton);
}
void MainWindow::jobCompleted(void)
{
QMessageBox::information(this, tr("Info"), tr("Job completed!"));
}
main.cpp
#include <QApplication>
#include "mainwindow.h"
#include "mainthread.h"
#include "mainworker.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow window;
MainThread thread;
MainWorker worker;
worker.connect(&window, SIGNAL(runJob()), &worker, SLOT(run()));
window.connect(&worker, SIGNAL(completed()), &window, SLOT(jobCompleted()));
worker.moveToThread(&thread);
thread.start();
window.show();
int exitCode = a.exec();
thread.quit();
thread.wait();
return exitCode;
}
Of course you can add args to signals and slots and call jobCompleted() slot any time from GUI thread.

How to send variables between classes in Qt

I have a problem. I created two classes in my Qt project. One as the main window, and second as the settings dialog. My idea is to send the values from "Settings" to "MainWindow" (like from one TextEdit to another) but unfortunately, I have no idea how to do it. It's confusing me. I have read similar topics on the internet but none of them gives me a clear answer. Can someone help me understand the way how can I do it via example?
I have no useful code to place it here, so I will put the part of the source code and headers of mine.
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
[...]
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "settings.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow()
[...]
private:
Ui::MainWindow *ui;
[...]
};
#endif // MAINWINDOW_H
settings.cpp
#include "settings.h"
#include "ui_settings.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
Settings::Settings(QWidget *parent) :
QDialog(parent),
ui(new Ui::Settings)
{
ui->setupUi(this);
}
settings.h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QDialog>
namespace Ui {
class Settings;
}
class Settings : public QDialog
{
Q_OBJECT
public:
explicit Settings(QWidget *parent = nullptr);
~Settings();
[...]
private:
Ui::Settings *ui;
[...]
};
#endif // SETTINGS_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Use signals/slots mechanism to share values between two QObject.
For example:
The following code allows yout to send the value in a QLineEdit to another widget by clicking on a button:
class Widget1: public QWidget
{
Q_OBJECT
public:
Widget1(): QWidget(),
message(new QLineEdit())
{
QPushButton* button = new QPushButton("Send msg", this);
connect(button, &QPushButton::clicked, this, [=]() { emit this->sendMsg(message->text());}); // When you click on the button, it will emit the signal sendMsg
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(message);
layout->addWidget(button);
}
private:
QLineEdit* message;
signals:
void sendMsg(QString const& msg);
};
class Widget2: public QWidget
{
Q_OBJECT
public:
Widget2(): QWidget(),
display(new QLabel("Nothing to display", this))
{
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(display);
}
private:
QLabel* display;
public slots:
void receive(QString const& message)
{
display->setText(message); // When called, display the message in the label
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget* mainWidget = new QWidget();
QHBoxLayout* layout = new QHBoxLayout(mainWidget);
Widget1* w1 = new Widget1();
Widget2* w2 = new Widget2();
layout->addWidget(w1);
layout->addWidget(w2);
// When the signal sendMsg is emitted, call the slot receive
QObject::connect(w1, &Widget1::sendMsg, w2, &Widget2::receive);
mainWidget->show();
return app.exec();
}
There are multiple ways to achieve this.
For example you can provide the public Getter Methods in your dialog for provide value to the public and use them directly in the MainWindow to read those.
Or you can use Signals/Slots as stated above.
One example with Signal/Slots:
The SettingsWindow emits textEdit(QString) signal if Dialog Accepted, and MainWindow receives this signal via on_textEdit(QString) slot and writes it to its own text field:
SettingsWindow reading text input and emitting signal textEdit(QString):
MainWindow receiving signal via slot on_textEdit(QString):
And this is the code:
maindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_textEdited(QString txt);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "settingsdialog.h"
#include <memory>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
auto dlg = new SettingsDialog{this};
connect(dlg, &SettingsDialog::textEdit, this, &MainWindow::on_textEdited);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->show();
}
void MainWindow::on_textEdited(QString txt)
{
ui->textEdit->setText(txt);
}
settingsdialog.h
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include <QDialog>
namespace Ui {
class SettingsDialog;
}
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog();
signals:
void textEdit(QString txt);
private slots:
void on_buttonBox_accepted();
private:
Ui::SettingsDialog *ui;
};
#endif // SETTINGSDIALOG_H
settingsdialog.cpp
#include "settingsdialog.h"
#include "ui_settingsdialog.h"
SettingsDialog::SettingsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SettingsDialog)
{
ui->setupUi(this);
}
SettingsDialog::~SettingsDialog()
{
delete ui;
}
void SettingsDialog::on_buttonBox_accepted()
{
emit textEdit(ui->textEdit->toPlainText());
}
More about Signal/Slots

Qt make modification of MainWindow from another class

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

Using Signals and Slots to Comunicate a QDialog with MainWindow in Qt

Ok I think is time to get some help, I have been practicing with signals and slots in Qt and I got stocked. What I want is to be able to change a label in mainwindow when a button in a QDialog is clicked. I have been searching and apparently the only way to do this is basically using signals and slots, here is what I have...
I have a mainwindow.ui with a button called "pushButton_OpenWindow" and a QLabel label_ShowText", I also have a externaldialog.ui that contains a QLineEdit called lineEdit_ExternalInput" and a QPushButton called "pushButton_SendText", and what I want is to change "label_ShowText" to whatever value "lineEdit_ExternalInput" is when pushButton_SendText" is clicked but it doesn't work, when I click the button nothing happens no errors, no warnings nothing.
Here is the code that doesn't work...
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_OpenWindow_clicked();
void textValue(const QString &newText);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "externaldialog.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ExternalDialog *externalDialog = new ExternalDialog;
// connecting signals and slots
QObject::connect(externalDialog, SIGNAL(textChanged(QString)), this, SLOT(textValue(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_OpenWindow_clicked()
{
ExternalDialog mDialog;
mDialog.setModal(true);
mDialog.exec();
}
void MainWindow::textValue(const QString &newText)
{
ui->label_ShowText->setText(newText);
qDebug()<<"Message from textValue Function \n";
}
externaldialog.h
#ifndef EXTERNALDIALOG_H
#define EXTERNALDIALOG_H
#include <QDialog>
namespace Ui {
class ExternalDialog;
}
class ExternalDialog : public QDialog
{
Q_OBJECT
public:
explicit ExternalDialog(QWidget *parent = 0);
~ExternalDialog();
private:
Ui::ExternalDialog *ui;
signals:
void textChanged(const QString&);
public slots:
void on_pushButton_SendText_clicked();
};
#endif // EXTERNALDIALOG_H
externaldialog.cpp
#include "externaldialog.h"
#include "ui_externaldialog.h"
#include <QDebug>
ExternalDialog::ExternalDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ExternalDialog)
{
ui->setupUi(this);
}
ExternalDialog::~ExternalDialog()
{
delete ui;
}
void ExternalDialog::on_pushButton_SendText_clicked()
{
emit textChanged(ui->lineEdit_ExternalInput->text());
qDebug()<<"Sent Message";
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Any idea what I'm I doing wrong? Any suggestion will be appreciated. Sorry I posted the whole code but sometimes is better to see the whole picture.
Thanks a lot
change function MainWindow::on_pushButton_OpenWindow_clicked() into this
void MainWindow::on_pushButton_OpenWindow_clicked()
{
externalDialog->setModal(true);
externalDialog->exec();
}
You have just create a new unconnected dialog in the original function.

Changing the currentIndex() of a tab widget when a different item is selected from a drop-down box

I'm new to C++ and I'm just start to port a program that was originally in python/Qt to C++/Qt in order to take advantage of a better terminal widget that I can embed in my program. Right now I'm a bit stuck, I'm trying to setup where if a different item from a drop-down box is selected the currentIndex() of a tab widget is changed accordingly.
Heres my code so far:
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
heres the mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTimer *timer;
void startMyTimer()
{
timer = new QTimer();
timer->setInterval(1);
timer->start();
QObject::connect(timer,SIGNAL(timeout()),this,SLOT(changeIndex()));
}
private:
Ui::MainWindow *ui;
void changeIndex();
};
#endif // MAINWINDOW_H
And lastly heres the mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
changeIndex();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeIndex()
{
if (ui->comboBox->currentText() == "add-apt-repository")
{
ui->stackedWidget->setCurrentIndex(0);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "apt-get")
{
ui->stackedWidget->setCurrentIndex(1);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "aptitude")
{
ui->stackedWidget->setCurrentIndex(2);
ui->checkBox->setCheckState(Qt::Checked);
}
if (ui->comboBox->currentText() == "bzr")
{
ui->stackedWidget->setCurrentIndex(3);
ui->checkBox->setCheckState(Qt::Unchecked);
}
if (ui->comboBox->currentText() == "cd")
{
ui->stackedWidget->setCurrentIndex(4);
ui->checkBox->setCheckState(Qt::Unchecked);
}
if (ui->comboBox->currentText() == "chmod")
{
ui->stackedWidget->setCurrentIndex(5);
ui->checkBox->setCheckState(Qt::Checked);
}
}
I've looked at a bunch of QTimer examples but I'm at a loss.
I also tried doing if (ui->comboBox->changeEvent()) but I was probably using that wrong as well.
First, you probably have to mark changeIndex() as a slot, like this:
class MainWindow : public QMainWindow
{
Q_OBJECT
// ...
private slots:
void changeIndex();
private:
Ui::MainWindow *ui;
}
This also requires you to invoke the Qt meta object compiler. If you use qmake, that's already done for you. Otherwise, it depends on your build system.
Second, is there any particular reason for using the timer? You can also connect to one of the combo box's currentIndexChanged signals.
Drop the timer, it's of no use here.
Instead, make changeIndex() a slot by putting it into a "private slots:" section:
public slots:
void changeIndex();
Then connect the combobox's currentIndexChanged signal to your slot, in the MainWindow constructor:
connect( ui->combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(changeIndex()) );