QML: QT Project does not run after modifying the code - qt

I'm learning the QT basic, starting the new project QT Quick APP Empty. Running for first time, the app run. Modifying the code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
Window { x: 100; y: 100; width: 100; height: 100; visible: true }
Output response:
17:34:02: Starting /home/PC/Documents/Projects/QT_APP/build-FirstAPP-Desktop_Qt_5_12_2_GCC_64bit-Release/FirstAPP ...
Nothing besides that happens. Am I forgetting anything?
Updating
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

Worked, after I Clean and build project again!

Related

I want to know the line number in editText where the cursor is

I want to know the line number in editText where the cursor is. How do I get that?
I checked the documentation, and there's no
ps:Is the textedit QML,not QTextEdit
You have to use textDocument and cursorPosition properties in c++:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickTextDocument>
#include <QTextBlock>
class Helper: public QObject{
Q_OBJECT
public:
Q_INVOKABLE int currentLineNumber(QQuickTextDocument *textDocument, int cursorPosition){
if(QTextDocument * td = textDocument->textDocument()){
QTextBlock tb = td->findBlock(cursorPosition);
return tb.blockNumber();
}
return -1;
}
};
#include "main.moc"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Helper helper;
engine.rootContext()->setContextProperty("helper", &helper);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
TextEdit{
id: textEdit
anchors.fill: parent
onCursorPositionChanged: function(){
let line = helper.currentLineNumber(textEdit.textDocument, textEdit.cursorPosition);
console.log(line);
}
}
}

Qt.createComponent() causes later "Object already has a QQmlContext" error when binding dynamically [duplicate]

I want get json file from local and send it to QML using this:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
engine.rootContext()->setContextProperty("text_json", "{\"text1\": \"Loading\"}");
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection
);
engine.load(url);
return app.exec();
}
But it say that QQmlEngine::setContextForObject(): Object already has a QQmlContext but I don't understand anything from that default file.
I don't have found anything from now.
-- Added Main.qml --
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: window
width: 640
height: 480
visible: true
title: qsTr("Stack")
property var text_json: ({"text1": "Loading"})
header: ToolBar {
contentHeight: toolButton.implicitHeight
ToolButton {
id: toolButton
icon.source: "./images/ruby.png"
font.pixelSize: Qt.application.font.pixelSize * 1.6
onClicked: {
drawer.open()
}
}
Label {
text: stackView.currentItem.title
anchors.centerIn: parent
}
}
}
Maybe a bit late, but did you try importing in your Main.qml without version number?
import QtQuick
import QtQuick.Controls

Update QML Window property flags from C++

