Qudpsocket readyread() don't work in try-catch block - c++

I wanna get message by UDP protocol.
If I create object to work with QUdpsocket in try-catch block, signal readyread() don't work.
But if I created UDPworker's object out of try-catch block - all OK.
What I did uncorrect in exceptions and Qt combo?
Is it about implementation QUdpsocket?
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QtDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//MyUDP m_UDP; // its work
try
{
MyUDP m_UDP; // its not work! WHY?!
}
catch(...)
{
qDebug()<< "Unknown exception cautch!!!" << endl;
}
return a.exec();
}
pr.pro
QT += core gui network
CONFIG += c++14 console
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
socket = new QUdpSocket(this);
socket->bind(QHostAddress::LocalHost, 6650);
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
#include <QMessageBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
//Base class QObject
class MyUDP : public QObject
{
Q_OBJECT
public:
explicit MyUDP(QObject *parent = 0);
void SayHello();
public slots:
void readData(){
QMessageBox::information(0, "Внимание","Это очень важный текст", 0,0,0);
}
private:
QUdpSocket *socket;
};
#endif // MAINWINDOW_H

You are creating MyUDP inside a try block, not catching any error an getting out of the try/catch scope, so MyUDP is begin destroyed:
try {
MyUDP m_UDP; // Created in the stack, valid only inside the try block
}
catch (...)
{
}
//m_UDP is already destroyed and undefined here
I should add that you are using QObjects, and signaling/slots mechanism not in intended/orthodox way, but that is beyond your question. You should read the documentation about the QObject and signal/slot mechanism, Qt has plenty of information both on-line and in the QtAssistant application.

Related

QT6 - signal/slot between 2 classes

