I'm just starting out with Qt on a Mac and working through:
http://doc.qt.nokia.com/4.7/gettingstartedqt.html
When I run the second example which has the following code:
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
The application starts up fine and works fine. The only issue occurs when I click the "Quit" button. When I do that the crash reporter is invoked and osx says the app quit unexpectedly.
Anything obvious I'm doing wrong?
Thanks
The problem is the order of the delete if you declare variables on the stack. The best it to give your object parents so that they can destroy the children.
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWidget window;
// If window get's destroyed, it will destroy it's children...
QTextEdit textEdit(&window);
QPushButton quitButton("Quit",&window);
QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
window.setLayout(&layout);
window.show();
return app.exec();
}
PS: Did you actually try a debugger to see where it crashes? It will give you an idea ;) My suggestion is to take a working Qt example and play with it.
PS2: The order I created the widgets also prevents the crash...
Try:
QTextEdit * textEdit = new QTextEdit;
QPushButton * quitButton = new QPushButton("Quit");
Related
I have an embedded Qt application for Linux which has the following startup code:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
QQuickView AppView;
AppView.setSource(QUrl(QStringLiteral("main.qml")));
AppView.resize(480, 800);
AppView.show();
return app.exec();
}
I'd like to remove the black screen shown before AppView and to display QML animation
instead of it.
I see two possible options here but non of them is clear. Could you please advice
which one of them is more correct and also comment/answer the questions in each.
Option 1: To display QSplashScreen at the beginnning of main().
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSplashScreen *splash = new QSplashScreen();
splash->show();
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
}
The question here is what API to use to attach QML animation to QSplashScreen?
QSplashScreen inherits from QWidget, and so as I understand, no API like QQuickWidget::setSource() can be used.
Option 2: To display another QQuickView at the beginnning of main() with attached QML animation.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQuickView SplashView;
SplashView.setSource(QUrl(QStringLiteral("SplashScreen.qml")));
SplashView.resize(480, 800);
SplashView.show();
app.exec();
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
QQuickView AppView;
AppView.setSource(QUrl(QStringLiteral("main.qml")));
AppView.resize(480, 800);
AppView.show();
}
The question here is how to to close the SplashView and to display AppView on top of it?
Thanks
Option 1 is not good idea. You should not mix Qt Quick and Qt Widgets applications.
QApplication::exec() starts event loop of main gui thread and never returns until application is quit. Although I do not like your way of handling splash screen, in this case, you can use something like this.
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl("SplashScreen.qml"));
view.resize(640, 480);
view.show();
QTimer::singleShot(2000,&view,[&view](){
view.close();
view.setSource(QUrl("main.qml"));
view.show();
});
return app.exec();
I used timer to simulate "actions to display app correctly" . You should replace that part with your class, which does actions. When actions are done that class can emit a signal in receiving slot you can close current view which shows splash screen and show main app.
I am writing a Qt Console Application using Qt Creator 4.6.0 in Linux. I would like to show a QDialog but I do not want it to
show an entry on taskbar, and
steal focus from other windows.
How can I do this?
I found kind of similar question, but the solutions does not work for me as it seems that I can't use this in a console application.
Here is what I have so far which shows the dialog but it neither hides it from taskbar, nor prevents it from stealing the focus:
QDialog splash;
QVBoxLayout *laySplash = new QVBoxLayout(&splash);
splash.setAttribute(Qt::WA_ShowWithoutActivating);
splash.setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
QLabel *lblText = new QLabel;
laySplash->addWidget(lblText);
lblText->setText(QString::fromStdString("test"));
QTimer::singleShot(1000, &splash, SLOT(close()));
splash.exec();
The set parameters with exec() seems contradicting and won't prevent showing a blocking modal dialog that steals focus, if you just show() the dialog instead of exec(), other settings work. below code was tested on Debian Ubuntu 17.10, and achieves desired results
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//
QDialog splash;
QVBoxLayout *laySplash = new QVBoxLayout(&splash);
splash.setAttribute(Qt::WA_ShowWithoutActivating);
splash.setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
QLabel *lblText = new QLabel;
laySplash->addWidget(lblText);
lblText->setText(QString::fromStdString("test"));
QTimer::singleShot(5000, &splash, SLOT(close()));
splash.show();
//
return a.exec();
}
Update:
If the code should work before or without a main event loop (before a.exec() is called or even without at all calling a.exec()), you need to enter an event loop to host your dialog, this can be repeated for each additional code separately; eventually you might opt to return any int value depending on your code.
#include <QEventLoop>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//
QDialog splash;
QVBoxLayout *laySplash = new QVBoxLayout(&splash);
splash.setAttribute(Qt::WA_ShowWithoutActivating);
splash.setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
QLabel *lblText = new QLabel;
laySplash->addWidget(lblText);
lblText->setText(QString::fromStdString("test"));
QEventLoop ev;
splash.show();
QTimer::singleShot(5000, &ev, &QEventLoop::quit);
ev.exec();
//
// More code .. more event loops
//
return 0;
}
Using the TreeModel from this tutorial:
http://qt-project.org/doc/qt-4.8/itemviews-simpletreemodel.html
this version works (shows the tree):
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow mainWin;
QFile file("default.txt");
file.open(QIODevice::ReadOnly);
TreeModel model(file.readAll());
file.close();
QTreeView *treeView = new QTreeView(mainWin.splitter);
treeView->setModel(&model);
mainWin.show();
return app.exec();
}
class MainWindow: public QMainWindow {
QSplitter* splitter;
public:
MainWindow() : QMainWindow() {
splitter = new QSplitter(Qt::Horizontal, this);
splitter->setMinimumSize(1000,1000);
}
};
and this one doesn't work:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow mainWin;
mainWin.show();
return app.exec();
}
class MainWindow: public QMainWindow {
QSplitter* splitter;
public:
MainWindow() : QMainWindow() {
splitter = new QSplitter(Qt::Horizontal, this);
splitter->setMinimumSize(1000,1000);
QFile file("default.txt");
file.open(QIODevice::ReadOnly);
TreeModel model(file.readAll());
file.close();
QTreeView *treeView = new QTreeView(splitter);
treeView->setModel(&model);
}
};
What happens here? Is there some API misuse / undefined behavior?
I assume that with "doesn't work" you mean that the tree view stays empty.
You create the TreeModel model on the stack. That means it will be destroyed at the end of the block. In the first case, that's not a problem, because main() won't be exited before the application quits (i.e. app.exec() returns).
In the second case it is a problem, as the model will be destroyed right away at the end of the MainWindow constructor, i.e. right away, before the window is even visible.
You must create the model either on the heap (don't forget about memory management then - pass the main window (this) as parent) or make it a member variable.
I'm trying to create an exit button that correctly closes the GUI I have made in QT. I have tried doing this in the following way:
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
int window_width = QApplication::desktop()->width();
int window_height = QApplication::desktop()->height();
MainWindow w;
QPushButton * quit_btn = new QPushButton;
quit_btn->setParent(w.centralWidget());
quit_btn->setGeometry(window_width-50,12,32,32);
QObject::connect(quit_btn,SIGNAL(clicked()),qApp,SLOT(quit()));
w.resize(window_width,window_height);
w.show();
return a.exec();
}
Unfortunately when I push the button, the debugger gives an error:
Invalid address specified to RtlFreeHeap( 003E0000, 0028F950 )
Can anybody point me in the right direction?
Connect the button's clicked() signal to your main window's close() slot. That way things are cleaned up properly.
/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)