How to catch Key_Cancel pressed from virtual keyboard in qml? - qt

I have the following TextField as the inputfield which is linked to a virtual keyboard.
TextField {
id: inputField
color: buttonActive ? Style.buttonColorTextOn : Style.buttonColorTextOff
text: "100"
topPadding: 8
anchors.left: parent.left
anchors.leftMargin: 8
anchors.right: icon.left
anchors.rightMargin: 8
anchors.top: parent.top
anchors.topMargin: 6
anchors.bottom: parent.bottom
anchors.bottomMargin: 6
inputMethodHints: Qt.ImhDigitsOnly
validator: IntValidator { bottom:lowestInput; top: highestInput}
selectionColor: Style.textSelectionBg
selectedTextColor: Style.fontcolor1
font.family: stdFont.name
horizontalAlignment: TextField.AlignRight
verticalAlignment: TextField.AlignVCenter
font.pixelSize: Style.highlightedFontSize
leftPadding: 3
rightPadding: 3
TextMetrics{
id: textMetrics
text: inputField.text
font.family: stdFont.name
font.pixelSize: Style.highlightedFontSize
}
background: Rectangle
{
color: buttonActive ? Style.buttonColorOn : Style.buttonColorOff
border.color: buttonActive ? Style.buttonColorTextOn : Style.buttonColorTextOff
border.width: 1
Rectangle
{
id: inputFieldColor
color: buttonActive ? Style.buttonColorOn : Style.buttonColorOff
anchors.top: parent.top
anchors.topMargin: inputField.topPadding - 1
anchors.right: parent.right
anchors.rightMargin: inputField.rightPadding - 1
width: textMetrics.width + inputField.rightPadding
height: textMetrics.height
}
}
}
This keyboard looks as the following.
Here the cancel key is constructed as the following in the custom layout for the keyboard.
Key {
key: Qt.Key_Cancel
text: "cancel"
}
My question is, how can I catch when the cancel button is pressed on the virtual keyboard? I'd like catch in a slot something onKeyCancelPressed and possibly undo the changes made on the textfield before pressing the cancel button.
Thanks.

I think the only way is to respond to it in the Key code itself (textBeforeEditing is your own variable):
onClicked: InputContext.priv.inputItem.text = InputContext.priv.inputItem.textBeforeEditing
The downside is that this uses private API.

Related

Scroll a text by mouse Click and hold like a touch screen

I need to scroll by mouse click ,the code bellow works very well when scroll bars clicked or on wheel,BUT I need by mouse click and hold in anywhere in text.
ScrollView {
id: scrollView
x: 15
y: 38
width: 647
height: 168
visible: true
spacing: 2
focusPolicy: Qt.ClickFocus
clip: true
Text {
id: text1
x: -17
y: -27
opacity: 1
visible: true
color: "#ffffff"
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
font.pixelSize: 16
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WrapAnywhere
font.preferShaping: false
font.kerning: false
font.styleName: "Bold"
style: Text.Normal
font.weight: Font.Medium
font.bold: true
clip: true
anchors.topMargin: 0
anchors.bottomMargin: -8
anchors.leftMargin: 0
anchors.rightMargin: 0
font.family: "Courier New"
}
}
You can use a Flickable instead of ScrollView.
A really basic sample would be like this.
Flickable {
width: 200; height: 100
contentWidth: text.width; contentHeight: text.height
// These create default scroll bars for both orientations.
// You could modify the scroll bars if you want.
ScrollBar.vertical: ScrollBar{}
ScrollBar.horizontal: ScrollBar{}
Text{ id: text; width: 200; height: 300; text: "Some long text here" }
}

StackLayout in QML