I have created a new class for qpushbutton, I am trying to establish signal slot communication between this class and my mainwindow class
connect(&MyPushButton, &pushbutton::pb_isChecked, this, &MainWindow::MainWindowPBClicked, Qt::DirectConnection);
I used this code but as output only
qDebug("pushButtonClicked");
I can get this output. After that, the slot I called with "emit" does not work.
void pushbutton::pushButtonClicked()
{
if (isChecked())
{
qDebug("pushButtonClicked");
**emit pb_isChecked();**
}
}
all code in my project;
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow ui;
ui.show();
return app.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include "pushbutton.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void MainWindowPBClicked();
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);
pushbutton MyPushButton;
connect(&MyPushButton, &pushbutton::pb_isChecked, this, &MainWindow::MainWindowPBClicked, Qt::DirectConnection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::MainWindowPBClicked()
{
qDebug("MainWindowPBClicked");
}
pushbutton.h
#ifndef PUSHBUTTON_H
#define PUSHBUTTON_H
#include <QWidget>
#include <QPushButton>
class pushbutton : public QPushButton
{
Q_OBJECT
public:
explicit pushbutton(QWidget *parent = nullptr);
public slots:
void pushButtonClicked();
signals:
void pb_isChecked();
};
#endif // PUSHBUTTON_H
pushbutton.cpp
#include "pushbutton.h"
#include "mainwindow.h"
pushbutton::pushbutton(QWidget *parent)
: QPushButton{parent}
{
setAcceptDrops(true);
connect(this, &QPushButton::clicked, [this]() {
pushButtonClicked();
});
}
void pushbutton::pushButtonClicked()
{
if (isChecked())
{
qDebug("pushButtonClicked");
emit pb_isChecked();
}
}
CASE 1: Not creating button in UI file:
In your class MainWindow, variable MyPushButton is a local variable that gets destroyed after it end its scope in constructor. You need to create a dynamic variable of pushButton like this:
pushbutton *MyPushButton = new pushButton(this);
connect(MyPushButton, SIGNAL(pb_isChecked()), this, SLOT(MainWindowPBClicked()), Qt::DirectConnection);
CASE 2: Creating button in UI file:
In this case you cannot use your custom signal pb_isChecked(). You will need to use standard QPushButton signal such as clicked()
connect(ui->MyPushButton, SIGNAL(clicked()), this, SLOT(MainWindowPBClicked()), Qt::DirectConnection);

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 C++ prevent Runtime Error when close app

I'm writing a QT application and everything is fine with building and working but when i close the app with a thread running, the app closes and shows a message:
[Runtime Error....].
The application output says:
QThread: Destroyed while thread is still running
The program has unexpectedly finished.
The process was ended forcefully.
example crashed.
how to solve that ?
Example:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QString>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
example = new Thread(this);
connect(example, SIGNAL(print_line(QString)), this, SLOT(print_line2(QString)), Qt::BlockingQueuedConnection);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::print_line2(QString in)
{
ui->textBrowser->append(in);
}
void MainWindow::on_pushButton_clicked()
{
example->start();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <Thread.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Thread *example;
public slots:
void print_line2(QString in);
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Thread.cpp
#include "Thread.h"
#include <windows.h>
using namespace std;
Thread::Thread(QObject *parent):
QThread(parent)
{
}
Thread::~QThread()
{
delete ui;
}
void Thread::print(QString in)
{
print_line(in);
}
void Thread::run()
{
int count = 0;
for(;;) {
Sleep(100);
count += 1;
print(QString::number(count));
}
}
Thread.h
#ifndef READINFO_H
#define READINFO_H
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
public:
explicit Thread(QObject *parent =0);
void print(QString in);
void run();
signals:
void print_line(QString x);
};
#endif
Ready example
The problem is that the thread is still in the running state when your application shuts down.
The code inside Thread::Run() contains an infinite loop -- there is no way for it to terminate by itself. You need to write your thread so that it will exit, or at the very least, you need to forcefully terminate the thread before your app closes.
To forcefully terminate, you could add two lines of code to the MainWindow destructor like so:
MainWindow::~MainWindow()
{
example->terminate();
example->wait();
(...)
}

How correctly to call a function from another file?

OK, let's start again...
I've created an project (Qt Widget Application) with Qt Creator.
My project structure:
myproject.pro
Headers
dialogform.h
mainwindow.h
Sources
dialogform.cpp
main.cpp
mainwindow.cpp
Forms
dialogform.h
mainwindow.h
When I click on DialogForm pushbutton, I need to call the clear() function from MainWindow
In my code below, my project is running, but, the clear() function does not clear the lineedit.
Do anyone known how can i fix this?
Thank you very much!
dialogform.h
#ifndef DIALOGFORM_H
#define DIALOGFORM_H
#include <QDialog>
namespace Ui {
class DialogForm;
}
class DialogForm : public QDialog
{
Q_OBJECT
signals:
void clearMainWindow();
public:
explicit DialogForm(QWidget *parent = 0);
~DialogForm();
private slots:
void on_pbClearLineEdit_clicked();
private:
Ui::DialogForm *ui;
};
#endif // DIALOGFORM_H
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();
public slots:
void clear();
private slots:
void on_pbCallDialog_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
dialogform.cpp
#include "dialogform.h"
#include "ui_dialogform.h"
#include "mainwindow.h"
DialogForm::DialogForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogForm)
{
ui->setupUi(this);
}
DialogForm::~DialogForm()
{
delete ui;
}
void DialogForm::on_pbClearLineEdit_clicked()
{
connect(); // need help here. I'm using Qt 5.6.1
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialogform.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pbCallDialog_clicked()
{
DialogForm *dialogForm = new DialogForm(this);
dialogForm->show();
}
void MainWindow::clear()
{
ui->lineEdit->clear();
}
myfunction accesses an attribute of class myfile. Therefore it either needs to be a method of myfile as well, or it could be a friend function of the class myfile. In the latter case, however, you would need to give the relevant instance of myfile to myfunction as an argument. All usages of myfunction would need to be updated in either case.
The solution:
DialogForm::DialogForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogForm)
{
ui->setupUi(this);
connect(ui->pbClearLineEdit, &QPushButton::clicked, static_cast<MainWindow*>(parent), &MainWindow::clear);
}

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.