setQuitOnLastWindowClosed(false) has disabled 'x' button on window / dialog QT - qt

In order to get my MessageBox working correctly (and not shutting the whole application) - I have had to setQuitOnLastWindowClosed to False.
This means however that pushing the 'x' button on my QDialog does not exit the application properly. Any help?
Here is the code:
Main.cpp
#include "openingdialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
Dialog w;
w.show();
return a.exec();
}
Dialog code:
#include "openingdialog.h"
#include "ui_openingdialog.h"
#include "patientsetup.h"
#include <QDesktopServices>
#include <QUrl>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
connect(ui->okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));
connect(ui->guideButton, SIGNAL(clicked(bool)), this, SLOT(guideButtonClicked()));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::okButtonClicked()
{
psetup = new pmps_f(this);
psetup->show();
}
void Dialog::guideButtonClicked()
{
QDesktopServices::openUrl(QUrl::fromLocalFile("C:/PMPS/PMPSv1/Instructionsforuse.pdf"));
}
MessageBox code:
void pmps_f::start()
{
QMessageBox msgBox;
msgBox.setText("Pressing OK will start the sedation process with the baseline target effect-site Ce of 0.5mcg/ml");
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int ret = msgBox.exec();
switch(ret) {
case QMessageBox::Ok:
break;
case QMessageBox::Cancel:
break;
}
}
Construction of MainWindow:
pmps_f::pmps_f(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::pmps_f)
{
ui->setupUi(this);
connect(ui->startbutton,SIGNAL(clicked(bool)), this, SLOT(start()));
}

Related

How to use QTimer to view a image sequence?

In the program, I am trying to create a image player using QT. When I click a button in the UI, the program will create a image slideshow with a 2s pause. I tried to use the QTimer to such things, but failed to do so. Hence, I want to ask how to achieve my purpose by using QTimer.
Let me describe the flow of my program. When the user click a button in the main window, the sub-window showpic will be opened and then start showing each image for a pause of 2s in its qgraphsview. The images filepath are stored in the "QStringlist filenames".
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
#include "showpic.h"
#include <QBasicTimer>
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void display(const QString & , ShowPic* );
private slots:
void tick();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QFileSystemModel *model;
QString filesPath;
ShowPic *showpic;
QStringList filenames;
QStringList::const_iterator m_imageIt;
QTimer m_timer;
};
#endif // MAINWINDOW_H
showpic.h
#ifndef SHOWPIC_H
#define SHOWPIC_H
#include <QWidget>
namespace Ui {
class ShowPic;
}
class ShowPic : public QWidget
{
Q_OBJECT
public:
explicit ShowPic(QWidget *parent = 0);
~ShowPic();
private:
Ui::ShowPic *ui;
public:
void addPixmap(const QPixmap &pixmap);
};
#endif // SHOWPIC_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();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QFileDialog>
#include<QFileSystemModel>
#include<QStringList>
#include <QTreeView>
#include <QGraphicsScene>
#include <QTime>
#include <QThread>
#include <QDebug>
#include <iostream>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
filenames.append("C:\\test\\image.jpg");
filenames.append("C:\\test\\apple.jpg");
filenames.append("C:\\test\\orange.jpg");
filenames.append("C:\\test\\lemon.jpg");
filenames.append("C:\\test\\grape.jpg");
m_imageIt = filenames.begin();
m_timer.setInterval(5000);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::display(const QString & filename, ShowPic* showpic) {
showpic->addPixmap(filename);
}
void MainWindow::tick(){
showpic = new ShowPic();
showpic->show();
display(*m_imageIt, showpic);
m_imageIt ++;
}
/*
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId()) tick();
}*/
void MainWindow::on_pushButton_clicked()
{
/*showpic = new ShowPic();
QPixmap pixmap("C:\\test\\image.jpg");
showpic->addPixmap(pixmap);
showpic->show();*/
m_timer.start();
}
showpic.cpp
#include "showpic.h"
#include "ui_showpic.h"
#include <QThread>
ShowPic::ShowPic(QWidget *parent) :
QWidget(parent),
ui(new Ui::ShowPic)
{
ui->setupUi(this);
ui->graphicsView->setScene(new QGraphicsScene);
}
ShowPic::~ShowPic()
{
delete ui;
}
void ShowPic::addPixmap(const QPixmap &pixmap){
ui->graphicsView->scene()->addPixmap(pixmap);
}
The compiling message error:
The error has nothing to do with the timer, it is because you forgot to declare display(), tick(), and timerEvent() as part of the MainWindow:: class, so they cannot access MainWindow members.
The timer should be even easier to use than your code. First I recommend you use a QTimer instead of QBasicTimer. Then you can simply connect to its timeout() signal.
mainwindow.h
#include <QTimer>
QTimer m_timer;
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
m_imageIt = filenames.begin();
m_timer.setInterval(5000);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
}
void MainWindow::on_pushButton_clicked()
{
m_timer.start();
}
You do not need timerEvent() function at all.