Requirement: I am building a Settings app in QML, in which the I have divided screen into a grid. On the left hand side of the Grid, there are buttons : Home, Connectivity, Settings and Quit. and on the right hand side, corresponding display should be drawn. Currently, I have added a rectangle, and when I click on buttons like Home, Settings, connectivity etc.. . Code written inside the rectangle of StackLayout is executed successfully.
Instead of writing code in a rectangle, i want to write code in a separate file like settings.qml, connectivity.qml.
How to call the different file by clicking on buttons and setting current Index
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.3
ApplicationWindow {
id:main1
visible: true
x:0
y:20
width: Screen.width
height: Screen.height
title: qsTr("Settings")
GridLayout {
id: gridLayout
width: parent.width
height:main1.height
columns: 2
Rectangle {
id: left_rect
width: Screen.width/4
height: gridLayout.height
color:"yellow"
Button {
id: button
text: qsTr("Home")
anchors.right: parent.right
anchors.rightMargin: 5
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
onClicked: {
layout.currentIndex = 0
}
}
Button {
id: button1
x: 1
y: -4
text: qsTr("Connectivity")
anchors.topMargin: 59
anchors.leftMargin: 5
anchors.left: parent.left
anchors.top: parent.top
anchors.rightMargin: 5
anchors.right: parent.right
onClicked: {
layout.currentIndex = 1
}
}
Button {
id: button2
x: 5
y: -8
text: qsTr("Settings")
anchors.topMargin: 112
anchors.leftMargin: 5
anchors.left: parent.left
anchors.top: parent.top
anchors.rightMargin: 5
anchors.right: parent.right
onClicked: {
layout.currentIndex = 2
}
}
Button {
id: button3
x: 6
y: -16
text: qsTr("Quit")
anchors.topMargin: 172
anchors.leftMargin: 5
anchors.left: parent.left
anchors.top: parent.top
anchors.rightMargin: 5
anchors.right: parent.right
onClicked: {
Qt.quit()
}
}
}
Rectangle {
id: right_rect
width: ( Screen.width/4 )*3
height: Screen.height
color:"green"
StackLayout {
id: layout
anchors.fill: parent
currentIndex: 0
Rectangle {
color: 'teal'
implicitWidth: 200
implicitHeight: 200
}
Rectangle {
color: 'plum'
implicitWidth: 300
implicitHeight: 200
}
Rectangle {
color: 'orange'
implicitWidth: 300
implicitHeight: 200
}
}
}
}
Where you currently have
Rectangle {
color: 'teal'
implicitWidth: 200
implicitHeight: 200
}
replace with
qmlClassName {
id: someId
}

Why does item disappear when anchors changed?

Here is a Tab in a TabView in my qml file:
Tab {
title: "Lab"
Rectangle {
width: 300
height: 600
anchors.margins: 60
color: "gray"
// anchors.top: parent.top
// anchors.bottom: parent.verticalCenter
// anchors.margins: 10
Column {
id : buttons
// anchors.top: parent.top
// anchors.bottom: parent.verticalCenter
anchors.fill: parent
anchors.margins: 10
spacing: 2
Repeater {
model: ["Add entity", "Add Unique Comp", "Add light", "Add Prefab", "Add entity to prefab", "None"]
Rectangle {
width: parent.width - 20
height: 24
anchors.horizontalCenter: parent.horizontalCenter
radius: 3
color: "lightBlue"
Button {
width: parent.width * 0.5
height: parent.height * 0.8
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: index +": "+modelData
onClicked: {
console.log("clicked ", modelData);
}
}
}
}
}
}
}
Here a TabView is used, above is one of the tabs. x y are not specified.
If I remove anchors.fill: parent, the Rectangle will disappear on the screen. Why did this happen? Or how could I debug this?

ListView item covered by header after scrolling

I am trying to use a ListView with a simple header that stays on top of the list. It is working fine for most situations. When I scroll all the way to the top manually the top item is located below the header:
When I set the current index from outside the list to highlight an item the list scrolls to the highlighted item. This is expected and desired behavior. However the list scrolls in a way, that the highlighted item will be on the same height (y) as the header. Therefore the header partially covers the item. In the picture the header is transparent, the highlight is light green:
How can I set up the list so that the list content always starts below the header? Or as a workaround, how can I set the height of the current item after the automatic scroll on selection?
For completeness here is the current code of my list.
ListView {
id: particleList
anchors.fill: parent
model: particleModel
clip: true
highlight: Rectangle { color: Material.color(Material.Green); opacity: 0.2}
highlightMoveDuration: Style.animationDurationMedium
headerPositioning: ListView.OverlayHeader
header: Item {
height: 40
anchors.left: parent.left
anchors.right: parent.right
Row {
anchors.fill: parent
MediumText {
horizontalAlignment: Text.AlignHCenter
width: parent.width / 3
text: qsTr("Width")
}
MediumText {
horizontalAlignment: Text.AlignHCenter
width: parent.width / 3
text: qsTr("Height")
}
MediumText {
horizontalAlignment: Text.AlignHCenter
width: parent.width / 3
text: qsTr("Area")
}
}
}
footer: SmallText {
anchors.left: parent.left
anchors.right: parent.right
text: particleModel.count
}
populate: Transition {
NumberAnimation { properties: "x,y"; duration: 1000 }
}
delegate: Item {
height: 40
anchors.left: parent.left
anchors.right: parent.right
Row {
anchors.fill: parent
MediumText {
anchors.verticalCenter: parent.verticalCenter
width: parent.width / 3
text: model.width
horizontalAlignment: Text.AlignRight
rightPadding: 20
}
MediumText {
anchors.verticalCenter: parent.verticalCenter
width: parent.width / 3
text: model.height
horizontalAlignment: Text.AlignRight
rightPadding: 20
}
MediumText {
anchors.verticalCenter: parent.verticalCenter
width: parent.width / 3
text: model.area
horizontalAlignment: Text.AlignRight
rightPadding: 20
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: 1
visible: model.index !== 0
color: Material.color(Material.Grey)
}
}
}
The Listview rows always scroll behind the header.
So make it opaque (e.g. Rectangle with background instead of item) and increase the z value to have it on top.
For the scrolling use highlightRangeMode, preferredHighlightBegin and preferredHighlightEnd.

Views in QML from Qt(main.cpp)

I have problem with change view/file in QML. In qrc file I have main.qml and second.qml. In main.cpp i start my app by code:
QQuickView view;
view.setSource(QUrl(("qrc:///main.qml")));
view.show();
In main.qml is button which should change view to second.qml, but I dont know in what way do it. I read about qml but anywhere i found the examples.
The main.qml:
Item {
id: screen; width: 320; height: 480;
signal exitApp()
signal qmlSignal(string addressIP, int portTCP)
Rectangle {
id: background
anchors.fill: parent; color: "#ffffff";
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
Button {
id: loginBtn
text: qsTr("RUN")
anchors.right: parent.right
anchors.rightMargin: 100
anchors.left: parent.left
anchors.leftMargin: 100
anchors.bottom: parent.bottom
anchors.bottomMargin: 170
anchors.top: tcpRow.bottom
anchors.topMargin: 10
onClicked: qmlSignal(addressIPTextField.text, parseInt(portTCPTextField.text))
}
}
Row {
id: tcpRow
x: 8
width: 309
height: 100
anchors.top: ipRow.bottom
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
Label {
id: portTCPLabel
height: 20
text: qsTr("Port TCP")
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: portTCPTextField.left
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
}
}}
You can use StackView to navigate between multiple "screens". To adapt your existing code to use StackView, it's probably easier to move each screen into its own QML file. For example, move the background item into LoginScreen.qml:
Rectangle {
id: background
// ...
Button {
onClicked: {
qmlSignal(addressIPTextField.text, parseInt(portTCPTextField.text));
StackView.view.push("qrc:/second.qml");
}
}
}
Here, we use the attached view property of StackView to get access to the view and then push the second screen onto it.
Then, in main.qml:
Window {
width: // ...
height: // ...
StackView {
initialItem: LoginScreen {}
}
}

Resources