QSound doesn't work in if statement - qt

This doesn't work:
QString directory = "";
int main(int argc, char *argv[])
{
QString boo = getDir();
if(!boo.isEmpty()) {
directory = boo;
QSound s1(directory);
QApplication a(argc, argv);
MainWindow w;
s1.play();
// MainWindow shows fine but QSound doesnt work at all
} else {
//somethingelse
}
}
But this works fine.
QString directory = "";
int main(int argc, char *argv[])
{
QString boo = getDir();
if(!boo.isEmpty()) {
directory = boo;
QApplication a(argc, argv);
MainWindow w;
} else {
//somethingelse
}
QSound s1(directory);
s1.play();
}
The question is - What's wrong with my first example? i have no idea to be honest.
I tried many times and it still doesn't work. What should i do to fix it?

Problem is simply, your QSound instance goes out of scope and gets destructed at the end of "then" block, and sound stops playing before you hear anything.
Move the definition out of the "then" block, before it. Then just start playing it in "then" block.

Related

How to restart a qt application after crashing?

Is it possible to restart a qt application after its crashing? Just like those windows service which will restart on its own. If so, how could I do it? I have tried code like this:
#define RESTART_CODE 1000
int main(int argc, char *argv[])
{
int return_from_event_loop_code;
QPointer<QApplication> app;
QPointer<MainWindow> main_window;
do
{
if(app) delete app;
if(main_window) delete main_window;
app = new QApplication(argc, argv);
main_window = new MainWindow(app);
return_from_event_loop_code = app->exec();
}
while(return_from_event_loop_code==RESTART_CODE)
return return_from_event_loop_code;
}
But it is not working...
What should I do now?
create another qt application that runs your application.
#include <QApplication>
#include "QProcess"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QProcess aProcess;
QString exe = "Your process name with exact path";
QByteArray myOut;
while(1)
{
aProcess.start(exe);
//aProcess.waitForStarted();
//myOut = aProcess.readAllStandardOutput();
//printf("%s",myOut.constData());
aProcess.waitForFinished(-1);
//QString output(aProcess.readAllStandardOutput());
myOut = aProcess.readAllStandardOutput();
printf("%s",myOut.constData());
}
return a.exec();
}
this program will restart your app when it crashed or closed
You can use my open source library:
https://marketplace.qt.io/products/main-loop-wdt-for-qt-qml
It is a watchdog timer for the main loop and only works if the main loop freezes (double mutex lock, infinite loop, etc.), but it would not work in an application crash.

QDialog exec() can not exit process

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog dlg;
dlg.exec();
return a.exec();
}
That's all my code, but when I close the window, The process isn't exit, it seems that drop in the loop a.exec().
Generally speaking, calling any exec is a bad idea, other than QCoreApplication::exec() or QDrag::exec(). The presence of exec() and waitForXxx() methods is an enticing trap for the unwary. Those methods are "easy" to use, but that ease comes at a price of hard to track bugs. Don't use them.
You should simply show the dialog:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMessageBox msg;
msg.setText("Hello");
msg.addButton(QMessageBox::Close);
msg.show();
return a.exec();
}
If you wish to wait for the dialog to be accepted or rejected, you should use the dialog's clickedButton slot. QMessageBox has a long-standing bug that makes the accepted and rejected signals useless :(
// https://github.com/KubaO/stackoverflown/tree/master/questions/messagebox-show-25545652
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
#include <functional>
[...]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMessageBox msg;
msg.setText("Continue?");
msg.addButton(QMessageBox::Yes);
msg.addButton(QMessageBox::No);
auto onClick = [&msg]() {
auto role = msg.buttonRole(msg.clickedButton());
if (role == QMessageBox::NoRole)
QApplication::quit();
if (role == QMessageBox::YesRole) {
auto label = new QLabel("I'm running");
label->setAttribute(Qt::WA_DeleteOnClose);
label->show();
}
};
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QObject::connect(&msg, &QMessageBox::buttonClicked, onClick);
#else
QObject::connect(&msg, SIGNAL(buttonClicked(QAbstractButton*)),
new FunctorSlot{onClick, &msg}, SLOT(call()));
#endif
msg.show();
return app.exec();
}
#include "main.moc"
For Qt 4, you need the following helper:
// Qt 4 only
struct FunctorSlot : public QObject {
Q_OBJECT
public:
std::function<void()> callable;
template <typename Fun>
FunctorSlot(Fun && fun, QObject * parent = {}) :
QObject{parent}, callable{std::forward<Fun>(fun)} {}
Q_SLOT void call() {
callable();
}
};
Possible solution:
QApplication a(argc, argv);
QDialog dlg;
QTimer::singleShot( &dlg, 0, SLOT(exec()) );
return a.exec();
It will work well. First - application event loop will be started. Then dialog event loop will be executed. After closing of dialog, both dialog and application loop will be finished. Application loop will be terminated automatically (by default), when last window is closed.
But, as noted by #thuga - there are no reason to call exec(). It is enough to call show() method.

