SpinBoxStyle unable to access button state - qt

SpinBoxStyle from QtQuick.Controls.Styles allows you to change the appearance of a SpinBox, and a part of that is the ability to redesign the up/down arrow buttons. However neither SpinBox nor the style gives you the ability to query the up/down arrow button state, so you can't check if it is pressed or hovered over.
This seems like too much of an oversight, so what part of the API docs have I missed?
I've tried adding a MouseArea to the control delegate itself, but some reason it never receives any events - the controls still work though which suggests that they are 'stealing' the events first.
SpinBox {
style: SpinBoxStyle {
incrementControl: Rectangle {
implicitHeight: 10
implicitWidth: 10
color: "blue"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: console.log( "Hello" ) // Never printed
}
}
}
}

Apparently you're supposed to use the styleData properties to detect hovered and pressed states, but they aren't documented. Please create a bug report for that.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
SpinBox {
style: SpinBoxStyle {
incrementControl: Rectangle {
implicitHeight: 10
implicitWidth: 10
color: styleData.upHovered && !styleData.upPressed
? Qt.lighter("blue") : (styleData.upPressed ? Qt.darker("blue") : "blue")
}
}
}
I'm not sure why the style was implemented this way, but if you look further into the source code, you can see that there are always MouseAreas for the up and down controls. This is very confusing to me; if you're not supposed to provide an interactive control because there will always be MouseAreas shadowing them, why call it incrementControl and decrementControl? Names like increment and decrement might suffice, given that they're not able to receive almost any interaction (clicking works at least, for some reason). If you find this a bit confusing, you may also want to file a separate bug report for the API.
git log --follow -p shows that this code hasn't changed much since the introduction of styles, so I'd say the current implementation (and API) is just outdated, and hopefully there are opportunities for improving this in the future.

Related

How to change qml's SystemPalette globally in linux

I'm using systemPalette (Qt5.15) in several qml-based applications in Linux, I need one of these applications to change systemPalette of qml system-wide (globally) so that other applications can detect this change at runtime.
what I need is similar to what happens in KDE, for example, I have the following qml code:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
SystemPalette {
id: palette
colorGroup: SystemPalette.Active
}
Rectangle{
anchors.centerIn: parent
width: 200
height: width
color: palette.base
}
}
when I run the above code in my KDE plasma, if I change the system's theme from breeze to breeze-dark, the rectangle's color will change at runtime, I can even select a custom color in
Appearance->globalTheme->colors.
In my case, regardless of Linux's distro, my application needs to change systemPalette globally and set its custom values for colors, how can I do that? where does qt read those color values from? (for systemPallete)
Thanks.
P.S: I can create my own style/plugin for qt and set different colors in my custom style, but still I have no idea how to change OS style globally so that all applications can detect this at runtime.

Custom checkbox shows original checkbox in QML and QtQuick

I'm using the custom checkbox that was used as an example in the QT Documentation posted with QtQuick 2.15 with Qt 6.2.1:
CheckBox {
id: control
text: qsTr("CheckBox")
checked: true
indicator: Rectangle {
implicitWidth: 26
implicitHeight: 26
x: control.leftPadding
y: parent.height / 2 - height / 2
radius: 3
border.color: control.down ? "#17a81a" : "#21be2b"
Rectangle {
width: 14
height: 14
x: 6
y: 6
radius: 2
color: control.down ? "#17a81a" : "#21be2b"
visible: control.checked
}
}
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.down ? "#17a81a" : "#21be2b"
verticalAlignment: Text.AlignVCenter
leftPadding: control.indicator.width + control.spacing
}
}
However, this example does not work. This is what I am seeing:
Checked
Checked and Hovered
Unchecked and Hovered
None
I am wondering if there is any fix to this. I have seen others with the same problem and no solution
This is the same issue as QTBUG-95589: native styles shouldn't be customised. The Customization Reference says:
Note: The macOS and Windows styles are not suitable for customizing. It is instead recommended to always base a customized control on top of a single style that is available on all platforms, e.g Basic Style, Fusion Style, Imagine Style, Material Style, Universal Style. By doing so, you are guaranteed that it will always look the same, regardless of which style the application is run with. For example:
There are two solutions:
Use a different style. I've linked to the run-time style selection documentation because it's the easiest and most common way of selecting a style, but you can also use compile-time style selection if your application only uses one style.
Style the control completely from scratch. Any time you use a type from QtQuick.Templates, no styling is applied, so you don't need to worry about which style is in use.
In Qt 6, the native styles were added, and at the same time a change was made to make the default style (i.e. the style that is used if none is specified) a platform-specific one. So if you don't specify a style on e.g. Windows, you'll get the native Windows style. Unfortunately this causes issues when customising controls, because the native styles are not designed to be customised.
Eventually the goal is to have Qt Creator warn the user when it detects that they are customising a native style.

