calling quit() method of QApplication - qt

if i try to use quit() method directly, it is compiling perfectly,
however during runtime there comes an error saying "Object::connect: No such slot myClass::quit()."
so to avoid this, is there any way?
by using a method quitPicture()(defined as slot) the application is working fine.
is this the only solution?
myClass::myClass(QWidget *parent)
: QWidget(parent)
{
QWidget *window = new QWidget;
window->setWindowTitle(QObject::tr("Class"));
QPushButton *quitButton = new QPushButton("&Quit");
// QObject::connect(quitButton, SIGNAL(clicked()), this, SLOT(quit())); //showing run time error
QObject::connect(quitButton, SIGNAL(clicked()), this, SLOT(quitPicture())); //working perfectly
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(this);
layout->addWidget(quitButton);
window->setLayout(layout);
window->show();
}
void myClass::quitPicture()
{
std::cout << "calling quitPicture" << std::endl;
QApplication::quit();
}

The button's clicked signal can be connected directly to the application's quit slot:
QObject::connect(quitButton, SIGNAL(clicked()),
QApplication::instance(), SLOT(quit()));

This answer covers new signal/slot syntax in Qt and also additionally covers how to handle it when using a signal that uses overloads.
For signals with no overloads using QObject as an example object:
QObject obj(nullptr);
QObject::connect(&obj, &QObject::destroyed, QCoreApplication::instance(), \
&QCoreApplication::quit);
For signals with overloads using QProcess as an example object:
QProcess * process = new QProcess(QCoreApplication::instance());
QObject::connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished), \
QCoreApplication::instance(), &QCoreApplication::quit);
That crazy-looking syntax is basically this, as placeholder syntax:
static_cast< _signalReturnType_( _ObjectName::*_ )( _overloadType1_, _overloadType2_, \
…etc )>( _&ObjectName::signalName_ )
You can check out this link if you want the details on why.
Since QProcess has two overloads, this is the other overload for it:
QProcess * process = new QProcess(QCoreApplication::instance());
QObject::connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>( \
&QProcess::finished ), QCoreApplication::instance(), &QCoreApplication::quit);
If this crazy-looking stuff is spinning your head, don't sweat it. You can comment questions here, as I usually check SO daily, or at least nowadays.

void my_exit_func()
{
// in mainwindow.cpp
delete MainWindow;
}

Related

How to add a QAction to a QListWidget

I have the following code:
roslaserscandoialog.h
public:
explicit ROSLaserScanDialog(QWidget *parent = nullptr);
~ROSLaserScanDialog();
QListWidgetItem *createItemFromAction(const QAction* action);
private slots:
void on_listWidget_itemClicked(QListWidgetItem *item);
private:
Ui::ROSLaserScanDialog *ui;
QAction *mAddMsgs;
QAction *mDeleteMsgs;
roslaserscandoialog.cpp
ROSLaserScanDialog::ROSLaserScanDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ROSLaserScanDialog)
{
ui->setupUi(this);
connect(ui->listWidget,SIGNAL(on_listWidget_itemClicked(QListWidgetItem*)),this,SLOT(createItemFromAction(QListWidgetItem*)));
}
QListWidgetItem *ROSLaserScanDialog::createItemFromAction(const QAction *action)
{
Q_ASSERT( action );
QListWidgetItem *mAddMsgs = new QListWidgetItem();
mAddMsgs->setText( action->text() );
mAddMsgs->setToolTip( action->toolTip() );
mAddMsgs->setIcon( action->icon() );
// ...
return mAddMsgs;
}
void ROSLaserScanDialog::on_listWidget_itemClicked(QListWidgetItem *item)
{
mAddMsgs = new QAction(QIcon(":ros.png"), tr("Add New Message"), this);
mDeleteMsgs = new QAction(QIcon(":remove_item.png"), tr("Remove Message"), this);
}
What I have done so far:
I came across this post and also this one. Very useful as I set up my project in a very similar way, but nothing happens when I try to click on the QListWidget.
I know that in order to trigger the action I have to go to the slot called itemClicked as I did on the above code provided.
On the official documentation I was trying to apply what is advised but I don't know why nothing happens.
Please point to the right direction for solving this problem.
Look at console output, there should a warning about connect failing. If you look at your code, the reason should be pretty obvious. Consider
SLOT(createItemFromAction(QListWidgetItem*))
versus your method which isn't even a slot
QListWidgetItem *createItemFromAction(const QAction* action);
See the difference?
And then you have this slot:
void on_listWidget_itemClicked(QListWidgetItem *item);
which you are trying to use as a signal
SIGNAL(on_listWidget_itemClicked(QListWidgetItem*))
That obviously won't work.
It's a bit unclear what you want to happen when an item is clicked, but maybe you just should call createItemFromAction directly from the on_listWidget_itemClicked.
Additionally, add debug print or use breakpoint to verify that the on_listWidget_itemClicked is actually called when you click an item. If not, then you are missing connecting the relevant signal from your list view, ie. ui->setupUi(this); does not have that connect (in other words you did not do the connection in the GUI Designer).

Can't write to Qt5 textEdit box with ui->control->setText(message)

