Trouble setting activeFocus to Item in a QML TabView - qml

When the user changes the current tab in my TabView. I would like to set the activeFocus to the top level Item in the current tab, e.g. using forceActiveFocus. However for some weird reason the TabView is setting the activeFocus to the first Button it finds in the Tab, even if that Button has "focus: false" set.
As shown in the output below. When I use forceActiveFocus to set the focus to the top-level Item. First that Item gets focus, then it immediately loses focus and the Button gains focus instead. If there is no Button in the tab, then it works as expected. I need advice on a work-around for this problem. I would like to know if this is a Bug or whether I'm doing something wrong here?
Below is the program output when the user clicks on the 2nd tab.
qml: Item Focus gained: Tab2
qml: Button focus gained: Tab2
qml: Item Focus lost: Tab2
Code example follows (tested in Qt 5.4.2):
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
width: 640
height: 480
visible: true
TabView {
id: tabView
onCurrentIndexChanged: {
getTab(currentIndex).forceActiveFocus();
}
}
Component.onCompleted: {
var tab1 = tabView.addTab("tab1", tabComp);
tab1.active = true;
tab1.item.objectName = "Tab1";
var tab2 = tabView.addTab("tab2", tabComp);
tab2.active = true;
tab2.item.objectName = "Tab2";
}
Component {
id: tabComp
Item {
focus: true
onActiveFocusChanged: {
if(activeFocus)
console.log("Item Focus gained: " + objectName);
else
console.log("Item Focus lost: " + objectName);
}
Button {
focus: false
onActiveFocusChanged: {
if(activeFocus)
console.log("Button focus gained: " + parent.objectName);
else
console.log("Button focus lost: " + parent.objectName);
}
}
}
}
}

When a tab is clicked, TabView is setting the activeFocus to the first Item with activeFocusOnTab set. Button has this set to true by default. I solved this by setting activeFocusOnTab to false for the Button. This is a bit inconsistent with usual focus management in QML because I think normally the "focus" property is meant to take precedence over "activeFocusOnTab" for initial focus, but in this case it is ignored.

Related

how to set TextField automatically editible without clicking Textfield on qtquick2

i am trying to create a TextField and when the TextField is appeared i want it to become editible even without clicking the Text area. It appears but without clicking on placeholder text which is text area, it is not becoming active. Here is what i tried
import QtQuick 2.12
import QtQuick.Controls 2.0
Item {
TextField {
id: textFieldTest
placeholderText: "This area should appear as clicked"
anchors.centerIn: parent
focus: true
Component.onCompleted: textFieldTest.forceActiveFocus()
}
}
I've also tried to use
focus: true
and
Component.onCompleted: textFieldTest.forceActiveFocus()
seperately. Also together. But both of them did not work. Which function or feature should i use?
Sometimes, you need to delay it, e.g.
Component.onCompleted: Qt.callLater(textFieldTest.forceActiveFocus)
The reason being, is that other components initializing may also want to change focus. So, you want to delay your request for focus so that "last in wins".
Please share your entire code if possible. It seems some thing else is stealing the focus. In my case this is working:
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
TextField {
id: textFieldTest
placeholderText: "This area should appear as clicked"
anchors.centerIn: parent
focus: true
Component.onCompleted: textFieldTest.forceActiveFocus()
}
}

MouseArea in qml(onEntered, onExited, onReleased)

