I am getting some weird behaviour from the Qt Virtual Keyboard on QML. I have a TextInput which has focus, but it will not receive the keystrokes until I do an actual click (using a real mouse, not touch) somewhere on the screen. I am also getting "input method not set" in the log. The system is running Ubuntu 20.04. Anybody came across something like this. Any hints/help would be appreciated.
Would also like to mention that the touch screen works for all the other screen navigation
Please see my code below:
Rectangle {
id: passwordFieldId
anchors.top: passwordPromptId.bottom
anchors.topMargin: 30
anchors.horizontalCenter: userPasswordBackgroundId.horizontalCenter
color: HLGStyles.white
border.color: HLGStyles.black
border.width: 1
width: 350
height: 40
TextInput {
id: passwordInputFieldId
echoMode: TextInput.Password
anchors.fill: parent
font {family: liberationSansRegular.name; pointSize: HLGStyles.mediumFont}
color: HLGStyles.black
visible: passwordVirtualKeyboardId.visible
onVisibleChanged: if(visible) passwordInputFieldId.forceActiveFocus()
onActiveFocusChanged: {
if(activeFocus) {
Qt.inputMethod.update(Qt.ImQueryInput)
}
}
focus: passwordVirtualKeyboardId.visible
padding: 2
verticalAlignment: TextInput.AlignVCenter
anchors.centerIn: parent
Keys.onReturnPressed: viewModel.onEnterPressed(passwordInputFieldId.text)
}
}
InputPanel {
id: passwordVirtualKeyboardId
visible: (guiManager.currentScreenDisplayed === Screens.SoftwareUpdate) && (viewModel.currentScreen === viewModel.userPasswordScreenName) ? true : false
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width * 0.95
height: parent.height * 0.5
anchors.bottom: parent.bottom
anchors.bottomMargin: 140
}
Related
I'm trying to write a little desktop widget for myself, namely a calendar which neatly displays my university calendar as a sort of timetable. I'm on Kubuntu 20.04, so I guess I'll have to use QML for that... I've followed this tutorial: https://develop.kde.org/docs/plasma/widget/ to create the basic look of the calendar, but now I'm lost as to how to implement the logic.
Basically I'd want to fetch the data from the online iCal, parse it and display it in my widget (and update about every hour or so). I guess I could write a python script for the first part, but I still haven't got the slightest clue how to implement displaying the dates in the QML widget (since QML is probably only supposed to handle the graphics, but how can I implement the logic then?). I've searched the web for a long time now, and looked at a lot of the preinstalled widgets, but that hasn't really helped that much. All of those are also only written in QML, no C++ as far as I could tell... So how could I go about this?
EDIT: By logic I mean: How can I express something like "If there is a calendar entry on monday at 15:30, construct a rectangle at the appropriate position in the widget and give it a fitting label"
My code so far:
import QtQuick 2.0
import QtQuick.Layouts 1.0
import org.kde.plasma.components 3.0 as PlasmaComponents
RowLayout {
spacing: 0
Layout.preferredWidth: 640 * units.devicePixelRatio
Layout.preferredHeight: 480 * units.devicePixelRatio
Rectangle {
//day header
Rectangle {
PlasmaComponents.Label {
text: "Monday"
width: parent.width
horizontalAlignment: Text.AlignHCenter
height: parent.height
verticalAlignment: Text.AlignVCenter
}
color: "transparent"
border.color: "#000"
border.width: 1
anchors.top: parent.top
anchors.right: parent.right
width: parent.width
height: parent.height / 12
}
//day body
color: "transparent"
border.color: "#000"
border.width: 1
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
//day header
Rectangle {
PlasmaComponents.Label {
text: "Tuesday"
width: parent.width
horizontalAlignment: Text.AlignHCenter
height: parent.height
verticalAlignment: Text.AlignVCenter
}
color: "transparent"
border.color: "#000"
border.width: 1
anchors.top: parent.top
anchors.right: parent.right
width: parent.width
height: parent.height / 12
}
//day body
color: "transparent"
border.color: "#000"
border.width: 1
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
//day header
Rectangle {
PlasmaComponents.Label {
text: "Wednesday"
width: parent.width
horizontalAlignment: Text.AlignHCenter
height: parent.height
verticalAlignment: Text.AlignVCenter
}
color: "transparent"
border.color: "#000"
border.width: 1
anchors.top: parent.top
anchors.right: parent.right
width: parent.width
height: parent.height / 12
}
//day body
color: "transparent"
border.color: "#000"
border.width: 1
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
//day header
Rectangle {
PlasmaComponents.Label {
text: "Thursday"
width: parent.width
horizontalAlignment: Text.AlignHCenter
height: parent.height
verticalAlignment: Text.AlignVCenter
}
color: "transparent"
border.color: "#000"
border.width: 1
anchors.top: parent.top
anchors.right: parent.right
width: parent.width
height: parent.height / 12
}
//day body
color: "transparent"
border.color: "#000"
border.width: 1
Layout.fillHeight: true
Layout.fillWidth: true
}
Rectangle {
//day header
Rectangle {
PlasmaComponents.Label {
text: "Friday"
width: parent.width
horizontalAlignment: Text.AlignHCenter
height: parent.height
verticalAlignment: Text.AlignVCenter
}
color: "transparent"
border.color: "#000"
border.width: 1
anchors.top: parent.top
anchors.right: parent.right
width: parent.width
height: parent.height / 12
}
//day body
color: "transparent"
border.color: "#000"
border.width: 1
Layout.fillHeight: true
Layout.fillWidth: true
}
}
there are in my opinion to ways to do this. The first one is as some comments allready mentioned using simple JavaScript to fetch the data from iCal and then parse it. THe other option is using C++ to do the same thing.
Because I am not that experienced in C++ I will only explaine the JavaScript and QML way.
You can start by simple creating a JavaScript file and writing a XMLhttpRequest in it.
https://www.w3schools.com/xml/xml_http.asp
The Link above shows you a simple way to write a XMLhttpRequest in JavaScript. But the basic code for all the people that do not want to open up the link is this.
function getData(url){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE) {
return xhr.responseText;
}
}
xhr.open("Get", url);
xhr.send();
}
This is as I allready said a very simple way of doing it. Next when you have the data, you can parse it. If you get data in a JSON format, the best way to do it would be to just use the normal JSON.parse() function build in Qt. And then you can plugin the data into a normal Model, like a ListModel. If the Data is not in a JSON format or the JSON is not so simple to pick apart, then you can also use the JSONListModel, check it out here: https://wiki.qt.io/JSONListModel
Basicly it is a simple ListModel that directly works with a JSON string. But you can also use the C++ JSON parser, which I unfortunatly have 0 experience with but the documentation can be found here: https://doc.qt.io/qt-5/json.html
Now I hope that I could help you a little with your problem. If not leave a comment.
YOu might also want to check out my book about Qt 6, there you can find a lot more info about Qt, using the Components Qt provides and for instance JSON and C++ Integration if you need that. The book can be found here: https://www.amazon.com/dp/B08XLLDZSG
I have a tab bar with a stacklayout like the following:
Rectangle {
id: rect
height: 190
anchors.right: parent.right
anchors.left: parent.left
color: "transparent"
anchors.top: uniqueHandleText.bottom
anchors.topMargin: 100
TabBar {
id: frame
anchors.right: parent.right
anchors.left: parent.left
background: Rectangle {
color: "#737373"
}
x: -hbar.position * width
Repeater {
model: wizard.categories
TabButton {
id: tabData
property bool selected: false
text: modelData.name
width: 200
font.pixelSize: 18
contentItem: Text {
text: tabData.text
font: tabData.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: "#FFFFFF"
}
background: Rectangle {
implicitWidth: frame.width
implicitHeight: 180
opacity: enabled ? 1 : 0.3
color: tabData.checked ? "#BD9CBE": "#737373"
}
}
}
}
ScrollBar {
id: hbar
hoverEnabled: true
active: hovered || pressed
orientation: Qt.Horizontal
size: rect.width / frame.width
anchors.left: parent.left
anchors.right: parent.right
anchors.top: frame.bottom
}
Text {
font.pixelSize: 18
text: "Next"
anchors.right: parent.right
visible: frame.x != frame.width ? true: false
}
StackLayout {
id: stack1
anchors.left: parent.left
anchors.right: parent.right
anchors.top: frame.bottom
currentIndex: frame.currentIndex
Repeater {
model: wizard.categories
Item {
id: homeTab
TabBar {
id: homeTabTab
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
height: 180
background: Rectangle {
color: "#958096"
}
Repeater {
model: modelData.sub_categories
TabButton {
property bool selected: false
id: currentTab
text: modelData.name
width: 200
font.pixelSize: 18
background: Rectangle {
implicitWidth: frame.width
implicitHeight: 180
opacity: enabled ? 1 : 0.3
color: currentTab.checked ? "#958096": "#8D758E"
}
contentItem: Text {
text: currentTab.text
font: currentTab.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: "#FFFFFF"
MouseArea {
anchors.fill: parent
onClicked: {
if(currentTab.checked){
currentTab.checked = false
} else {
currentTab.checked = true
}
}
onDoubleClicked: {
currentTab.selected = true
var found = false;
var someText = frame.itemAt(stack1.currentIndex).text;
print(someText)
for(var i = 0; i<wizard.selectedSkills.count; i++){
if(wizard.selectedSkills.get(i).name === someText){
wizard.selectedSkills.get(i).sub_categories.append({"name":currentTab.text});
wizard.skills.push({"name": someText})
found = true;
}
}
if(!found){
print(currentTab.text)
wizard.selectedSkills.append({"name":someText, "sub_categories":[{"name":currentTab.text}]})
}
print(window.selectedSkills)
}
}
}
}
}
}
}
}
}
}
I've tried many different things to add a scrollbar or to figure out how to use the flickable functionality that TabBar has. However, the documentation doesn't specify how it works, it just does. Therefore, they are not accessible (or even rewritteable, to use those properties). I want to add a small indicator like an arrow to specify that there is more elements for ease of navigation on desktop on top of the TabBar functionality.
It doesn't seem like the necessary properties are exposed in order to make this happen the easy way.
However, since this is QML, it means the whole object tree is gaping wide open to introspection, allowing us to establish that the item that does the flicking is the contentItem of a ListView inside the Container the ToolBar inherits. The view happens to be the second visible child, although this is technically "private implementation" that one should not rely on. So it is better to take some extra care to establish whether or not you have the correct object.
ApplicationWindow {
id: main
width: 640
height: 480
visible: true
TabBar {
id: toolbar
width: parent.width
height: 50
Repeater {
model: 10
TabButton {
text: "test " + index
width: 100
}
}
}
Rectangle {
height: 5
width: main.width * (view ? view.visibleArea.widthRatio : toolbar.width / toolbar.contentWidth)
color: "red"
anchors.top: toolbar.bottom
x: view ? (main.width - width) * (view.contentX / (view.contentWidth - view.width)) : 0
}
property ListView view: {
var l = toolbar.visibleChildren.length
while (--l) if ("cacheBuffer" in toolbar.visibleChildren[l]) return toolbar.visibleChildren[l]
return null
}
}
And there you have it. We iterate the tabview children until we find one that has a property cacheBuffer which is fairly unique to ListView, and once we have that, we can access the needed properties. As you see, for the indicator width we can do even without the list view, as the toolbar exposes a contentWidth property, but for the indicator position there is no workaround.
And it works:
The problem is that after I build the app on low-resolution Android devices the screen doesn't look compatible. There is not enough spaces for some pages of application. For instance text inputs overflow the screen, some pages have half view images. I would like the application must keep its form even though I resize it to the minimal screen. There are examples in Qt Software like Gallery sample which can be scalable. But I couldn't find what I missed.
Here is part of my application:
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
import Fluid.Controls 1.0
Flickable {
id:optionsPage
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
margins: 5
}
width: parent.width
clip: true
contentHeight: Math.max(optionsColumn.implicitHeight, height)
ScrollBar.vertical: ScrollBar {}
z: 2
Material.background: "white"
Material.elevation: 1
Universal.background: Universal.accent
Column{
anchors.horizontalCenter: parent.horizontalCenter
id:optionsColumn
spacing: 40
anchors.fill : parent
anchors.topMargin : 15
anchors.bottomMargin : 15
anchors.leftMargin :15
anchors.rightMargin : 15
TextField {
anchors.horizontalCenter: parent.horizontalCenter
id:abg_to3
anchors.margins: 1
Text {
color: "#002aff"
anchors.right: abg_to3.left
text: "(AB): "
font.pointSize: 15
}
}
TextField {
anchors.horizontalCenter: parent.horizontalCenter
id:beta_to3
anchors.margins: 1
Text {
color: "#002aff"
anchors.right: beta_to3.left
text: "Beta: "
font.pointSize: 15
}
}
Row{
anchors.horizontalCenter: parent.horizontalCenter
spacing:50
Button {
id:hesapla_to3
text: "Calculate"
}
Button {
id:sil_to3
text: "Delete"
}
}
Column{
anchors.horizontalCenter: parent.horizontalCenter
spacing: 50
TextField {
anchors.horizontalCenter: parent.horizontalCenter
id:bcg_to3
anchors.margins: 1
Text {
color: "#002aff"
anchors.right: bcg_to3.left
text: "(BC): "
font.pointSize: 15
}
}
Rectangle{
id:reco
height:geri.height
width:geri.width
anchors.horizontalCenter: parent.horizontalCenter
Image {
id:geri
source:"../images/third.png"
}
}
}
}
}
This is normal app.
This is after resizing the window.
For the image you should specify a width and a height proportional to the size of the parent or the device and use Image.PreserveAspectFit as fillMode.
For the font, I think you should use a factor ratio which depends on the resolution of the screen, there is an example here: http://doc.qt.io/qt-5/scalability.html#calculating-scaling-ratio
There might be problems with the margins too and once again the use of a ratio might be the solution.
More generally If you want a full scalable application, there are a few rules that can help you, you can find them here : http://doc.qt.io/qt-5/scalability.html
Hope it helped.
We are developing an application on IMX6 using Qt 5.3.2. The Qt libraries are provided by Yocto.
Our requirement is to list items inside a drop down menu using a particular background style. For this purpose we are using ComboBox provided by Qt Quick Controls and QtQuick.Controls.Styles for customizing the drop down background style. We are using MenuStyle component to customize the drop down.
When we apply the styles, we observed that the drop down bottom border does not close.
Please use the following link to view the picture.
We are not facing this issue in the Desktop. We tried running the same application on Ubuntu 12.04.
https://www.dropbox.com/s/33a57jaxs452c4r/IMX6.JPG?dl=0
https://www.dropbox.com/s/cmvvf3ytxg615q8/Ubuntu.JPG?dl=0
Also, below I've listed the qml code which we used for Customizing the drop down.
ComboBox {
id: comboFilterBy
x: 10
y: 130
z:1
width: 285
height: 39
model : eventFiltersList
Rectangle {
id: arrow
anchors.right: parent.right
width: 20; height: parent.height
border.color: "black"
border.width: 1
Image {
id: arrowIcon
// anchors.fill: parent
width: 10
height: arrow.height
anchors.centerIn: parent
clip: true
smooth: true
fillMode: Image.PreserveAspectFit
source: "images/dropDownArrow.png"
}
}
style: ComboBoxStyle {
background:
Rectangle {
color: "#FFFFFF"
border.width: 1
border.color: "black"
antialiasing: true
}
label: Text {
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.left
font.pointSize: 19
font.family: "WenQuanYi Micro Hei Mono"
color: "black"
text: control.currentText
}
// drop-down customization here
property Component __dropDownStyle: MenuStyle {
__maxPopupHeight: 240
__menuItemType: "comboboxitem"
padding.bottom : getPaddingLength(1)
frame: Rectangle { // background
color: "#fff"
border.width: 1
}
itemDelegate.label: // an item text
Text {
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pointSize: 19
font.family: "WenQuanYi Micro Hei Mono"
color: "black"
text: styleData.text
}
itemDelegate.background: Rectangle { // selection of an item
color: styleData.selected ? "#5692c4" : "transparent"
}
__scrollerStyle: ScrollViewStyle { }
}
}
Any help is greatly appreciated.
--Narayanan K
I have a nested ScrollView, similar to the following QML:
import QtQuick 2.0
import QtQuick.Controls 1.1
Rectangle {
width: 200
height: 600
ScrollView {
id: sView
anchors.fill: parent
ListView {
id: list
boundsBehavior: Flickable.StopAtBounds
clip: true
focus: true
interactive: true
model: 5
delegate: Component {
MouseArea {
id: hoverArea
width: 100
height: 200
onClicked: list.currentIndex = index;
Rectangle {
id: fauxParent
anchors.fill: parent
border.width: 1
border.color: "black"
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
height: parent.height
width: parent.width / 2
border.width: 1
border.color: "purple"
color: "green"
Text {
anchors.centerIn: parent
text: "stuff"
}
}
ScrollView {
//parent: sView
anchors.top: fauxParent.top
anchors.right: fauxParent.right
height: fauxParent.height
width: fauxParent.width / 2
ListView {
model: 3
delegate: Component {
Rectangle {
radius: 10
height: 100
width: 100
color: "blue"
}
}
}
}
}
}
}
}
}
}
It seems to run correctly, except that the inner ScrollView won't respond to the mousewheel: the outer ScrollView intercepts that event. The only fix I've found in research for this, is to set the inner scrollview's parent directly to the outer scrollview (uncomment the parent: sView line). Unfortunately, this re-positions all five scrollview delegates onto the top right corner of the outer scrollview. It seems that ScrollView positions itself based on its parent?
For the record, my actual application is wrapping a large section of the page in a scrollview so as to allow the user to access sections of it that may be out of bounds for the current window size. The content of this section, though, has a variety of different controls for a variety of different purposes, including some scrollviews. So I'd also accept an alternate way of moving around a set of generic content that's too large for the window.
This is a Windows desktop app, so I don't need to consider mobile-specific issues.
You nested four elements that handle scroll Events.
Why do you put a ScrollView arround a ListView?
If you remove the ScrollViews the Mousewheel work fine.
Rectangle {
width: 200
height: 600
ListView {
anchors.fill: parent
id: list
boundsBehavior: Flickable.StopAtBounds
clip: true
focus: true
interactive: true
model: 5
delegate: Component {
MouseArea {
id: hoverArea
width: 100
height: 200
onClicked: list.currentIndex = index;
Rectangle {
id: fauxParent
anchors.fill: parent
border.width: 1
border.color: "black"
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
height: parent.height
width: parent.width / 2
border.width: 1
border.color: "purple"
color: "green"
Text {
anchors.centerIn: parent
text: "stuff"
}
}
ListView {
anchors.top: fauxParent.top
anchors.right: fauxParent.right
height: fauxParent.height
width: fauxParent.width / 2
model: 3
delegate: Component {
Rectangle {
radius: 10
height: 100
width: 100
color: "blue"
}
}
}
}
}
}
}
}
If you miss the Scrollbar look at this:
How to create scrollbar in QtQuick 2.0?