QMainWindow close button gets inactive while QNetworkReply is reading data - qt

Here is some idea of my code.It executes successfully. I am just not able to use close button the moment it starts executing read statement.!
inside main():
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
this is my constructor: one main window and a button that calls execute when clicked
inside MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) //this creates a window that has a download button
{
setWindowTitle("File Downloader");
QWidget* central = new QWidget(this);
QVBoxLayout *lay = new QVBoxLayout(central);
button1 = new QPushButton("Download", this);
connect(button1, SIGNAL (clicked()),this,SLOT( execute()));
lay->addWidget(button1);
manager = new QNetworkAccessManager(this);
}
this function sets up connection with php file and then calls sendFinished
void MainWindow::execute() //PHP file link here
{
QUrl url"/patofmyphp");
reply = manager->post(request, data); //data is some string
connect(reply, SIGNAL (finished()),this,SLOT( sendFinished()));
}
this function reads data from php file in chunks
void MainWindow::sendFinished() //this gets called successfully
{
while(copied < size) //copied = 0, size = 10000;
{
const QByteArray data = reply->read(tocopy);
file.write(data);
copied += data.size();
}
}
Whole program is running successfully. But when I want to abort my reply using closebutton of QMainWindow before program gets executed successfully. But the moment it reply->read gets executed, it seems close button stops working. What should I do?

Looks like I solved my issue just by using this line inside my while loop.
QApplication::processEvents(); if(close == true) { closeProgram(); }

Related

QT Qapplication stuck in "return a.exec() " in calculation Loop

I simulated a dynamical device like mass spring damper.the QT Solves the equation of motion in Real Time and displays the output. I want to use an Qapplication object,to display Data and the outputs in "Real time". whole problem and display output is inside a loop.Everything is going well, but when the program reaches to command return a.exec() for display output,the GUI window Has come up and remain in the firest iteration." I expect don't gets stuck there and At each loop the program runs And at the end of loop update the GUI window in "Real time".
here is my code:
#include "QtWidgets/QApplication"
#include "QtWidgets/QGraphicsScene"
#include "QObject"
#include "QTimer"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Motion* ball = new Motion();
// create a scene
QGraphicsScene * scene = new QGraphicsScene();
QGraphicsRectItem* rect = new QGraphicsRectItem();
//show the view
view->show();
The Loop I talked about that.
for (int i = 0; i<int(j); i++)
{
Sleeper::msleep(50);
double t = time->getTime() + i*0.05;
states2 = world.openLoopSys;
for (int i=0; i<12; i++)
{
states1(i) = states2(i);
}
ball->run();
return a.exec(); // gets stuck there !!!
}
The Motion class is:
#include "motion.h"
Motion::Motion()
{
// create an item to put into the scene
setRect(0,0,20,30);
setPos(x(),y());
pos_x = 0;
pos_y = 0;
}
void Motion::run()
{
// connect
QTimer * timer = new QTimer();
connect(this,SIGNAL(timeout()),this,SLOT(move()));
timer->start(50);
}
void Motion::move()
{
setPos(x(),y()-5);
// setPos(0.01*pos_x,-0.01*pos_y);
}
How can I solve this problem?

Qt Call Form in Main function after close a form

I am new to Qt. I trying convert my existing Gtk2 Project to Qt for Cross-Platform Support.
My Code as follows:
// main.cpp
int success = 0;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
success = 0;
Logon *l = new Logon();
l->show();
if(success == 1) // success flag set in Logon.cpp when connection created !
{
Menu *m = new m();
m->show();
}
return a.exec();
}
// logon.cpp
void Logon::OnOkBtnClicked(void)
{
if(!ValConnection())
return;
success = 1;
this->destroy();
}
While execute the code, the connection successfully created & the logon for disappears. But, Menu form doesn't appears.
Kindly help me to solve this.
Try to use SIGNAL/SLOT method with lambda function.
Logon .h side:
class Logon : public QObject
{
Q_OBJECT
<...>
signals:
void success(int scs);
public slots:
bool ValConnection();
}
Logon .cpp side:
// Where button creation
connect(button, &QPushButton::clicked, this, &Logon::ValConnection);
// Somewhere on ValConnection
if(true)
emit success(1);
Main side:
QObject::connect(l, &QLogon::success, [=] (int scs) {
if(scs == 1) {
Menu *m = new m();
m->show();
}
});

