I have created a TextArea inside a flickable, and when I add lots of newlines the area scrolls as expected. However, although a scrollbar appears when I type more lines than the available height, if I try to drag the scrollbar it resets to fully colored (nothing to drag) and just generally misbehaves.
What is wrong with my scrollbar?
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id: box
width: 640
height: 180
visible: true
title: qsTr("ScrollBar Mystery")
Flickable {
id: inputWrapper
anchors.fill: parent
ScrollBar.vertical: ScrollBar {
id: scrollBar
policy: ScrollBar.AlwaysOn
anchors.left: box.right
}
Keys.onUpPressed: scrollBar.decrease()
Keys.onDownPressed: scrollBar.increase()
clip: true
flickableDirection: Flickable.VerticalFlick
function ensureVisible(r)
{
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x+r.width)
contentX = r.x+r.width-width;
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit {
id: input
anchors.fill: parent
text: ""
focus: true
wrapMode: TextEdit.Wrap
onCursorRectangleChanged: inputWrapper.ensureVisible(cursorRectangle)
} // TextEdit
} // Flickable
} // Window
you forget to set contentHeight and contentWidth
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
id: box
width: 640
height: 180
visible: true
title: qsTr("ScrollBar Mystery")
Flickable {
id: inputWrapper
anchors.fill: parent
contentHeight: input.implicitHeight
contentWidth: input.implicitWidth
ScrollBar.vertical: ScrollBar {
id: scrollBar
policy: ScrollBar.AlwaysOn
anchors.left: box.right
}
Keys.onUpPressed: scrollBar.decrease()
Keys.onDownPressed: scrollBar.increase()
clip: true
flickableDirection: Flickable.VerticalFlick
function ensureVisible(r)
{
if (contentX >= r.x)
contentX = r.x;
else if (contentX+width <= r.x+r.width)
contentX = r.x+r.width-width;
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit {
id: input
anchors.fill: parent
text: ""
focus: true
wrapMode: TextEdit.Wrap
onCursorRectangleChanged: inputWrapper.ensureVisible(cursorRectangle)
} // TextEdit
} // Flickable
} // Window
Related
Is it possible to transfer the same code logic in another page, in which these two images are taken as alias or something similar and they behave in the same pattern of "if statement" logic on the other QML file(2) when this button is pressed from the first QML file(1)?
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Studio.Components 1.0
import QtQuick.Timeline 1.0
Item {
id: root
width: 500
height: 500
property alias locking: locking
Text {
id: confirmSign
text: qsTr("")
anchors.left: parent.left
anchors.top: parent.top
font.styleName: "Bold"
anchors.leftMargin: 70
anchors.topMargin: 55
color: "white"
font.pointSize: 10
font.family: "Tahoma"
}
RoundButton {
id: locking
y: 70
width: 90
height: 90
anchors.left: password_field.right
anchors.leftMargin: 15
Image {
id: unlck
anchors.centerIn: parent
source: "Images/Unlocked.png"
visible: false
}
Image {
id: lcked
anchors.centerIn: parent
source: "Images/Locked.png"
visible: true
}
onClicked: {
passBlocker.visible = true
confirmSign.text = qsTr("The ToolBar is 'Locked' ");
confirmSign.color = "#ffffff";
lcked.visible = true
unlck.visible = false
}
}
}
You can create a new file just for the lock image and use it wherever you want.
Something like this:
File LockImage.qml
Item {
property bool locked: false
Image {
id: lcked
anchors.centerIn: parent
source: locked? "Images/Locked.png": "Images/Unlocked.png"
visible: true
}
}
Side note: you don’t need to change properties using clicked handler. Prefer using the checked property of Button
I have created a custom virtual keyboard where the components are buttons, whose attributes I have defined in the code below . When I rapidly move the mouse across the buttons, I find that there is a 'flashing' effect whereby the button opacity appears to momentarily drop to 0 and then return. How can I prevent this flashing effect?
import QtQuick 2.15
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.0
import "definitions.js" as Defs
Button {
id: keyboardButton
property bool specialButton: false
contentItem: Text {
text: keyboardButton.text
font.family: Defs.font
font.pointSize: Defs.defaultTextSize
color: Defs.ivory
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
id: background
property double op: specialButton ? 0.7 : 0.5
color: Defs.b_blue
opacity: op
radius: 0
OpacityAnimator on opacity{
running: keyboardButton.hovered
from: background.opacity
to: background.op + 0.05
duration: 100
}
OpacityAnimator on opacity{
running: !keyboardButton.hovered
from: background.op + 0.05
to: background.op
duration: 100
}
}
}
Using one animator fixes it for me:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
width: 640
height: 480
visible: true
Flow {
anchors.fill: parent
Repeater {
model: 100
Button {
id: keyboardButton
property bool specialButton: false
contentItem: Text {
text: keyboardButton.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: "steelblue"
opacity: hovered ? baseOpacity + 0.15 : baseOpacity
radius: 0
property double baseOpacity: keyboardButton.specialButton ? 0.7 : 0.5
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
}
}
}
}
I've made some QtQuick programs, and I thought it was all working fine, till I tried them out on my laptop, which is running KDE, with the Breeze Dark theme.
A simple program with a label is barely readable:
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window
{
visible: true
Label
{
font.pointSize: 20
text: "Hello world!"
}
}
With KDE Breeze Dark:
With XFCE:
I have a customised combobox too, and it looks terrible under KDE. It has the same issue on the default KDE theme, just with the colours inverted:
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick 2.7
Window
{
visible: true
minimumWidth: 200
minimumHeight: 200
ComboBox
{
id: combo
model: ["Apple", "Banana", "Orange"]
width: 150
height: 50
delegate: ItemDelegate
{
id: item
width: parent.width
contentItem: Text
{
text: modelData
font.pointSize: 15
}
MouseArea
{
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
onClicked: mouse.accepted = false
onPressed: mouse.accepted = false
onReleased: mouse.accepted = false
onDoubleClicked: mouse.accepted = false
onPositionChanged: mouse.accepted = false
onPressAndHold: mouse.accepted = false
onEntered:
{
item.highlighted = true
}
onExited:
{
item.highlighted = false
}
}
}
contentItem: Text
{
id: dropDown
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pointSize: 15
text: combo.displayText
}
}
}
With KDE Breeze Dark:
With XFCE:
So, I'm not sure if this is a KDE issue, or a QtQuick issue.
I guess I want to know how I can either disable KDE theming of certain programs, or modify my Qml to display my programs nicely when themed.
I couldn't find barely any literature on QtQuick theming, aside from some proposals or ways to manually implement it.
You can use SystemPalette. For example:
Window {
visible: true
color: palette.window
Label {
font.pointSize: 20
text: "Hello world!"
}
SystemPalette {
id: palette
colorGroup: SystemPalette.Active
}
}
Inside QML MainWindow, I have Slider and ProgressBar:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
ApplicationWindow
{
visible: true
width: Screen.width/2
height: Screen.height/2
opacity: 1.00
color: "black"
RowLayout
{
anchors.fill: parent
Slider
{
id: ueSlider
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignLeft|Qt.AlignVCenter
activeFocusOnPress: false
tickmarksEnabled: false
minimumValue: 0
maximumValue: 100
stepSize: 1
orientation: Qt.Vertical
onValueChanged:
{
ueProgressBar.value=value;
} // onValueChanged
} // Slider
ProgressBar
{
id: ueProgressBar
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 8
Layout.alignment: Qt.AlignRight|Qt.AlignVCenter
orientation: Qt.Vertical
indeterminate: false
onValueChanged:
{
print("ProgressBar value: "+value);
} // onValueChanged
Component.onCompleted:
{
minimumValue=ueSlider.minimumValue;
maximumValue=ueSlider.maximumValue;
value=ueSlider.value;
} // Component.onCompleted
} // ProgressBar
} // RowLayout
} // ApplicationWindow
Now, the ProgressBar is "connected" to Slider - when I change value of Slider, the ProgressBar's value changes. If I change ProgressBar's orientation to Qt.Horizontal, everything works fine, but if I change its orienation to Qt.Vertical, run example and push Slider to top (to its maximumValue), the ProgressBar does not go to 100%:
Why the hell?!
I know I should be using Row, Column etc. rather than items anchored by ID to make my code simpler and easier to read. But they refuse to work most of the time. For example, in this case:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Item {
id: textItem
height: row.height
Label {
anchors.left: textItem.left
anchors.top: textItem.top
text: nazov
font.bold: true
}
Label {
anchors.left: textItem.left
anchors.bottom: textItem.bottom
text: cas
}
}
}
}
}
This shows two Labels on the top of an Image in the delegate of list view. Not two labels to the right of the image, as you would expect. However, this code works:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Label {
text: nazov
font.bold: true
}
}
}
}
Of course I need to show more than one label in the delegate. What am I missing here?
It turns out that Item has zero width by default. The code works properly after the width is set:
Item {
id: textItem
height: row.height
width: childrenRect.width
// labels etc
}