How to handle system Dark mode in QML - macos

I'm using QML + Python to create a multi-platform application. Facing a challenge with handling System Dark Mode (not sure if it applies to Windows, but I'm currently using a Mac).
For now I do set Dark / Light mode manually, using property. Is there any way I can detect user's mode and set this value to my property? Or are there any other possible solutions?
import QtCore
import QtQuick
import QtQuick.Controls
import QtQuick.Dialogs
ApplicationWindow {
width: 640
height: 480
visible: true
property bool darkMode: false
Text {
id: textField
color: {
switch (darkMode) {
case true:
"white";
break;
case false:
"black";
break;
}
}
}
}

Related

How to turn window background black on showing modal view in nativescript

As shown in the image 1 below, when the modal view on ios 13 shows up, the default background is black. But on nativescript, the default background is white as shown in the image 2. How to achieve the image 1 kind of background (black) using nativescript core? I tried changing the color of status bar but that actually changes the color of the top page portion that's partially visible in the images. I tried to define background-color on Frame css, but didn't work. Any suggestions? Thanks in advance.
Image 1:
Image 2:
The modal view options:
const option: ShowModalOptions = {
context: { selectedAccount: account },
closeCallback: (a, b, c, action) => {
//some code
},
fullscreen: false
};
mainView.showModal("./modal-add-page", option);
You have to set the background color of window on iOS.
Update: Nativescript 7
import * as app form "#nativescript/core/application";
import { Color } from "#nativescript/core/color";
import { isIOS } from '#nativescript/core';
if (isIOS) {
if (app.hasLaunched) {
app.ios.window.backgroundColor = new Color("black").ios;
} else {
app.on("launch", _ => app.ios.window.backgroundColor = new Color("black").ios)
}
}
Older versions:
import * as app form "tns-core-modules/application";
import { Color } from "tns-core-modules/color";
// You must run it once application is initiated
app.ios.window.backgroundColor = new Color("black").ios;

QML Keys.onReleased fire when pressing key

Env:
Qt 5.13 + Mingw32 + Windows 10 64bit
or
Qt 5.11 + Mingw32 + Windows 10 64bit
Demo code:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
id: name
anchors.fill: parent
focus: true
Keys.onReleased: console.log("onReleased")
}
}
Problem: QML Keys.onReleased fire when pressing key(Any Key)
From running your example I assume your problem occurs after holding the Key.
To prevent that you can simply check the isAutoRepeat attribute when you catch the KeyEvent:
Keys.onReleased: if (!event.isAutoRepeat) console.log("onReleased")
You can check isAutoRepeat from event
Item {
id: name
anchors.fill: parent
focus: true
Keys.onReleased: {
if (!event.isAutoRepeat)
console.log("released")
else
console.log("repeated like in a text field")
}
}

Qml Qt Quick Control 2: Font size difference between Text and ComboBox

Let's look at this very simple sample application, built with QT 5.9 on a Windows 10:
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.left: parent.left
anchors.leftMargin: 20
anchors.right: parent.right
anchors.rightMargin: 20
Text {
id: text
text: "This is a sample Text"
}
ComboBox {
model: [
"A",
"B",
"C"
]
}
Text {
text: "Another Text"
}
TextField {
anchors.left: parent.left
anchors.right: parent.right
text: "User Input"
}
}
}
If I run it without any further modifications from the QT Creator, I get a very weird relationship between the Font-Size of the Text and the ComboBox and TextField blocks. It looks like this:
The text is too small, and the ComboBoxes (and their Fonts) are HUGE.
If I change the main function to set the default font size explicitely to the system font size using this code (It's the same when I hardcode the setPointSizeF to 12, which is the supposed standard size on windows):
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
auto font = app.font();
QFontInfo fi(font.defaultFamily());
font.setPointSizeF(fi.pointSizeF());
app.setFont(font);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
It looks like this:
Now the "Relative Dimensions" are more balanced, but overall everything is just "too big". Additionally, if I'm opening the ComboBox, I get again very small text:
Did I miss to set some default here? How can I achieve a more balanced look that fit's better into the Operating Systems' native font sizes?
The combobox delegates use a different font to the application default.
Delegate font can be changed to match the rest of the application as follows:
ComboBox {
id: control
delegate: ItemDelegate {
width: control.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
font.family: control.font.family
font.pointSize: control.font.pointSize
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
}
}
Leave the font sizes as defaults and instead set the widths of your items. You could explicitly set the width of the ComboBox and TextField, or if you want to use the ColumnLayout to have consistent sizing of all the items, see example below,
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.left: parent.left
anchors.leftMargin: 20
width: text.width
Text {
id: text
text: "This is a sample Text"
}
ComboBox {
Layout.fillWidth: true
model: [
"A",
"B",
"C"
]
}
Text {
text: "Another Text"
}
TextField {
Layout.fillWidth: true
text: "User Input"
}
}
}
You can simply try setting: font.pointSize: 12 in both the combobox and text fields. This works for me on Qt 5.9 in Windows 10. I am still trying to figure how to change the font size inside the combobox drop down; will expand this answer when I know.