I have a basic qml application QWindow that already defines the property flags. I would like to change/update the property flags from main.cpp so that it is not frameless. I know I can do it directly in QML but I'd like to change it dynamically without re-compiling. I have found a number of examples but none show how to do this after using QQmlApplicationEngine::load() method. I posted my code below and I am able to see the current flags decimal value 2048 or hex value 0x800. According to documentation the hex value of 0x800 refers to Qt::FramelessWindowHint which is the current setting. I have tried to modify the flags property but the window doesn't update.
// Main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: window
objectName: "window"
...
flags: Qt.FramelessWindowHint
...
}
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
QObject::connect(&engine, &QQmlApplicationEngine::quit, &app,
&QGuiApplication::quit);
const QUrl url(QStringLiteral("qrc:/Main.qml"));
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) QCoreApplication::exit(-1);
QVariant obj2 = obj->property("flags");
if (obj2.isValid()) {
Qt::WindowFlags flags = qvariant_cast<Qt::WindowFlags>(obj2);
flags &= ~Qt::FramelessWindowHint;
auto *tmp = dynamic_cast<QWindow*>(obj);
tmp->setFlags(flags);
tmp->show();
}
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
you have obj and if you want that main.qml change you can easily add property to this:
obj->setProperty("flags", Qt::FramelessWindowHint);
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl)
{
if (!obj && (url == objUrl))
{
QCoreApplication::exit(-1);
}
obj->setProperty("flags", Qt::FramelessWindowHint);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Edited :

How get the initial value from Qml Checkbox to c++?

I have qtquick frontend and c++ backend. In Qml I have a checkbox with random initial value. I have a signal emitted onCheckedChanged which is never received. I believe, it is because the component is created before connect statements are made. When user interacts, I can catch those events but I miss the initial value. I cannot make the connections sooner because the QMl engine has to first create the components so I can have a reference to them to make the signal slot connection. So how to find out the initial value? Do I have to make a timer which will emit the value few seconds after startup? Is there a better way?
here is minimum example (when the initial value is true, the slot is never triggered)
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
signal checkboxStateChanged(enabled: bool)
CheckBox{
checked: Math.random() > 0.5
text: "value"
onCheckedChanged: checkboxStateChanged(checked)
}
}
backend.h
#include <QObject>
#include <QDebug>
class Backend: public QObject{
Q_OBJECT
public:
Backend(){}
public slots:
void logChecked(bool checked){
qDebug()<<checked;
}
};
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include "backend.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
const auto root=engine.rootObjects();
QObject *window = root[0];
Backend b;
QObject::connect(window,SIGNAL(checkboxStateChanged(bool)),
&b,SLOT(logChecked(bool)));
return app.exec();
}
I am not sure about the approach you are trying but a cleaner method would be to bind the QML checked value to the c++ class. Then you can handle everything in your backend class which is a lot easier to debug and maintain. So using your example,
#include <QObject>
#include <QDebug>
class Backend: public QObject{
Q_OBJECT
// Add a Q_PROPERTY to bind in QML
Q_PROPERY(Qt::CheckState checked READ getChecked WRITE setChecked NOTIFY checkedChanged)
signals:
void checkedChanged();
public:
Backend() { m_checked = <random_value>;}
// implement the q_property methods
void setChecked(const Qt::CheckState value) {
if (m_checked != value) {
m_checked = value;
emit checkedChanged();
}
}
Qt::CheckState getChecked() const { return m_checked; }
public slots:
void logChecked(bool checked){
qDebug()<<checked;
}
private:
m_checked;
};
Then in QML:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQml 2.12 // Binding
import Backend 1.0
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
signal checkboxStateChanged(enabled: bool)
CheckBox{
id: qmlCheckBox
checked: backend.checked // C++ to QML binding
text: "value" // you can bind this too
}
// QML to C++ binding
Binding {
target: backend
property: "checked"
value: qmlCheckBox.checked
}
}
In main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QObject>
#include "backend.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// Register backend class for qml
qmlRegisterType<Backend>("Backend", 1, 0, "Backend");
engine.rootContext()->setContextProperty("backend", new Backend);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

Import Qt function to QML file?

How do you call for example QFile::exists(path) inside a QML file in Qt 5.5?
MyFile.qml
import QtQuick 2.5
// These are some various things I've tried, with the error message they
// give related to the row where I call QFile::exists()
#include <QFile> // Expected token `{'
import QtQml 2.5 // Expected token `;'
import io.qt // Expected token `;'
import io.qt.QFile // Expected token `;'
Item {
id: root
property string imageSource
Image {
id: test
source: fileOrFallback(root.imageSource)
}
function fileOrFallback (source) {
return QFile::exists(source)
? preprocessor.getFilePath(source)
: theme.example + 'placeholder.png'
}
}
I've seen some examples on how to import your custom Qt functions, but how do you call built-in Qt functions in QML?
You cannot directly import a C ++ function, in these cases the approach is to create a QObject that exposes the method through a Q_INVOKABLE:
backend.h
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
class Backend : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE bool exists(const QString &fileName);
};
#endif // BACKEND_H
backend.cpp
#include "backend.h"
#include <QFile>
bool Backend::exists(const QString &fileName){
return QFile::exists(fileName);
}
main.cpp
#include "backend.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Backend backend;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("backend", &backend);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
*.qml
// ...
function fileOrFallback (source) {
return backend.exists(source)
? preprocessor.getFilePath(source)
: theme.example + 'placeholder.png'
}
// ...

Resources