Is it possible to achieve a possibility of editing title of a tab within TabView after double-click it? I mean exactly something as follows.
I had a look at Tab, TabView and TabBar documentation, but I didn't find anything which could help to implement mentioned functionality.
You can embed anything in any other item in QML. By using states, one can let the TabButton behave in different states (duh), in this case an "editing" state, where some parts are only show during that state and others are hidden.
You should place the following in some qml
import QtQuick 2.0
import QtQuick.Controls 2.3
TabButton {
id: btn
onDoubleClicked: state = "editing"
TextField {
id: editor
anchors.fill: parent
text: btn.text
visible: false
onAccepted: {
btn.text = text
btn.state = ""
}
}
states: [
State {
name: "editing"
PropertyChanges {
target: editor
focus: true
visible: true
}
PropertyChanges {
target: btn
explicit: true
restoreEntryValues: false
text: "" //so the text won't show up during editing
}
}
]
}
Related
I have this code:
//main.qml
Window {
id: root
width: 640
height: 480
visible: true
title: qsTr("Hello World")
objectName: "Window"
onActiveFocusItemChanged: console.log("***** ACTIVE FOCUS:", activeFocusItem, "*****")
StackView {
anchors.fill: parent
initialItem: "qrc:/LoaderPage.qml"
objectName: "StackView"
onCurrentItemChanged: currentItem.forceActiveFocus()
}
}
//LoaderPage.qml
Item {
objectName: "ItemLoaderPage"
// Keys.forwardTo: loader
Loader {
id: loader
anchors.fill: parent
objectName: "Loader"
focus: true
sourceComponent: rect1
}
Component {
id: rect1
Rectangle {
Keys.onReleased: {
if(event.key === Qt.Key_Escape || event.key === Qt.Key_Back)
{
console.log("Esc or back pressed from", objectName)
event.accepted = true
}
}
objectName: "Rectangle"
focus: true
color: "blue"
}
}
}
I am trying to give the focus to the Rectangle in rect1 Component and catch key events, but with this code, the focus is always given to ItemLoaderPage and I am not able to catch key events. How can I solve that?
I find that maintaining keyboard focus is a big weakness in Qt. The docs make it all sound so straightforward, but in practice I am always ending up in situations where I can't even tell where the focus went.
I usually resort to manually calling forceActiveFocus() rather than depending on Qt to do the right thing automatically. It's a fragile solution, but it's at least one that I feel I have control over.
Loader {
sourceComponent: rect1
onLoaded: {
item.forceActiveFocus();
}
}
The Loader and the rectangle has requested the focus by your attribute:
focus: true
You should try to set the focus only once if I get the idea of the focus-attribute right.
Since my last issue with my code, I've come across a new one. Unfortunately, it's not really an implementation issue but much more an "conceptual" issue.
Well so let met introduce the case. I have a grid full of button and then to deal with their onClicked events I have a ButtonGroup
GridLayout {
id: gl
anchors.fill: parent
...
CustomButton{
id: btnMILA1
text: "PlayBook 1"
... //Layout stuff
}
CustomButton{
id: btnMILA2
text: "PlayBook 1"
... //Layout stuff
}
CustomButton{
id: btnMILAN
text: "PlayBook 1"
... //Layout stuff
}
}
Those are generated in a loop so no worries, I didn't wrote all 40 buttons ^^ So here is my ButtonGroup
ButtonGroup {
id: btnGroup
buttons: gl.children
onClicked: {
... //Do some stuff
}
}
As you may have seen, I have a CustomButton element which is used for two reasons :
Esthetics (custom design, round corners, etc...)
Add a MouseArea to each button and onRightclick, show a Menu element
So here is a simplified version of my code for CustomButton element:
import QtQuick 2.15
Button {
id: button
property string optionalConf //SEE LATER BELOW, THIS ITEM WILL BE USEFUL
text: qsTr("Button")
contentItem: Item{
Text {
id: name
text: button.text
font: button.font
color: "#ffffff"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
}
background: Rectangle{
color: internal.dynamicColor //Used to deal with Hovered/Pressed/Default states
radius: 10
}
MouseArea {
id:mouseHovered
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked:{
rightClickMenu.open()
}
hoverEnabled: true
}
Menu {
id: rightClickMenu
MenuItem {
text: qsTr("Choix du fichier de configuration...")
shortcut: StandardKey.Open
onTriggered: confOpen.open()
}
MenuItem {
text: qsTr("Choix du firmware...")
shortcut: "Ctrl+Shift+O"
onTriggered: firmwareOpen.open()
}
MenuSeparator{}
MenuItem {
text: qsTr("Console")
shortcut: StandardKey.AddTab
//onTriggered: zoomOut()
enabled: false
}
}
}
I don't really know the efficiency in generating a mouseArea for each element so let me know if you have a better way to have an independent onRightclick option for something like 20 or 30 elements.
My issue is the following. On the page, let's say main.qml where the CustomButton is implemented, I have two fileDialog items : one called confOpen and the other called firmwareOpen as you could expect given the code above. When the user uses the rightclick, the MenuItem shows at the exact place of the mouse, he can choose wherever option he wants. Then a called is made to either confOpen or firmwareOpen and the user is able to select one file.
FileDialog{
id: confOpen
title: "Please choose a conf file"
folder: shortcuts.desktop
selectMultiple: false
nameFilters: ["Conf file (*.conf)"]
onAccepted: {
console.log(fileUrl)
//I'd like to do something like this :
//ButtonUsedToOpenFileDialog.optionalConf : fileUrl
}
}
So here is the real issue, I'd like to store the file path into a property of my CustomButton. I have a property string optionalConf in order to do so. But I can't manage to which button made the call to the FileDialog, so I don't know which button should have his optionalConf property updated.
I hope I've been clear and it doesn't take to long to read but I wanted to be clear and precise. Let me know if you have better ways to do what I'm doing, I'm always listening to advice :)
Add a function to your FileDialog called openDialog and pass to it the button like this:
[...]
MenuItem {
text: qsTr("Choix du fichier de configuration...")
shortcut: StandardKey.Open
onTriggered: confOpen.openDialog(button)
}
[...]
FileDialog {
id: confOpen
property var button
function openDialog(button_) {
button = button_;
open();
}
onAccepted: {
button.optionalConf = "UPDATED";
}
}
I'm trying to create a SwipeView where the first page has the interactive property false, while the others have it enabled. The effect that I'm trying to achieve is to have the main page with a link to the others, but the others can only go back to the main page (like the iOS settings menu).
The issue is that after the first change page, the currentIndex property loses binding causing the SwipeView to break.
Here's the application output:
qrc:/main.qml:10:5: QML SwipeView: Binding loop detected for property "currentIndex"
file:///home/rcc/Qt/5.12.6/gcc_64/qml/QtQuick/Controls.2/SwipeView.qml:49:18: QML ListView: Binding loop detected for property "currentIndex"
and here's the default swipe view application (QtCreator -> New Project -> Qt Quick Application - Swipe) main.qml:
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Tabs")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
interactive: false
onCurrentIndexChanged: {
if (currentIndex === 0) {
interactive = false
} else {
interactive = true
}
}
Page1Form {}
Page2Form {}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("Page 1")
}
TabButton {
text: qsTr("Page 2")
}
}
}
To reproduce the bug:
Click on Page 2.
Swipe left.
Click again on Page 2.
Any suggestions to solve this issue?
I'm still looking into this, but for now you should be able to work around it by delaying the assignment to the interactive property:
onCurrentIndexChanged: {
if (currentIndex === 0) {
Qt.callLater(function() { interactive = false })
} else {
Qt.callLater(function() { interactive = true })
}
}
So, I'm trying to create a traditional look for my QML application which simply consists of a TabBar and a SwipeView. There's also another component which essentially boils down to a button click which should result in a new tab in the TabBar and a new page in the SwipeView. This works, except that when I click on the previous tab (there's a static tab and page when the app starts up), the page in the view doesn't change.
Here's my QML file -
import QtQuick 2.12
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.12
import QtQuick.Controls 2.13
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Component {
id: tabButton
TabButton {
width: implicitWidth
}
}
Component {
id: resultListView
Rectangle {
anchors.fill: parent
color: "green"
}
}
SwipeView {
id: tabBarLayout
Layout.fillHeight: true
Layout.fillWidth: true
interactive: false
currentIndex: 0
LogArea {
id: logArea
}
}
TabBar {
id: tabBar
currentIndex: tabBarLayout.currentIndex
Layout.fillWidth: true
font.capitalization: Font.MixedCase
TabButton {
text: qsTr("log")
width: implicitWidth
}
Connections {
target: qmlBridge
onLoadResultTab: {
tabBar.addItem(tabButton.createObject(tabBar, {text: qsTr("search - " + term)}))
tabBarLayout.addItem(resultListView.createObject())
tabBarLayout.incrementCurrentIndex()
console.log("Added new item...")
}
}
}
}
The onLoadResultTab signal is invoked when the button is clicked. As you can see, I'm adding a new TabButton and incrementing the current index and then creating another component which is just a simple Rectangle for now. Now, when I click on the "log" button, the SwipeView doesn't change its page to the one corresponding to the log tab. Could anyone point out what's the issue here?
I'd like to arrange for a specific control to get the focus within a TabView Tab. Its seems that the first one gets the focus regardless of what I do. I have tried setting focus:false everywhere else but it doesn't work.
Consider the following code. I have a simple column containing two RadioButtons and a TextField. I'd like to arrange for the TextField to always get focus when the tab is selected, but it always goes to the first RadioButton
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
ApplicationWindow
{
visible: true
width: 800
height: 400
TabView
{
anchors.fill: parent
Tab { title: "tab1"; sourceComponent: foo }
Tab { title: "tab2"; sourceComponent: foo }
}
Component
{
id: foo
ColumnLayout
{
spacing: 32
ExclusiveGroup { id: optionGroup }
RadioButton
{
// i always get the focus!!
exclusiveGroup: optionGroup
text: "Click me"
activeFocusOnPress: true
focus: false
}
RadioButton
{
exclusiveGroup: optionGroup
text: "No, click me!"
activeFocusOnPress: true
focus: false
}
TextField
{
// but i want the focus
placeholderText: "type here"
focus: true
}
}
}
}
Press "tab2" to see this,
I tried forcing within TabView by adding,
onCurrentIndexChanged: getTab(currentIndex).item.forceActiveFocus()
But it makes no difference.
I've read the explanation of focus but it hasn't helped in this case.
Thanks for any suggestion or help,
Probably a bug. Try Qt Quick Controls 2.0 instead:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 800
height: 400
header: TabBar {
id: bar
width: parent.width
TabButton {
text: qsTr("tab1")
}
TabButton {
text: qsTr("tab2")
}
}
StackLayout {
anchors.fill: parent
currentIndex: bar.currentIndex
ColumnLayout {
id: columnLayout
spacing: 32
ButtonGroup {
id: optionGroup
buttons: columnLayout.children
}
RadioButton {
text: "Click me"
}
RadioButton {
text: "No, click me!"
}
TextField {
placeholderText: "type here"
focus: true
}
}
}
}