I am trying to put the data passed to a mainwindow.cpp function on the screen with the typical ui->control->setText(message) without success. The same line works if it is in a timer loop or a button function but not from display_that_data function
"MainWindow::display_that_data()" is called from myudp.cpp with the following lines
MainWindow show_tlm;
show_tlm.display_that_data(data_source, buf_copy);
mainwindow.cpp (updated to include emitting a signal for a SIGNAL/SLOT connection)
The SIGNAL/SLOT connection is set up in the constructor with the following line
connect (this, SIGNAL (showdata_signal()), this, SLOT(showdata_slot()));
void MainWindow::display_that_data(QByteArray data_source, QByteArray tlmBuf){
QString msg ;
msg = " in display_that_data";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
//generate a signal which will trigger showdata_slot
emit showdata_signal();
msg = " in display_that_data after emit showdata_signal()";
qDebug() << msg ;
}
void MainWindow::showdata_slot() {
QString msg = "showdata_slot called";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
}
Runtime debug messages show that code is making it to the showdata_slot but it is still not writing to the ui->tlm_vals
" in display_that_data"
"showdata_slot called"
" in display_that_data after emit showdata_signal()"
but.... neither one of the ui->tlm_vals->setText(msg) lines are putting text on the ui
"MainWindow::realtimeDataSlot()" is called by at timer timout signal as follows:
void MainWindow::setupRealtimeDataDemo(QCustomPlot *customPlot) {
// setup a timer that repeatedly calls MainWindow::realtimeDataSlot
connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
dataTimer.start(1000);
}
void MainWindow::realtimeDataSlot(){
QString temp = QString("%1").arg(epochTime, 10, 10, QChar('0'));
ui->tlm_vals->setText(temp);
}
And this works perfectly (of course I have to disable it to see if showdata_slot is writing to the ui)
I thought the problem was a needed SIGNAL and SLOT connection to trigger the write to the ui but generating a SIGNAL/SLOT connection (which debug shows as working) still does not write to the ui from the slot function.
For completeness mainwindow.h contains the following
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setupRealtimeDataDemo(QCustomPlot *customPlot);
void display_that_data (QByteArray data_source, QByteArray tlmBuf);
private slots:
void realtimeDataSlot();
void showdata_slot();
private:
Ui::MainWindow *ui;
QTimer dataTimer;
What am I missing/doing wrong?
Somewhere deeply embedded in Qt there is a difference between gui mouse click generated event and code generated event and this somehow caues Qt behavior to vary with the same lines of code. I will repost a more more "root level" question on this topic.

Display not updating on the QTimer?

Trying to display text based on when the QTimer fires off...
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_label1 = new QLabel("My Label not working", this);
QTimer* timerDisplay = new QTimer(this);
connect(timerDisplay, SIGNAL(Started()), this, SLOT(updateDisplay(this)));
timerDisplay->start(10);
}
void updateDisplay(MainWindow* m_this)
{
QString out;
out = "hello";
m_this->m_label1->setText("asdf");
}
connect(timerDisplay, SIGNAL(Started()), this, SLOT(updateDisplay(this)));
This statement is failing. And you're ignoring the message that Qt is printing on your console.
The problem is, you can't pass variables in connect statements like that. And what for, by the way? You can use this in the updateDisplay method without the need of passing it in explicitely!

Qt QNetworkRequest hang, but I believe I'm in an event loop

I'm running Qt 4.8.1
I'm trying to use QNetworkRequest to send a request and I'm getting a 'QEventLoop: Cannot be used without QApplication' error. I believe I'm running within an event loop.
void WebLoader::load()
{
QNetworkRequest request;
request.setUrl(QUrl("http://www.bbc.co.uk/"));
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(checkForUpdateFinished(QNetworkReply*)));
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(checkForUpdateSlot()));
}
The manager->get(reply) call never returns.
This function is being called when a menu item is clicked upon. There is QWidget::event(QEvent) in its stack trace. The application is definitely running with the rest of a complex UI working.
as variations I've tried:
using new QNetworkAccessManager(mainWindow) - mainWindow inherits from QMainWindow
using new QNetworkAccessManager(application) - application inherits from QApplication
calling load() from a customEvent
calling load() from a timer callback
[edit]
I'm now constructing the QNetworkAccessManager in the MainWindow constructor:
MainWindow::MainWindow() : queryAnalyser(NULL)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(managerFinished(QNetworkReply*)));
managerFinished is not being called.
I'm getting the debug IO:
'QObject: Cannot create children for a parent that is in a different thread.
(Parent is MainWindow(0x28fcd0), parent's thread is QThread(0x4862828), current thread is QThread(0x7d90b70)'
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
WXApplication *a = WXApplication::getApp();
MainWindow mainWin;
mainWin.show();
mainWin.checkArgs();
return app.exec();
}
Ensure that your QNetworkAccessManager is not destroyed at the end of the method which sens the request. If it is destroyed, your request is lost since the destroyed QNetworkAccessManager will not be able to send the finished() signal to the connected slot.
This is exactly what happened in the WebLoader::load(); method. The manager variable only exists during the method execution and the method will end before you will receive the reply.
What you can do is putting the QNetworkAccessManager in a global variable and use this global variable every time you need it :
Afile.hpp :
//...
#include <QNetworkAccessManager>
extern QNetworkAccessManager QNAM;
//...
Afile.cpp :
//...
#include "afile.hpp"
QNetworkAccessManager QNAM = QNetworkAccessManager();
//...
In your code (WebLoader::load(); for example) :
//...
#include "afile.hpp"
//...
QNetworkAccessManager * manager = &QNAM;
//...
In requests, set an originating object to "tag" requests and to ensure that the right methods will treat the right replies :
void WebLoader::load()
{
QNetworkRequest request;
request.setUrl(QUrl("http://www.bbc.co.uk/"));
request.setOriginatingObject(this);
QNetworkAccessManager * manager = &QNAM;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkForUpdateFinished(QNetworkReply*)));
manager->get(request);
}
void WebLoader::checkForUpdateFinished(QNetworkReply* reply)
{
if (reply == 0 || reply->request().originatingObject() != this)
{
return;
}
disconnect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkForUpdateFinished(QNetworkReply*)));
// Reply treatment
reply->deleteLater();
// ...
}
In your MainWindow constructor, forget the this if it is not necessary or use the QNAM global variable.

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)

Resources