How do I make QML Designer display button icons?

I made a new QML project which auto-generated a main.cpp. I added an icon to the qml.qrc which now looks like this:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>bookmark.png</file>
</qresource>
</RCC>
I then add a button and set the icon. The QML Designer doesn't seem to have a field for that, so I have to do it via code. Also I don't want any text on the button:
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Scroll")
Button {
id: button
x: 301
y: 159
icon.source: "qrc:/bookmark.png"
}
}
I compile and run to end up with this window which is what I wanted:
However, the QML Designer shows me this:
As you can see the icon is missing. When designing a more complicated GUI that is heavy on icon-only buttons you end up with a bunch of empty squares that make it very difficult to see what you are doing. In my desperation I tried to set the icon as the background image:
Button {
id: button
x: 301
y: 159
icon.source: "qrc:/bookmark.png"
background: Image {
id: name
source: "qrc:/bookmark.png"
}
}
When I run this I get a button with both the icon and the background image overlapping which makes sense. When I look at it in the QML Designer it stil shows me an empty button.
I can add images just fine, drag+drop of the bookmark.png asset causes an Image element (also loading qrc:/bookmark.png) to be added that is visible in both the application and QML Designer, so QML Designer is generally capable of looking into resource files and displaying images.
I'm using Qt Creator/QML Designer plugin 4.14.2.
Is there any workaround to make QML Designer show icons?

QQuickView - resize the content without delay / lag

An image often being the easiest way to explain something, here is a little screengrab of the problem I'm having:
If you look at the right side of the window, you can see that the content is resized with a visible lag / delay. It's a problem that happens in quite a lot of applications, but I was wondering if there is a way to fix this in a Qt application using QQuickView and QML content.
Basically my application is created like this:
QQuickView view;
view.resize(400, 200);
view.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
view.setSource(...);
The QML's content is just an item with 2 rectangles to highlight the problem.
Edit: here is a simplified version of the QML file (yes, the simplified version also suffers from the same problem ;p)
import QtQuick 2.12
Item {
Rectangle {
color: "black"
anchors { fill: parent; margins: 10 }
}
}
Edit2: Running this small QML snippet through the qmlscene executable also shows the same delay / lag.
Edit3: The same problem occurs on some Linux distros but not on some others: on my Ubuntu it works fine, but on my CentOS 7 is shows the same delay / glitches as on Windows. Both Qt version were 5.12.3. On an old OSX it works fine (tested on Qt 5.9) I'm really lost now ^^
Is there any way to prevent this kind of delay ? The solution will probably be platform specific since it seems the problem comes from the fact that the native frame is resized before Qt has the possibility to get the event, and so the content gets resized with a 1 frame delay ... but I'd like to know if anyone has an idea on how to handle this ?
Any help or pointer appreciated :)
Regards,
Damien
As you mentioned in your update - content gets resized with a 1 frame delay.
And there is a quite simple hack to handle this.
Use nativeEventFilter, handle
WM_NCCALCSIZE with pMsg->wParam == TRUE and remove 1px from top or from bottom.
if( pMsg->message == WM_NCCALCSIZE and pMsg->wParam == TRUE )
{
LPNCCALCSIZE_PARAMS szr = NULL;
szr = reinterpret_cast<LPNCCALCSIZE_PARAMS>( pMsg->lParam );
if( szr->rgrc[0].top != 0 )
{
szr->rgrc[0].top -= 1;
}
}
Regards, Anton
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
There is no obvious lag after I use OpenGL.
If so, try the following codeļ¼š
if (msg == WM_NCCALCSIZE) {
*result = WVR_REDRAW;
return true;
}

Setting volume per instance in QML Audio/Video elements?

I want to fade out the volume of an audio file while fading in the sound of a video in QML.
This should be no problem with animations, but I'm hitting a wall here.
It seems like the volume property is somehow shared between all instances of all media elements in QML. See for example the following code:
Rectangle
{
id:mainScreen
focus: true
Video
{
id:video
anchors.fill: parent
source: "path/to/file.mp4";
volume:1
onVolumeChanged: console.warn("video: "+volume)
autoPlay: true
}
Audio
{
source: "path/to/file.mp3";
id:audio
volume:1
onVolumeChanged: console.warn("audio: "+volume)
autoPlay: true
}
Keys.onPressed:
{
audio.volume = Math.random(1);
}
}
When I press a key, the onVolumeChanged-Handlers of both video and audio are called.
Is there a way to control the volume of the elements independently?
Or should I file a Qt bug report? This is the OpenGL MSVC2010 build of Qt 5.2.0 in case it matters.
Kakadu, you were right. I hit this bug and the provided patch fixes it!
With that patch, everything works as-is.

Resources