Qt QMessageBox - closes application instead of just message box

have created a QMessageBox that appears when I press a 'Start' button on my application.
When either button is pressed (Ok or Cancel) - I want the message box to close - but the application to remain open.
Unfortunately, when I hit Ok or Cancel the whole application closes. Any tips?
J
Here's my code:
Main.cpp:
#include "openingdialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
Opening Dialog:
patientsetup::patientsetup(QWidget *parent) :
QDialog(parent),
ui(new Ui::patientsetup)
{
ui->setupUi(this);
connect(ui->okButton, SIGNAL(clicked()), this, SLOT(confirmButtonClicked()));
connect(ui->ACSMode, SIGNAL(clicked()), this, SLOT(ACSButtonClicked()));
connect(ui->PromptMode, SIGNAL(clicked()), this, SLOT(PMPSAIButtonClicked()));
connect(ui->FullMode, SIGNAL(clicked()), this, SLOT(PMPSFullbuttonClicked()));
}
void patientsetup::PMPSAIButtonClicked()
{
direct = new pmps_f(this);
direct->setData(patient, ui->Weight->value(), ui->Height->value(), lbmvalue, bsavalue, gender);
direct->show();
}
pmps_f MainWindow
pmps_f::pmps_f(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::pmps_f)
{
ui->setupUi(this);
connect(ui->startbutton,SIGNAL(clicked(bool)), this, SLOT(start()));
}
void pmps_f::start()
{
QMessageBox msgBox;
msgBox.setText("Pressing continue will start the process with the process");
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int ret = msgBox.exec();
switch(ret) {
case QMessageBox::Ok:
msgBox.close();
break;
case QMessageBox::Cancel:
msgBox.close();
break;
}
}
Full code:
pmps_f::pmps_f(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::pmps_f)
{
ui->setupUi(this);
connect(ui->startbutton,SIGNAL(clicked(bool)), this, SLOT(start()));
}
pmps_f::~pmps_f()
{
delete ui;
}
//public function that pulls the Patient data from the patientsetup.ui interface
void pmps_f::setData(const QString &fileName, const double &weightValue, const double &heightValue, const double &lbmValue, const double &bsaValue, const QString &genderName)
{
ui->file->setText(fileName);
ui->weight->setText(QString::number(weightValue));
ui->height->setText(QString::number(heightValue));
ui->lbm->setText(QString::number(lbmValue));
ui->bsa->setText(QString::number(bsaValue));
ui->gender->setText(genderName);
}
//Sedation start confirmation check
void pmps_f::start()
{
QMessageBox msgBox;
msgBox.setText("Pressing continue will start the sedation process");
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int ret = msgBox.exec();
switch(ret) {
case QMessageBox::Ok:
break;
case QMessageBox::Cancel:
break;
}
}
I managed to the solve the problem using:
setQuitOnLastWindowClosed(false);
However - now the program does not quit properly when the window 'x' button is pushed...
Can anyone help?

How to run thread from push button?

main.cpp:
#include "mainwindow.h"
#include "myobject.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QThread cThread;
MyObject cObject;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
// cThread.start();
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);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// cThread.start();
}
I'm trying to start the thread on on_pushButton_clicked(). In order to do this, I would have to pass cThread to mainwindow through an argument, right? I just want someone to confirm to make sure I'm doing it right.
This seems like one way to do that. The other one would be to connect signal clicked() of button to thread's slot start(Priority) in your application which will be nicer and shorter.

