I have a simple QT project that looks like the following:
#include <QtWidgets/qwidget.h>
TempClass::TempClass() {
QWidget* tempWidget = new QWidget();
}
Everything compiles fine, but when I try to run the program it segfaults on the line that instantiates a new QWidget. FYI I am using QT 5.7.1.
The issue here was that I was instantiating my application as a QGuiApplication vs. a QApplication. Once I changed the code to the following, my QWidget instantiates properly:
QApplication app(argc, argv);
Related
In my application I want to create another window with QML UI from C++ code.
I know it's possible to create another window using QML Window type, but I need the same thing from C++ code.
So far I managed to load my additional qml file into QQmlComponent:
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl(QStringLiteral("qrc:/testqml.qml")));
if ( component.isReady() )
component.create();
else
qWarning() << component.errorString();
How do I display it in a separate window?
You can achieve that using a single QQmlEngine. Following your code, you could do something like this:
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl(QStringLiteral("qrc:/main.qml")));
if ( component.isReady() )
component.create();
else
qWarning() << component.errorString();
component.loadUrl(QUrl(QStringLiteral("qrc:/main2.qml")));
if ( component.isReady() )
component.create();
else
qWarning() << component.errorString();
I prefer QQmlApplicationEngine though. This class combines a QQmlEngine and QQmlComponent to provide a convenient way to load a single QML file. So you would have fewer lines of codes if you have the opportunity of using QQmlApplicationEngine.
Example:
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
engine.load(QUrl(QStringLiteral("qrc:/main2.qml")));
return app.exec();
We could also use QQuickView. QQuickView only supports loading of root objects that derive from QQuickItem so in this case our qml files couldn't start with the QML types ApplicationWindow or Window like in the examples above. So in this case, our main could be something like this:
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl("qrc:/main.qml"));
view.show();
QQuickView view2;
view2.setSource(QUrl("qrc:/main2.qml"));
view2.show();
return app.exec();
You can try to create new QQmlEngine
For anyone curious, I ended up solving the problem with slightly different approach.
My root QML document now looks like this:
import QtQuick 2.4
Item {
MyMainWindow {
visible: true
}
MyAuxiliaryWindow {
visible: true
}
}
Where MainWindow is a QML component with root element ApplicationWindow and AuxiliaryWindow is a component with root element Window.
Works just fine and you don't have to worry about loading two separate QML files.
I am trying to write an QtQuick program which works as an intelligent interface between user and a few CLI applications. I have implemented QtQuick + JavaScript application.
A QtQuick butten emits signal that is listened by C++ layer. So far everything works well.
However, in my C++ slot function I need to write to a certain Item in QtQuick application. This Item is an TextArea which serves as Log output of CLI applications. These CLI applications are run from the slot function in C++. I store their output into a variable, and I want to show output of this variable in this Log output TextArea.
I tried a lot of things, but I didn't find the right way to do that
I'd a similar problem.
This is how I solved it.
In C++ I created a class that handles the command with a QProcess (and I expose the class to QML), which attach the readyToRead signal to a C++ function in my exposed class, this function emits another signal showOutput with the output text.
With this information I just connect my new signal to a javascript function in qml:
cppExposed.showOutput.connect(jsFunction);
And in the javascript function I just append the text
function jsFunction(output) {
OutputTextArea.text += output;
}
To expose C++ properties to QML you can have a look at the documentation here: http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html
I think the easiest way for you is to create an object of your cpp class, and set as a context property in your main.cpp before load your main.qml:
Something like this:
QQmlApplicationEngine engine;
ProcessHandler procHandler;
engine.rootContext()->setContextProperty("procHandler", &procHandler);
Now you can access your object direct from QML, and you can connect signals
procHandler.showOutput.connect(jsFunction)
And in your C++ class don't forget to connect with the process ReadyToReady signal and emit your own signal with the data:
void readyToRead() {
emit showOutput(m_proc.readAllStandardOutput());
}
UPDATE:
Your property should be set before load the QML file by the engine:
AnalyzeSignal analyzeSignal;
engine.rootContext()->setContextProperty("analyzeSignal", &analyzeSignal);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
And I don't think you need that writeToLogOutput to be a property (and it has some syntax error btw), it's a signal method, right? So it's automatically available to QML as a signal, not a property.
DON'T create a new QQMLContext.
In this line what you are doing is creating a new QQMLContext
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextProperty("analyzeSignal", &analyzeSignal);
This won't work, as you are setting the property to the newly created context, not to the original root context.
My final solution of main function looks like this:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
AnalyzeSignal analyzeSignal;
QQmlContext *context = engine.rootContext();
context->setContextProperty("analyzeSignal", &analyzeSignal);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
// Registering slot onto a signal
QObject *win = engine.rootObjects()[0];
QObject *item = win->findChild<QObject*>("myButton");
QObject::connect(item, SIGNAL(doAnalyzeSignal(QString,QString,QString,QString)), &analyzeSignal, SLOT(cppSlot(QString,QString,QString,QString)));
return app.exec();
}
And this works!
I receive this error (title, below) whenever I try to run the following code:
#include <QCoreApplication>
#include <QQuickView>
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl::fromLocalFile("app.qml"));
QObject *object = (QObject*)view.rootObject();
view.show();
delete object;
return app.exec();
}
Cannot create window: no screens available
The program has unexpectedly finished.
All I can find online for that error are bug reports arising from specific conditions significantly more involved than the above.
app.qml is a file that runs fine alone, i.e. without the above C++ and in a separate project configured as a 'Qt Quick UI'. Giving it's qrc:// path, or deliberately specifying a file which does not exist has no effect.
Note the QObject* cast - this was not present in the docs, but without it:
/main.cpp:11: error: cannot initialize a variable of type 'QObject *' with an rvalue of type 'QQuickItem *'
How should this be done?
The QCoreApplication can be used with console application, not with GUI ones, i.e. you have to use a QGuiApplication object. It seems to me that you created a console application instead of a graphical one.
You can create a proper application via the Qt Quick Application, add your "app.qml" as a resource to that project and call such a file instead of the default "main.qml", provided by the project template.
If you want to quick fix your current project, just check that the .pro file is set to import GUI libraries:
QT += gui qml quick
Set your qml file as a resource:
Create a new resource file via file -> new File or Project... -> Qt -> Qt Resource File
Right click the newly created .qrc file and click add existing file to add your "app.qml" file
Finally, rewrite your main like this:
#include <QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv); // GUI APPLICATION!!!
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:///app.qml")));
view.show();
return a.exec();
}
However, going for the Qt Quick Application project would be the wiser choice.
I'm using Qt5.1 and I'm trying to create a QApplication without a display. I need to draw text with QPainter, so I need to use QApplication (or QGuiApplication), otherwise I get a segfault.
The application worked fine in Qt4.8, but fails in Qt5.1 on a headless version of Ubuntu with the error:
"QXcbConnection: Could not connect to display".
In Qt 4.8, I was able to use the following constructor with GUIenabled = false to create a QApplication that did not require a display:
QApplication::QApplication ( int & argc, char ** argv, bool GUIenabled )
In Qt5.1, the constructor for QApplication no longer has the GUIenabled flag.
I scanned the source code briefly, and there does seem to be a flag in the QApplication constructor, but it is undocumented as to what options can be used in that flag. Using "false" does not work.
How can I create a QApplication without a display? Is there an alternative method to telling QApplication GUIenabled = false? Alternatively, can I create a QCoreApplication that will not segfault when drawing text with QPainter on a QImage?
Yes, that's a Qt 3 (?) thing that is gone in Qt 5. Try running your application with the -platform offscreen command line option instead.
Note that you don't need QApplication or linking to QtWidgets to just draw upon a QImage, using QGuiApplication (and linking to QtGui) is sufficient.
If you want to create an app without GUI, you need to use QCoreApplication instead of QApplication.
Just hit this same issue. Really annoying that it at least isn't a compile error. My solution was just to use pointers and heap objects like,
QCoreApplication* app = 0;
Display* display = XOpenDisplay(NULL);
if (display)
{
XCloseDisplay(display);
app = new QApplication(argc, argv);
qobject_cast<QApplication*>(app)->setQuitOnLastWindowClosed(false);
}
else
{
app = new QCoreApplication(argc, argv);
}
return app->exec();
In the C++ GUI Programming with Qt 4 book, part of creating a dialog application, there was the following main.cpp file:
#include <QApplication>
#include <QDialog>
#include "ui_gotocelldialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Ui::GoToCellDialog ui;
QDialog *dialog = new QDialog;
ui.setupUi(dialog);
dialog->show();
return app.exec();
}
Can you just describe those lines of code?
Ui::GoToCellDialog ui;
QDialog *dialog = new QDialog;
ui.setupUi(dialog);
Thanks.
"ui_gotocelldialog.h" is a file generated automatically based on the file "gotocelldialog.ui" which contains the GUI for the dialog. Ui::GoToCellDialog::setupUi() must be called for the UI to be initialized.
Lets take a look:
Ui::GoToCellDialog ui;
This line creates an instance of GoToCellDialog. As already have been said, this class automatically generated from the gotocelldialog.ui file. The use-case is:
Open qt-designer and make the interface you want.
Save the file (in our case gotocelldialog.ui)
In your .cpp file write #include "ui_gotocelldialog.h"
Now you can use the interface you designed
PROFIT????
Next:
QDialog *dialog = new QDialog;
This line creates new instance of the QDialog class that represents simple modal window (commonly called as dialog). But your window would be empty after this line. You need to place the controls, do you? How you can do this? Lets see:
ui.setupUi(dialog);
This line uses the interface you designed in the qt-designer. It places this interface to the newly created dialog. So you can see all the controls in the window. Pretty easy as for me.
It sets up the ui described by an qt ui xml file hosted inside of a dialog window/qdialog.