Open QDialog and run the QProcess simultaneously

This is my btconnect.h file
#ifndef BTCONNECT_H
#define BTCONNECT_H
#include "scandialog.h"
namespace Ui {
class BTConnect;
}
class BTConnect : public QWidget
{
Q_OBJECT
public:
explicit BTConnect(QWidget *parent = 0);
~BTConnect();
private slots:
void on_ScanButton_clicked();
void ScanBTDevices();
//some slots here
void ScanDialogShow();
void ScanDialogClose();
public slots:
//some slots here
private:
Ui::BTConnect *ui;
QProcess BTscan_Process;
scanDialog *scan;
};
#endif // BTCONNECT_H
btconnect.cpp
BTConnect::BTConnect(QWidget *parent) :
QWidget(parent),
ui(new Ui::BTConnect)
{
//set the userinterface as BTConnect.ui
ui->setupUi(this);
scan = new scanDialog(this);
}
void BTConnect::ScanDialogShow()
{
scan->show();
}
void BTConnect::ScanDialogClose()
{
scan->close();
}
void BTConnect::ScanBTDevices()
{
ScanDialogShow();
//Command to scan nearby bluetooth devices
//"hcitool scan"
QString cmd("hcitool scan");
//start the process
BTscan_Process.start(cmd);
//Wait for the processs to finish with a timeout of 20 seconds
if(BTscan_Process.waitForFinished(20000))
{
//Clear the list widget
this->ui->listWidget->clear();
//Read the command line output and store it in QString out
QString out(BTscan_Process.readAllStandardOutput());
//Split the QString every new line and save theve in a QStringList
QStringList OutSplit = out.split("\n");
//Parse the QStringList in btCellsParser
btCellsParser cp(OutSplit);
for(unsigned int i = 0; i<cp.count(); i++)
{
//writing in listwidget
}
}
ScanDialogClose();
}
void BTConnect::on_ScanButton_clicked()
{
//Scan for available nearby bluetooth devices
ScanBTDevices();
}
if I use the above code, the qdialog scandialog does open when the process begins and closes when the data is loaded in qlistwidget, but the contents of qdialog scandialog are not displayed. If I were to change show() to exec(), the contents will be shown but the QProcess does not run until the dialog is closed.
I want the dialog to open when the Qprocess starts and close when the qlistwidget is loaded with data from the scan. And I want the contents of scandialog to be displayed. It has two labels. One with .GIF file and another with text saying scanning.
Any help is appreciated.
you never return to the event loop when you do show (because of waitForFinished) and you never continue to the processing code when you do exec
instead of the waitForFinished you should connect to the finished signal and handle it there and use a single shot timer that will cancel it:
void BTConnect::on_BTscanFinished()//new slot
{
//Clear the list widget
this->ui->listWidget->clear();
//Read the command line output and store it in QString out
QString out(BTscan_Process.readAllStandardOutput());
//Split the QString every new line and save theve in a QStringList
QStringList OutSplit = out.split("\n");
//Parse the QStringList in btCellsParser
btCellsParser cp(OutSplit);
for(unsigned int i = 0; i<cp.count(); i++)
{
//writing in listwidget
}
ScanDialogClose();
}
void BTConnect::ScanBTDevices()
{
ScanDialogShow();
//Command to scan nearby bluetooth devices
//"hcitool scan"
QString cmd("hcitool scan");
//start the process
connect(BTscan_Process, SIGNAL(finished()), this, SLOT(on_BTscanFinished()));
BTscan_Process.start(cmd);
QTimer::singleShot(20000, scan, SLOT(close()));
}
The problem is that QDialog::exec and QProcess::waitForFinished functions block event loop. Never ever block event loop. So you just need to do things more asynchronously.
QProcess class can be handled asynchronously using signals like readReadStandardOutput. And QDialog can be shown asynchronously using open slot.
The example:
void ScanBTDevices() {
// Open dialog when process is started
connect(process, SIGNAL(started()), dialog, SLOT(open()));
// Read standard output asynchronously
connect(process, SIGNAL(readyReadStandardOutput()), SLOT(onReadyRead()));
// Start process asynchronously (for example I use recursive ls)
process->start("ls -R /");
}
void onReadyRead() {
// Write to list widget
dialog->appendText(QString(process->readAllStandardOutput()));
}
The data will be appended to the dialog during generating by process.
Also using QProcess::finished signal and you can close the dialog.

