How to apply radius to ApplicationWindow in qml - qt

I had a question about how to trimming corners around the edges in ApplicationWindow, i tried to use clip, opacity and many standard methods of the qml language My Code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.13
ApplicationWindow {
id: loginPage
visible: true
opacity: 0.8
x: 732; y:245
width: 456; height: 529
color: "#3C096C"
flags: Qt.FramelessWindowHint
}
Here is the result that I want to get:

The answer is to not try to make the ApplicationWindow itself have a radius, but to make it transparent and simply draw a rounded Rectangle as the first child.
ApplicationWindow
{
id: loginPage
visible: true
x: 732; y:245
width: 456; height: 529
color: "transparent"
flags: Qt.FramelessWindowHint
Rectangle {
color: "#3C096C"
opacity: 0.8
radius: 20
anchors.fill: parent
}
}

Another alternative is to use the method setMask() of QWindow:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QWindow>
class Utils: public QObject{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void applyRadius(QWindow *window, int radius){
QRect r(QPoint(), window->geometry().size());
QRect rb(0, 0, 2 * radius, 2 * radius);
QRegion region(rb, QRegion::Ellipse);
rb.moveRight(r.right());
region += QRegion(rb, QRegion::Ellipse);
rb.moveBottom(r.bottom());
region += QRegion(rb, QRegion::Ellipse);
rb.moveLeft(r.left());
region += QRegion(rb, QRegion::Ellipse);
region += QRegion(r.adjusted(radius, 0, -radius, 0), QRegion::Rectangle);
region += QRegion(r.adjusted(0, radius, 0, -radius), QRegion::Rectangle);
window->setMask(region);
}
};
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);
Utils utils;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("Utils", &utils);
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();
}
#include "main.moc"
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.13
ApplicationWindow {
id: loginPage
visible: true
opacity: 0.8
x: 732; y:245
width: 456; height: 529
color: "#3C096C"
flags: Qt.FramelessWindowHint
Component.onCompleted: ()=> Utils.applyRadius(loginPage, 20);
}

Related

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

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();
}

How to display .png image using image provider with detail explanation

i want to send the dynamic image to qml and display on Qt gui i read online image provider is way to solve this issue but i want any sample and simple application which does this.
You should create an image provider class where you load your image, this is a simplified example.
qmlimageprovider.h
#ifndef QMLIMAGEPROVIDER_H
#define QMLIMAGEPROVIDER_H
#include <QQuickImageProvider>
class QmlImageProvider : public QQuickImageProvider
{
public:
QmlImageProvider();
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
void updateImage(QImage new_image);
private:
QImage image;
};
#endif // QMLIMAGEPROVIDER_H
qmlimageprovider.cpp
#include "qmlimageprovider.h"
QmlImageProvider::QmlImageProvider()
: QQuickImageProvider(QQuickImageProvider::Image)
{
}
QImage QmlImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
image.load("/home/ubuntu/music.jpg");
return image;
}
void QmlImageProvider::updateImage(QImage new_image)
{
image = new_image;
}
Then you should register this class to your QML engine.
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "qmlimageprovider.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImageProvider(QLatin1String("imageprovider"),
new QmlImageProvider());
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();
}
Finally you can use imageprovider in your qml page and don't forget to write image reload function because images will be cache and you need to reload in order to change them.
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Connections {
target: imageprovider
onNewFrameReceived: image.reload();
}
Item {
id: name
width: parent.width
height: parent.height
Rectangle
{
id: progressBackground
height: parent.height
width: parent.width
Text {
id: text
text: qsTr("click to show")
color: "#c400c4"
}
MouseArea {
id: progressArea
anchors.fill: progressBackground
onClicked:
{
image.source = "image://imageprovider/cover"
}
}
}
Image {
id: image
anchors.left: text.right
source: ""
cache: false
function reload() {
var oldSource = source;
source = "";
source = oldSource;
console.log("reload")
}
}
}
}
You can call imageprovider update function to change the image.

How to get the className of activeFocusControl in QML ApplicationWindow

I try
ApplicationWindow {
onActiveFocusControlChanged: {
console.log(activeFocusControl)
console.log(activeFocusControl.objectName)
}
}
ouput:
qml: QQuickTextField(0xa6ec00) //the 'activeFocusControl'
qml: //the 'activeFocusControl.objectName'
qml: QQuickButton(0xd7ccb0)
qml:
I want to
onActiveFocusControlChanged: {
if (activeFocusControl.className == "QQuickTextField") {
//do something
}
else if (activeFocusControl.className == "QQuickButton") {
//do something
}
but the "className" method does not exist
so how i can do it?
sorry, my english is pool, and thank you
There is no method to access the className from qml, so a possible solution is to create a helper from c ++ as shown below:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QObject>
class Helper : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE QString getClassName(QObject *obj) const{
return obj? obj->metaObject()->className(): "";
}
};
#include "main.moc"
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
Helper helper;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("helper", &helper);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
then it is used on the QML side:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button {
id: button
x: 270
y: 47
text: qsTr("Button")
}
TextField {
id: textField
x: 220
y: 169
text: qsTr("Text Field")
}
onActiveFocusControlChanged: {
var className = helper.getClassName(activeFocusControl)
switch(className){
case "QQuickTextField":
console.log("I am QQuickTextField")
break
case "QQuickButton":
console.log("I am QQuickButton")
break
default:
console.log("empty")
}
}
}
The complete example can be found at the following link.

QWidgetAttribute for QWindow

dose anyone know how to convert Qt::WidgetAttribute to Qt::WindowFlags???
and by convert i mean is there any WidgetAttribute like WA_NoBackground or WA_TranslucentBackground as a flag for WindowFlags....???
i've been trying to transparent my ApplicationWindow Item in QML but i couldn't.
Main.Qml
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
flags: Qt.SubWindow | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
opacity: 0.5
Image {
anchors.fill: parent
source: "blah.png" // and this picture in transparent
}
}
and know im looking for the flag that works like WA_NoBackground and WA_TranslucentBackground
Main.cpp
int main(int argc, char *argv[])
{
Application app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl("blah.qml"));
QObject *topLevel = engine.rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
window->show();
window->setColor(Qt::transparent);
return app.exec();
}

Resources