I have one button. I want to change the states of button e.g:
Default image is black.
onEntered i want image as blue, onExited i want image as black(equal to default state), and onReleased i want image as blue(equal to onEntered state).
Note:
onRelease should be active inside the button and outside the button onRelease shouldn't work.
How this can be achieved?
Mouse area looks like this:
MouseArea
{
anchors.fill: firstImage(parent)
onEntered:
{
firstImage.source = "blue.img"
}
onExited:
{
firstImage.source = "black.img"
}
onReleased:
{
firstImage.source = "blue.img"
}
}
Problem i am facing is:
onRelease is active outside the button.
I want onRelease to be active when press is released inside the button.
You can leverage the fact that you can give every object in qml an extra custom property.
I came up with the following, which seems to be what you ask, however, I see a flaw, because when you are 'entered' and press, the button will go to entered state, so there is not difference in the 'released' state, and after leaving the MouseArea it will again go to 'exited' state.
Note, I did not copy the firstImage.source stuff, but you can easily tailor this example to your situation
import QtQuick.Controls 2.4
Button {
hoverEnabled: true
property bool touched : false
onHoveredChanged: touched = hovered
onReleased: touched = true
text: touched ? "touched" : "not touched"
}
The hoverEnabled needs to be set

Qml button fix size

I have made list whose delegate is RowLayout consist of Button. The list takes data from cpp.
My problem is the button variable width. The button side changed based on data. I want to keep fix button side and wrap text
To give your Button a fixed width, just set the property with the same name to a fixed value.
The Button has a contentItem that is a Text. You can change the wrapMode there to Text.WordWrap
As the contentItem is of type Item you can't set the wrapMode like this:
Button {
width: 100
text: 'Very very long button description.'
contentItem.wrapMode: Text.WordWrap // Won't work
}
Instead you might use Component.onCompleted like this:
Button {
width: 100
text: 'Very very long button description.'
Component.onCompleted: contentItem.wrapMode = Text.WordWrap
}

Zoom Flickable's content on wheel event

By default, Flickable scrolls on mouse wheel event: horizontally if Shift modifier is pressed, and vertically if no modifier is active. I'd like to override this behaviour to make it zoom in/out.
I tried to use MouseArea as a child of Flickable. Defining desired behaviour inside onWheel handler I get what I want, but it breaks flicking feature. Motion of two touch points is recognised as a wheel event on my Mac, what prevents Flickable to steel this event (MouseArea.preventSteeling is false by default). So I get somewhat mixed zooming feature that respects velocity/acceleration behaviour of Flickable.
Add an onWheel handler underneath your MouseArea:
MouseArea
{
onWheel: {
if (wheel.modifiers & Qt.ControlModifier){
if (wheel.angleDelta.y > 0)
{
zoomin()
}
else
{
zoomout()
}
}
else{
wheel.accepted=false
}
}
}

Send text from Qt textEdit control to QML TextInput control using Qt/QML

I have created a UI in widget and added a edittext control and a pushButton control to it. In the QML file I have a TextInput control. I am able to display the Widget controls in the QML. Now I want to set the EditText control text in the QML to the text in the edittext control that is there inside the widget when the pushButton of the Widget is clicked. On button click I want to send the text from the editText to QML TextInput.
How is it possible.
I used the following to register and use the Widget in the QML.
main.cpp file --->
qmlRegisterType<WidgetContainer>("MyWidget", 1, 0, "MyWidget");
QML file contents:
import QtQuick 1.1
import MyWidget 1.0
Rectangle {
width: 360
height: 360
color: "gray"
TextInput {
id: textInput1
x: 10
y: 10
width: 100
height: 100
color: "black"
cursorVisible: true
text: widget.getText()
}
MyWidget {
id: widget
x:10;
y:70
width: 180;
height: 150
text: "Widget text"
}
}
Class WidgetContainer should emit signal when button is clicked. Then you will be able to write the clicked handled which you need in QML.
By default button (or any other member of WidgetContainer class) is not available in QML code. So you can't use button's clicked signal in QML directly.
You need to declare e.g. buttonClicked signal inWidgetContainer class. Then you need to connect WidgetContainer's buttonClicked signal to button's clicked signal.
Now you can use buttonClicked signal in QML:
TextInput {
id: textInput1
text: widget.getText()
}
MyWidget {
id: widget
text: "Widget text"
onButtonClicked: textInput1.text = text
}