How to exit my Qt console program through a function with parent?

/EDIT: solved, see my comment in the 1st answer!/
I am currently building an application which only has a tray icon displayed, so it doesn't have any windows.
Well, in the tray icon I've included a QAction so as to close the application. The thing is, that I get seg fault when I call exit(0); from that function. This is some example code:
//I have a reason for setting it to be a QTimer, please don't even comment on this
class Boot_Timer : public QTimer {
Q_OBJECT
public:
explicit Boot_Timer(QObject *parent = 0) : QTimer(parent) {
}
public Q_SLOTS:
void set_up_command_line_tray(){
//Setting up the tray Icon.
QSystemTrayIcon *trayIcon_cmd = new QSystemTrayIcon(this);
trayIcon_cmd->setIcon(QIcon(":/icons/Pictures/myapp.png"));
trayIcon_cmd->setToolTip("My tray tooltipp");
QMenu *changer_menu = new QMenu;
QAction *Quit_action = new QAction(tr("&Quit"), this);
Quit_action->setIconVisibleInMenu(true);;
connect(Quit_action, SIGNAL(triggered()), this, SLOT(close_application()));
changer_menu->addAction(Quit_action);
trayIcon_cmd->setContextMenu(changer_menu);
trayIcon_cmd->show();
}
void close_application(){
//HERE I GET SEG FAULT
exit(0);
}
};
Boot_Timer boottimer;
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//making some checks (code omitted)
...
boottimer.set_up_command_line_tray()
return app.exec();
}
So, the tray icon is shown normally and perfectly, but when I choose to Quit the application using the menu I've added to the tray icon, I get a seg fault. I guess that I cannot quit the application using exit(int state) outside main() function and its functions that don't have a parent...
What is the correct way to quit my application, then?
Thanks in advance for any answers!
Try to call
qApp->quit(0);
instead of
exit(0);
Remember to #include <QApplication>.
Thanks, that didn't solve it. For some reason, the thing that solved it was to do the following: QSystemTrayIcon *trayIcon_cmd = new QSystemTrayIcon(0); instead of QSystemTrayIcon *trayIcon_cmd = new QSystemTrayIcon(this)

Open new dialog from a dialog in qt

I am trying to open a new dialog Window from a existing dialog on a a button click event,but I am not able to do this as i opened the dialog window from MainWindow.
I am trying with:
Dialog1 *New = new Dialog1();
New->show();
Is there a different way of opening dialog window form existing dialog Window???
There must be some other problem, because your code looks good to me. Here's how I'd do it:
#include <QtGui>
class Dialog : public QDialog
{
public:
Dialog()
{
QDialog *subDialog = new QDialog;
subDialog->setWindowTitle("Sub Dialog");
QPushButton *button = new QPushButton("Push to open new dialog", this);
connect(button, SIGNAL(clicked()), subDialog, SLOT(show()));
}
};
class MainWindow : public QMainWindow
{
public:
MainWindow()
{
Dialog *dialog = new Dialog;
dialog->setWindowTitle("Dialog");
dialog->show();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("Main Window");
w.show();
return a.exec();
}
By the way, note how I've connected QPushButton's "clicked" signal to QDialog's "show" slot. Very handy.
I am new to QT and I did have a similar problem. In my case, I was calling the new dialog from a function from the main dialog. I was using dlg->show which does not wait until the result of the new dialog. Hence the program still running. I change dlg->show for dlg->exec and the dialog works now. In your code, the dialog seems to be a local variable, perhaps you have the same problem. Other option could be to use a static pointer instead.
Dialog1 *newDlg = new Dialog1();
this->hide();
int result = newDlg->exec();
this->show();
delete newDlg;
in mainwindow.h file you should declare a pointer to your new dialog
and include the new dialog.h like
#include <myNewDialog.h>
private:
Ui::MainWindow *ui;
MyNewDialog *objMyNewDialog;
and after that you can call your dialog to be shown up in mainwindow.cpp
like
void MainWindow::on_btnClose_clicked()
{
objMyNewDialog= new MyNewDialog(this);
objMyNewDialog->show();
}

Resources