Getting QSplashScreen to work in my application - qt

There is an example in the documentation providing the following code, which seems to be quite simple :
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPixmap pixmap(":/splash.png");
QSplashScreen splash(pixmap);
splash.show();
app.processEvents();
...
QMainWindow window;
window.show();
splash.finish(&window);
return app.exec();
}
Now the thing is that I am using QApplication, create an engine and open my QML files like this:
engine->load(QUrl(QLatin1String("qrc:/qml/main.qml")));
And from the documentation I cannot really understand how to go the QMainWindow way like in the example, without passing a URL of the file as an argument (there is no such function available). Do I have to write a C++ class derived from QMainWindow or something like this? Or am I missing another important point?
I am furthermore happy about any other suggestions of getting QSplashScreen to work.

Related

QApplication Within A Shared Library Event Loop Issues

I'm trying to use QWebPage in a shared library, which means I have to have QApplication in there to get a GUI context for it to run in. I've built my code up to get this in place, however as soon as I run qApp->exec() the Event Loop completely blocks and prevents anything else from executing. This is with the shared library being ran on OS X, I've yet to try any other platforms.
I've tried adding a QTimer in to trigger every 100msecs but that doesn't ever get called, I'd assume to the event loop blocking. I've added my QApplication setup code below. I'd assume I either need to run it in a thread, or I've missed something trivial but I'm completely unsure what.
web_lib.cpp
WebLib::WebLib(int argc, char *argv[])
{
QApplication a(argc, argv, false);
connect(&m_eventTimer, SIGNAL(timeout()), this, SLOT(handleEvents()));
m_eventTimer.start(100);
a.exec();
}
void WebLib::renderFile(QString file
{
...some connection code that's boring here
m_page = new QWebPage;
m_page->mainFrame()->load(file);
}
void WebLib::handleEvents()
{
qApp->processEvents()
}
web_lib.h
class WEBLIBSHARED_EXPORT WebLib: public QObject
{
Q_OBJECT
public:
WebLib();
WebLib(int argc, char *argv[]);
void renderFile(QString fileName);
private slots:
void handleEvents();
private:
QWebPage *m_page;
QTimer m_eventTimer;
};
main.cpp
int main(int argc, char *argv[])
{
WebLib *webLib = new webLib(argc, argv);
svgLib->renderFileFromName("somePath");
return 0;
}
As soon as I run qApp->exec() the event loop completely blocks and prevents anything else from executing.
That's correct. After you're done with your rendering, you should exit the event loop.
The timer is useless, since calling processEvents from a nonblocking slot like handleEvents simply forces the event loop to be re-entered for a short time, for no reason.
Your event loop has nothing to do. You need to make the render file request before calling a.exec(), not afterwards. In other words, you need to make the following changes:
In the WebLib constructor:
1. Remove the call to a.exec().
2. Dynamically allocate the QApplication instead of putting it on the stack. 3. Remove the timer, you don't need it.
In web_lib.cpp:
Add WebLib::run(), which will call a.exec().
In main.cpp:
After the call to renderFile(), call webLib->run().
The exec must be run in a tread. Alternatively, you can call QApplication::processEvents periodically.

Connect QML signal of arbitrary placed .qml-file to Qt slot

I am trying to connect QML signal to Qt slot. I have read that example and here is code
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
qDebug()<<QUrl::fromLocalFile("main.qml");
QQuickView view(QUrl::fromLocalFile("main.qml"));//I should replace that line
QObject *item = view.rootObject();
MyClass myClass;
QObject::connect(item, SIGNAL(qmlSignal(QString)),
&myClass, SLOT(cppSlot(QString)));
view.show();
return app.exec();
}
It works fine, but the problem is that main.qml should be in the folder where .exe file is. So, every time I modify main.qml I should copy it to another foder. File path to main.qml is: "C:\Qt\projects\ConnectionsQT\main.qml". I have tried to replace line by
QQuickView view(QUrl("‪C:\Qt\projects\ConnectionsQT\main.qml");
and by
QQuickView view(QUrl("‪C:\\Qt\\projects\\ConnectionsQT\\main.qml");
but in that cases the program cannot find the main.qml file. What should I do?
The good practice is making your qml file part of the app executable by putting into .qrc resource file with Qt creator or by hand:
http://qt-project.org/doc/qt-5/qtquick-deployment.html#managing-resource-files-with-the-qt-resource-system
And the you can make use of it with something like:
QQuickView view(QUrl("qrc:///res/qml/main.qml"));

Loading qm files within dynamic translation in Qt

I have an application that I want to translate the UI for Persian language. For that, I need to load qt_fa.qm and my_app_fa.qm in it. But the misfortune is, both files aren't loaded correctly. Below code always run as I expected:
QApplication app(argc, argv);
QTranslator translator;
translator.load("qt_fa"); // returns true
app.installTranslator(&translator);
translator.load("my_app_fa"); // returns true
app.installTranslator(&translator);
.
.
sometimes the qt_fa affects the application and the layout is changed to RTL and the translation of Qt used words are displayed and none of my own translations are shown.
Sometimes the my_app_fa affects the app and just my own translations are displayed.
Do have any idea about the reason?
Thanks
According to Qt Documentation with the sample code snippet you should create two objects from QTranslator
int main()
{
QApplication app(argc, argv);
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
QTranslator myappTranslator;
myappTranslator.load("myapp_" + QLocale::system().name());
app.installTranslator(&myappTranslator);
...
return app.exec();
}

Qt quick project - how to invoke cpp function in qml file?

I' ve created quick project in Qt, selected from wizard at the begin, when Qt creator is started.
Qt creator create project. There are qmlapplicationvierwer subproject and qml files in main project. I want to add new cpp source and header files (MainMenu.cpp and MainMenu.h) to project and then invoke function from these files in main.qml file.
How I can register new type in qmlapplicationviewer and invoke function from ManiMenu ?
qmlapplicationvierwer has only few function:
QApplication app(argc, argv);
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/PUTest/main.qml"));
viewer.showExpanded();
return app.exec();
and:
viewer.addImportPath(const string &path);
Better way is not create project without project wizard ?
Thanks
Normally, you use this wizard to create QML only projects.
The QmlApplication viewer is just a lightweight C++ wrapper around your QML file so a binary is generated and the QML file is loaded.
There's not much magic to do that on your own, see:
https://doc.qt.io/archives/qt-4.7/qtbinding.html
#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeContext>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
QDeclarativeContext *context = view.rootContext();
context->setContextProperty("backgroundColor",
QColor(Qt::yellow));
view.setSource(QUrl::fromLocalFile("main.qml"));
view.show();
return app.exec();
}
And with setContextProperty you can ad global QML types via cpp...
Of course you can also reuse the QmlApplicationViewer. The Mainclass QmlApplicationViewer is derived from QDeclarativeView, so you directly have access to the context in this class.
So like in the example above, it should be possible to use:
QDeclarativeContext *context = this.rootContext();
context->setContextProperty("backgroundColor", QColor(Qt::yellow));
somewhere in the QmlApplicationViewer costructor or afterwards (didn't try it for now, let me know if it doesn't work).

Do I have to delete it? [Qt]

Do I have to delete objects from the heap in the example below? And if yes, how?
#include <QApplication>
#include <QTreeView>
#include <QListView>
#include <QTableView>
#include <QSplitter>
int main(int argc, char* argv[])
{
QApplication app(argc,argv);
QTreeView* tree = new QTreeView;
QListView* list = new QListView;
QTableView* table = new QTableView;
QSplitter* splitter = new QSplitter;
splitter->addWidget(tree);
splitter->addWidget(list);
splitter->addWidget(table);
splitter->show();
// delete splitter; WHEN TRYING TO DELETE I'M GETTING INFO THAT app EXITED
// delete table; WITH CODE -1073741819
// delete list;
// delete tree;
return app.exec();
}
Thank you for any help.
Just allocate splitter on the stack. Then tree, list and table become children of splitter which takes ownership. When splitter gets deleted, all the children are deleted.
From Widgets Tutorial - Child Widgets:
The button is now a child of the window and will be deleted when the window is destroyed. Note that hiding or closing the window does not automatically destroy it. It will be destroyed when the example exits.
See also Object Trees and Object Ownership.
Gregory Pakosz pointed out the proper solution, but I wanted to reiterate with a code example and to suggest you look into C++ object scope. Greg is accurate but did not clarify that putting splitter on the stack means that once it goes out of scope (the application exits) it will be deleted.
More accurately you should set a QObject's parent. When a parent object takes ownership of an another object it deletes it's children upon calling delete on the parent object. In QSplitters case, addWidget adds to QWidget's layout and the layout takes ownership of those objects.
#include <QApplication>
#include <QTreeView>
#include <QListView>
#include <QTableView>
#include <QSplitter>
int main(int argc, char* argv[])
{
QApplication app(argc,argv);
QTreeView* tree = new QTreeView;
QListView* list = new QListView;
QTableView* table = new QTableView;
QSplitter splitter;
splitter.addWidget(tree);
splitter.addWidget(list);
splitter.addWidget(table);
splitter.show();
return app.exec();
}
So simply making 'splitter' a local variable will cause it to be deleted when it goes out of scope. In turn, it's children will also be deleted.
http://doc.qt.io/qt-5/qtwidgets-tutorials-widgets-windowlayout-example.html
http://doc.qt.io/qt-5/qsplitter.html#addWidget
Instead of managing the memory manually, you can let the compiler do it for you. At that point you may ask: why use the heap at all? You should keep things by value as much as feasible, and let the compiler do the hard work.
The objects will be destroyed in the reverse order of declaration. Thus the splitter - the implicit parent - must be declared first, so that it doesn't attempt to incorrectly delete its children. In C++, the order of declarations has a meaning!
int main(int argc, char* argv[])
{
QApplication app(argc,argv);
QSplitter splitter;
QTreeView tree;
QListView list;
QTableView table;
splitter.addWidget(&tree);
splitter.addWidget(&list);
splitter.addWidget(&table);
splitter.show();
return app.exec();
}

Resources