Need help connecting signal from thread to slot in GUI

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 disableStartButton();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QtCore>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
void doSetup(QThread &cThread);
signals:
void disableStartButton();
public slots:
void doWork();
};
#endif // MYOBJECT_H
main.cpp:
#include "mainwindow.h"
#include "myobject.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QThread cThread;
MyObject cObject;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
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);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::disableStartButton() {
ui->pushButton->setEnabled(false);
}
myobject.h:
#include "myobject.h"
#include <QDebug>
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::doSetup(QThread &cThread)
{
connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start())); // (1)
connect(this, SIGNAL(disableStartButton()), ui, SLOT(disableStartButton())); // (2)
}
void MyObject::doWork()
{
emit disableStartButton();
qDebug() << "1";
}
I'm trying to do two things.
(1): As soon pushButton is clicked, I want cThread to start.
(2): As soon as cThread starts, it does: emit disableStartButton();. I want to connect disableStartButton() to disableStartButton() in mainwindow.cpp.
For (1), I get this error:
myobject.cpp:12: error: C2065: 'ui' : undeclared identifier
Of course, there ui is undefined. You try to connect ui->pushButton
connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start())); // (1)
in file myobject.cpp, when your ui declared only in mainwindow.cpp
You have to connect pushbutton to your thread within mainwindow.cpp file, hope that helps
By the way, you should create your objects NOT in main.cpp but, in your case, in mainwindow.cpp, move lines
QThread cThread;
MyObject cObject;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
to file mainwindow.cpp in constructor, for example
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
right after ui->setupUi(this);

QSystemTrayIcon, open other dialog than mainwindow closes the application

As the title says, if I make a systemtray icon which has an option to open an other dialog (e.g. preferences) through there, when I close this other dialog, the whole application closes when I call
this>close(); from withing that preferences dialog.
Take this example code:
main.cpp:
#include <QtGui/QApplication>
#include "mainwindow.h"
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);
trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(QIcon(":/icons/error.png"));
//replace 'error' with 'video' and recompile. The indicator isn't shown!
trayIcon->setToolTip("Test");
QMenu *changer_menu = new QMenu;
Show_action = new QAction(tr("S&how"),this);
Show_action->setIconVisibleInMenu(true);
connect(Show_action, SIGNAL(triggered()), this, SLOT(show_me()));
changer_menu->addAction(Show_action);
changer_menu->addSeparator();
Preferences_action = new QAction(tr("Preferences"), this);
Preferences_action->setIconVisibleInMenu(true);
connect(Preferences_action, SIGNAL(triggered()), this, SLOT(showpref()));
changer_menu->addAction(Preferences_action);
Quit_action = new QAction(tr("&Quit"), this);
Quit_action->setIconVisibleInMenu(true);
connect(Quit_action, SIGNAL(triggered()), this, SLOT(quit_me()));
changer_menu->addAction(Quit_action);
trayIcon->setContextMenu(changer_menu);
}
void MainWindow::showpref(){
pref=new Preferences(this);
pref->exec();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
trayIcon->show();
this->hide();
}
void MainWindow::show_me(){
this->show();
}
void MainWindow::quit_me(){
this->close();
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include "preferences.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void show_me();
void quit_me();
void showpref();
private:
Ui::MainWindow *ui;
QSystemTrayIcon *trayIcon;
QAction *Show_action;
QAction *Preferences_action;
QAction *Quit_action;
Preferences *pref;
};
#endif // MAINWINDOW_H
preferences.cpp:
#include "preferences.h"
#include "ui_preferences.h"
Preferences::Preferences(QWidget *parent) :
QDialog(parent),
ui(new Ui::Preferences)
{
ui->setupUi(this);
}
Preferences::~Preferences()
{
delete ui;
}
void Preferences::on_pushButton_clicked()
{
/HERE THE WHOLE PROGRAM CLOSES. I WANT ONLY THE PREFERENCES DIALOG TO CLOSE, THE INDICATOR TO STAY
close();
}
preferences.h:
#ifndef PREFERENCES_H
#define PREFERENCES_H
#include <QDialog>
namespace Ui {
class Preferences;
}
class Preferences : public QDialog
{
Q_OBJECT
public:
explicit Preferences(QWidget *parent = 0);
~Preferences();
private slots:
void on_pushButton_clicked();
private:
Ui::Preferences *ui;
};
#endif // PREFERENCES_H
icons.qrc:
error.png
file error.png here:
http://i.imgur.com/beSvX.png
Keep all of the above files to the same dir and compile as:
qmake -project
qmake *.pro
qmake
make
Thanks for any help!
Make a little test, open main window, don't close it. Open preference window and close it. Your application shouldn't quit in this way. Now close the main window and application will quit. This happens because of QApplication property "quitOnLastWindowClosed" which is by default set to true. You should call
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
MainWindow w;
w.show();
return a.exec();
}
Also note that you leak memory from MainWindow while creating new instance of preferences everytime you want to show preferences. You could do something like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
pref(NULL)
{
// snap, your code goes here
}
void MainWindow::showpref(){
if( ! pref )
pref=new Preferences(this);
pref->exec();
}

Resources