Qt Login Dialog Box before Main Window

How do I have the user first login before getting to the main window in my QT app? I'm new to QT and have looked through the documentation and have not found anything very helpful. Thank you.
I would make this in the following way. Let's assume, that my login dialog is a QDialog:
class Login : public QDialog
{
[..]
};
In my application, I create an instance of my Login dialog and if it is accepted, i.e. closed with OK button, I open my main window:
int main(int argc, char *argv[])
{
[..]
QMainWindow mw;
Login login;
if (login.exec() == QDialog::Accepted) {
mw.show();
}
[..]
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
LoginWindow l; // create login-widget
connect(&l, SIGNAL(loggedIn), &w, SLOT(show()); // connect to mainwindow show()
l.show(); // show login-window instead of
// mainwindow at start
return a.exec();
}
You might want to :
1 - exec the loop only if the dialog is accepted, otherwise you application continues to run
2 - create the mainwindow only if accepted, cause it might be a heavy interface, which takes time to initialize
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog_Login dialog;
if(dialog.exec() == QDialog::Accepted){
MainWindow w;
w.setUser(dialog.GetUser());
w.show();
return a.exec();
}
else return 0;
}
You need to create the QApplication instance in parrallel with the login dialog.

Remove application from memory

I am trying to close an application
#include <QtGui/QApplication>
#include "battle.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
battle w;
int x = 14;
if(x == 1)
{
w.show();
}
else if(x!=1)
{
qApp->exit(0);
//Remove application from memory...
}
return a.exec();
}
but if i go to windows processes,it is still there.What is the best way to remove the application from memory?.
Don't call a.exec() after you call qApp->exit(0).
What's inside battle.h? If you start a thread in the battle class, and closing the window does not stop it, then the process will remain in the task list even if you close the window.

QX11EmbedWidget and QX11EmbedContainer

Can one place an arbitrary program (firefox, openoffice, etc...) in a QX11EmbedContainer? The fllowing seems, to work
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QX11EmbedContainer container;
container.show();
QProcess * process = new QProcess(&container);
QString executable("xterm");
QStringList arguments;
arguments << "-into";
arguments << QString::number(container.winId());
process->start(executable, arguments);
int status = app.exec();
process->close();
return status;
}
but the next snippet launches a new window, not what I want
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QX11EmbedContainer container;
container.show();
QProcess * process = new QProcess(&container);
QString executable("konsole");
process->start(executable);
int status = app.exec();
process->close();
return status;
}
The first example work because xterm is able to reparent its top level widget (an X11 window). You tell it to do so with the argument -into <WinId>.
I don't know if Konsole can do that, i don't use it and the man page doesn't seem to talk about this.
But that doesn't mean it is not doable, the X Window system is very flexible and anyone can reparent another window (that's how windows managers add decorations to windows).
Take a look at man 3 XReparentWindow ;-)

Resources