PyQt5 - Update an Image in QML

I have been looking for a way to update images on my QML UI from my PyQt code. The closest answer I could find was from Grecko Update ImageView in QML
// Code from Stackoverflow Link
// MyImage.qml
Image {
cache: false
function reload() {
var tmpSource = source;
source = "";
source = tmpSource;
}
}
I would like to apply that solution (or any solution) to my project. Below is some sample code that is similar to my implementation.
#test.py
import sys
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
from PyQt5.QtQml import QQmlApplicationEngine
if __name__ == '__main__':
myApp = QApplication(sys.argv)
engine = QQmlApplicationEngine()
context = engine.rootContext()
context.setContextProperty("main", engine)
engine.load('main.qml')
win = engine.rootObjects()[0]
image = win.findChild(QObject, "myimage")
#What do with the image here?
win.show()
sys.exit(myApp.exec_())
Here is the QML code.
//test.qml
Image {
id: image1
objectName: "myimage"
x: 384
y: 403
width: 100
height: 100
source: ""
}
I am still fairly new to PyQT5 and QML so if someone has a basic example that shows how I can implement this or can edit my basic example, it would be greatly appreciated.
Thank you :)
If you want to reload all images via your MyImage type, then one option is to use the setContextProperty() mechanism to expose an Python object with a signal and use that signal in MyImage.qml to trigger the reload() function.
In Python:
reloader = ObjectWithAReloadSignal()
context.setContextProperty("_reloader", reloader);
in MyImage.qml
Image {
id: image
void reload() { ... }
Connections {
target: _reloader
onReloadImages: image.reload()
}
}
The assumption here is that the ObjectWithAReloadSignal has a signal called reloadImages() which ti emits when QML should trigger the reload.

Use MenuBar component in a QQuickView on Windows

I am building a QML application that must work on Windows and Mac OS X. I want to manage the menus in QML so I started using the MenuBar component in my application. I am using a QQuickView in C++ to display my QML elements. My menus appear properly on Mac OS X but I get nothing displayed on Windows and no errors in the logs.
The documentation speaks about this component being linked to ApplicationWindow but as it was working fine on Mac OS I was hoping it would work the same anywhere.
Is there a way to fix this on Windows ?
It seems that QQuickView is not able to contain ApplicationWindow as a root object.
Have you tried to use QQmlApplicationEngine instead of QQuickView?
#include <QtGui/QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine("qml/untitled/main.qml");
QObject* root = engine.rootObjects().at(0);
static_cast<QWindow*>(root)->show();
return app.exec();
}
I faced with the same issue on Windows, and it helped me.
I had a look at the way this is done in the QML ApplicationWindow component and found a way to display my menu on Windows. The idea/hack is to use the property __contentItem of the MenuBar component and attach it to the root element. I also do this only if the menu is not native so that it works as it did before on Mac OS X.
TopMenu.qml
import QtQuick 2.1
import QtQuick.Controls 1.0
MenuBar {
Menu {
title: "Window"
MenuItem {
text: "SubMenu3"
shortcut: "Ctrl+s"
}
MenuItem {
text: "SubMenu2"
shortcut: "Ctrl+p"
}
MenuItem {
text: "Preferences"
shortcut: "Ctrl+,"
}
}
}
RootElement.qml
import QtQuick 2.1
Rectangle {
id: rootWindow
width: 400
height: 400
Item {
id: menuWrapper
anchors.fill: parent
TopMenu {
id: myTopMenu
}
states: State {
name: "hasMenuBar"
when: myTopMenu && !myTopMenu.__isNative
ParentChange {
target: myTopMenu.__contentItem
parent: rootWindow
}
PropertyChanges {
target: myTopMenu.__contentItem
x: 0
y: 0
width: menuWrapper.width
}
}
}
}

Resources