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

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.

Related

QML on Windows: use platform menu in dark mode, or get qt menu to jump to underlines?

Using both Qt 6.3.0 and 6.4.1, I'm trying to use a menu bar on Windows that (a) renders in dark mode and (b) lets the user jump to a menu item by typing its underlined character, just like a normal Windows app does.
If I use qt.labs platform menus, I can't find a way to make (a) happen, but (b) happens by default.
If I use qt's own menus, (a) happens naturally, but (b) does not.
I set up dark mode in main.cpp as follows (based on this post, among others):
#ifdef Q_OS_WIN
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",QSettings::NativeFormat);
if(settings.value("AppsUseLightTheme")==0){
app.setStyle(QStyleFactory::create("Fusion"));
QPalette darkPalette;
QColor darkColor = QColor(64,64,64); // QColor(45,45,45);
QColor disabledColor = QColor(127,127,127);
darkPalette.setColor(QPalette::Window, darkColor);
darkPalette.setColor(QPalette::WindowText, Qt::white);
...
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor);
app.setPalette(darkPalette);
app.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
#endif
My QML code is this, for platform menus:
import Qt.labs.platform as Platform
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Platform.MenuBar {
id: menuBar
Platform.Menu {
id: fileMenu
title: qsTr("&File")
Platform.MenuItem {
id: openMenuItem;
text: qsTr("&Open...")
onTriggered: fileOpenAction.trigger();
} // open
}
}
...
Or this, for native menus:
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
menuBar: MenuBar {
id: menuBar
Menu {
id: fileMenu
title: qsTr("&File")
MenuItem {
id: openMenuItem;
text: qsTr("&Open...")
onTriggered: fileOpenAction.trigger();
} // open
}
}
...
In both cases, the "Open..." item displays with an underlined O.
With the platform menus, the menu bar and menus are resolutely black on white, even as the rest of the window goes dark (explicit changes to the parent's palette aren't seen either, and the platform menu elements don't have a palette member that can be modified directly). I can type Alt+F to display the menu, and O to select the Open item. Is there a way to make the Windows-native platform menu respect dark mode?
With qt menus, the menu turns dark in dark mode, and I can type Alt+F to display the menu, but typing O does nothing. Is there a way to make the qt menus select a menu item when its underlined character is typed?
You can change the color of your controls by modifying the palette. The modification of the palette is hierarchical. i.e. you can define the palette by setting it in the parent control and the children will inherit, or, you can define the palette in the child control.
Here's a working example:
import QtQuick
import QtQuick.Controls
Page {
background: Rectangle { color: "#444" }
palette.buttonText: "lightgreen" // menu text
palette.button: "black" // menu background
palette.mid: "grey" // menu highlighted background
palette.windowText: "lightgreen" // popup menu text
palette.window: "black" // popup menu background
palette.light: "grey" // popup menu highlighted background
palette.dark: "grey" // popup menu border
MenuBar {
Menu {
title: qsTr("&File")
MenuItem {
text: qsTr("&Open...")
}
MenuItem {
text: qsTr("&Quit")
}
}
Menu {
title: qsTr("&Edit")
palette.window: "#400"
MenuItem {
text: qsTr("&Copy")
}
MenuItem {
text: qsTr("&Paste")
}
}
}
}
You can Try it Online!
References:
https://doc.qt.io/qt-6/qml-qtquick-systempalette.html
https://doc.qt.io/qt-6/qml-qtquick-palette.html
"Solved" by talamaki in the comments: Pressing the letter alone is no longer that way it's done; the proper way is to press Alt+letter, and that works with qt menus — which obey dark mode. Thanks, talamaki!

How to handle system Dark mode in QML

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

How to highlight image on mouse hoover QML

I'm new to QML and I am trying to highlight an image on mouse hoover. I have a row of movie images, like this:
Here is my code for image number 4 (tarzan):
Rectangle{
id:rect4
width: parent.width/5-row.spacing/5
height:parent.height
color:'transparent'
Image{
id: tarzan
fillMode: Image.PreserveAspectFit
anchors.fill: parent
source:'qrc:tarzan.jpg'
MouseArea{
id:area
width:parent.width
height: parent.height
hoverEnabled: true
anchors.fill:parent
onClicked:tarzan.forceActiveFocus()
}
I tried different ways, but nothing happens. Any ideas? Help would be appreciated.
There are 2 ways to do this if you are using the qt quick version 2.15
import QtQuick 2.15
you can use the HoverHandler object something like this
Image{
id: tarzan
fillMode: Image.PreserveAspectFit
anchors.fill: parent
source:'qrc:tarzan.jpg'
HoverHandler{
onHoveredChanged: {
if(hovered){
tarzan.scale = 1.2
}
else{
tarzan.scale = 1
}
}
}
if you are using qtquick anything below 2.15 then your mousearea object should look something like this
Then it would be something like this the mouse area code
MouseArea{
id:area
width:parent.width
height: parent.height
hoverEnabled: true
anchors.fill:parent
onContainsMouseChanged: {
if(containsMouse){
tarzan.scale = 1.2
}
else{
tarzan.scale = 1
}
}
onClicked:tarzan.forceActiveFocus()
}

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")
}
}

Image atlas in QML

I have an image like this one:
http://www.imagemagick.org/Usage/basics/result.gif
(it contains two rows of individual data: three square images in the upper row, and below another square and two 'empty' squares)
I want to use it inside a repeater, so that I get four image buttons, each with one of the subimages.
Is there a "texture-atlas" modules in QML?
I only found http://doc.qt.io/qt-5/qml-qtquick-sprite.html and I hope there is something that is better for my use-case.
As I said in comment I would do that using QQuickImageProvider since that's the fastest and the least memory intensive way. But QML is very flexible and you can do with it whatever you want. As for your question you can do as following:
Tile.qml
import QtQuick 2.9
Item {
id: container
property alias source: img.source
property int cellWidth: 1
property int cellHeight: 1
property int slideIndex: 0
clip: true
Image {
id: img
property int cols: img.paintedWidth / container.cellWidth
property int rows: img.paintedHeight / container.cellHeight
x: -container.cellWidth * Math.floor(container.slideIndex % cols)
y: -container.cellHeight * Math.floor(container.slideIndex / cols)
}
}
and usage:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: window
title: "Test"
visible: true
width: 600
height: 400
Row {
spacing: 10
anchors.centerIn: parent
Repeater {
model: 4
Tile {
width: 32
height: 32
cellWidth: 32
cellHeight: 32
slideIndex: index
source: "http://www.imagemagick.org/Usage/basics/result.gif"
}
}
}
}
The idea is to wrap the entire image into a container and clip it appropriately. Here I use index-based access to a slide, you can do that as you want.

Resources