I am attempting to customize the text on the buttons of my custom Dialog.
For this I used a DialogButtonBox as the footer of the dialog, together with some loaders that will load the appropriate buttons as chosen by the user.
However what I'm seeing is that for some popups the buttons get stacked at the far left, and you can't click them. I have managed to reproduce it with a small example:
main.qml
import QtQuick 2.12
import QtQuick.Window 2.2
import QtQuick.Controls 2.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Row{
anchors.centerIn: parent
Button{
property var popup: SimDialog { }
onClicked:
{
popup.open()
}
text: "Open"
}
}
}
SimDialog.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
Dialog {
// ID
id: popupRoot
width: 500
height: 200
topMargin: 20
bottomMargin: 10
leftMargin: 20
rightMargin: 10
// Centered position
x: parent ? parent.x + (parent.width / 2) - (width / 2) : 0// align horizontally centered
y: parent ? parent.y + (parent.height / 2) - (height / 2) : 0// align vertically centered
modal: true
focus: true
clip: true
property int buttons: Dialog.Close | Dialog.Ignore
title: "Test"
Button
{
anchors.centerIn: parent
text: "HELLO"
}
// personalized dialog box buttons so we can translate the button text.
footer: DialogButtonBox {
id: dialogBox
alignment: Qt.AlignRight
Loader
{
active: buttons & Dialog.Help
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Help")
DialogButtonBox.buttonRole: DialogButtonBox.HelpRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Discard
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Continue without saving")
DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Save
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Save")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Ignore
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Ignore")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Apply
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Apply")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Ok
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Ok")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Close
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Close")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
}
Loader
{
active: buttons & Dialog.Cancel
sourceComponent:
Button {
parent: dialogBox
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
}
}
}
Note that in my actual application I have several of these popups and only some of them have this behavior. I haven't been able to pinpoint a commonality between those that don't work either, so I'm really lost.
Here's how it looks on my end
you don't really need the loaders. You can just use the visible property in Button.
This worked for me as expected:
// personalized dialog box buttons so we can translate the button text.
footer: DialogButtonBox {
id: dialogBox
Button {
text: qsTr("Help")
DialogButtonBox.buttonRole: DialogButtonBox.HelpRole
flat: true
visible: true //false
}
Button {
text: qsTr("Continue without saving")
DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
flat: true
}
Button {
text: qsTr("Save")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
Button {
text: qsTr("Ignore")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
Button {
text: qsTr("Apply")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
Button {
text: qsTr("Ok")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
flat: true
}
Button {
text: qsTr("Close")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
flat: true
}
}
Related
I'm making a side menu using a Drawer and I want to stop the user from swiping the drawer. The drawer should open and close based on button clicks. Is there any way to achieve this or am I better off creating my own component?
Drawer {
id: menu
width: 0.37 * parent.width
height: parent.height
edge: Qt.RightEdge
closePolicy: Popup.NoAutoClose
Button {
id: option
onClicked: menu.close()
}
}
Button {
id: menuButton
onClicked: menu.open()
}
You have to set the interactive property of the Drawer to false:
Drawer {
id: menu
width: 0.37 * parent.width
height: parent.height
edge: Qt.RightEdge
closePolicy: Popup.NoAutoClose
interactive: false
Button {
id: option
onClicked: menu.close()
}
}
Button {
id: menuButton
onClicked: menu.open()
}
in Qml there is auto key navigation for already known components like checkbox,textfield,button and etc , i have my custom component which is a item or rectangle and i want same functionality for it,without writing
KeyNavigation.tab: componentid
here is one of my custom controls :
Rectangle {
signal clicked
property alias font : icoText.font.family
property alias icon : icoText.text
property alias size : icoText.font.pixelSize
property alias toolTip : tooltipText.text
property string colorEnter :"#0481ff"
property string colorExit :"#00171f"
id: root
implicitWidth: 50
implicitHeight: 50
//width: childrenRect.width
radius: 0
//height: childrenRect.height
color: colorExit
state: "default"
Text {
id: icoText
text: ""
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 25
font.family: "fontawesome"
visible: text!= ""
color: "white"
}
ToolTip {
id:tooltipText
text: ""
delay: 500
timeout: 2000
visible: mouseArea.containsMouse && text!=""
font.family: "B Nazanin"
contentItem: Text {
text: tooltipText.text
font: tooltipText.font
color: "white"
}
background: Rectangle {
color: "#cc000000"
border.color: "black"
}
}
InnerShadow {
id:shadow
anchors.fill: icoText
radius: 1.0
samples: 17
horizontalOffset: 1
color: colorExit
source: icoText
visible: false
}
MouseArea{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: root.color = colorEnter
onExited: root.color = root.state == "transparent"? "transparent" : root.colorExit
onPressed: {
shadow.visible = true
}
onReleased: {
shadow.visible = false
}
onClicked: {
root.clicked()
}
}
states: [
State {
name: "transparent"
PropertyChanges {
target: root
color:"transparent"
}
PropertyChanges {
target: icoText
color:colorExit
}
},
State{
name: "default"
PropertyChanges {
target: root
color:colorExit
}
PropertyChanges {
target: icoText
color:"white"
}
}
]
}
which will be inside a page like this :
Item{
myControl{
}
myControl{
}
}
this component by default does not loop through pressing tab what should i do?
i already tried this without success, i think this should be inside FocusScope but cause of poor documentation i did not get a simple example for this
set activeFocusOnTab on parent and focus:true in child you want to get focus
Rectangle{
activeFocusOnTab: true
Control{
focus: true
}
}
Focusable Qml Components (Focus My Control On Tab)
For my experience key navigation only works with native components like checkbox, textfield, button, etc.
To work arround this problem I used a fake native component hided with the same size of my custom component like the next example:
Rectangle {
id: myCustomComponent1
width: 100
height: 100
color: red
Button {
id: buttonFake1
text: "My Accessible text Component 1"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake2
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake1.focus = true
}
}
}
}
Rectangle {
id: myCustomComponent2
width: 100
height: 100
color: green
Button {
id: buttonFake2
text: "My Accessible text Component 2"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake1
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake2.focus = true
}
}
}
}
I am trying now to convert my app UI from C++ to QML. At some step I need a login window so I created it in QML with code below:
Window {
id: loginWindow
property string username: login.text;
property string password: password.text;
property bool issave: savePassword.checked;
flags: Qt.Dialog
modality: Qt.WindowModal
width: 400
height: 160
minimumHeight: 160
minimumWidth: 400
title: "Login to program"
GridLayout {
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: "Login"
}
TextField {
id: login
text: Config.getParam("user")
Layout.fillWidth: true
}
Label {
text: "Password"
}
TextField {
id: password
text: Config.getParam("password")
echoMode: TextInput.Password
Layout.fillWidth: true
}
Label {
text: "Save password?"
}
CheckBox {
id: savePassword
}
Item {
Layout.columnSpan: 2
Layout.fillWidth: true
Button {
anchors.centerIn: parent
text: "Enter"
onClicked: {
loginWindow.close();
}
}
}
}
}
I used GridLayout as more compatible to form layout. But the window looks not as expected. This is a screenshot:
GridLayout has 10px margin and also 10px between rows/columns.
But at the screenshot it is seen that the row with button has neither margins nor spacing.
What I do wrong?
Qt 5.3.0
Debian 7.5 x32
The problem is that the Item containing your Button doesn't have a height set. This type of problem is the first thing to check when debugging layout problems. You can do so by printing out the geometry of the item:
Item {
Layout.columnSpan: 2
Layout.fillWidth: true
Component.onCompleted: print(x, y, width, height)
Button {
anchors.centerIn: parent
text: "Enter"
onClicked: {
loginWindow.close();
}
}
}
This outputs:
qml: 0 87 118 0
The fix:
Item {
Layout.columnSpan: 2
Layout.fillWidth: true
implicitHeight: button.height
Button {
id: button
anchors.centerIn: parent
text: "Enter"
onClicked: {
loginWindow.close();
}
}
}
The complete code:
import QtQuick 2.2
import QtQuick.Window 2.0
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
Window {
id: loginWindow
property string username: login.text;
property string password: password.text;
property bool issave: savePassword.checked;
flags: Qt.Dialog
modality: Qt.WindowModal
width: 400
height: 160
minimumHeight: 160
minimumWidth: 400
title: "Login to program"
GridLayout {
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: "Login"
}
TextField {
id: login
text: "blah"
Layout.fillWidth: true
}
Label {
text: "Password"
}
TextField {
id: password
text: "blah"
echoMode: TextInput.Password
Layout.fillWidth: true
}
Label {
text: "Save password?"
}
CheckBox {
id: savePassword
}
Item {
Layout.columnSpan: 2
Layout.fillWidth: true
implicitHeight: button.height
Button {
id: button
anchors.centerIn: parent
text: "Enter"
onClicked: {
loginWindow.close();
}
}
}
}
}
I didn't found any good resource how to use this component and it still fails layout of my app (check that right properties inspector). What i did wrong?
without ScrollView
with ScrollView
scroll that code down please, the scrollview is defined last
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.1
ApplicationWindow {
title: qsTr("Hello World")
width: 1400
height: 800
color: "#414141"
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
ColumnLayout {
anchors.fill: parent
Rectangle {
color: "#414141"
Layout.fillWidth: true
Layout.preferredHeight: 50
MyLabel {
text: "Toolbar"
}
}
SplitView {
Layout.fillHeight: true
Layout.fillWidth: true
orientation: Qt.Horizontal
handleDelegate: MyVSlider {}
SplitView {
Layout.fillHeight: true
Layout.fillWidth: true
orientation: Qt.Vertical
handleDelegate: MyHSlider {}
SplitView {
handleDelegate: MyVSlider {}
Layout.fillHeight: true
Layout.fillWidth: true
orientation: Qt.Horizontal
Rectangle {
color: "#565656"
Layout.fillHeight: true
Layout.preferredWidth: 200
Layout.minimumWidth: 200
MyLabel {
text: "Tree view"
}
}
Rectangle {
color: "#565656"
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumWidth: 500
Layout.preferredHeight: 300
MyLabel {
text: "Scene view"
}
}
}
Rectangle {
color: "#565656"
Layout.fillWidth: true
Layout.preferredHeight: 200
Layout.minimumHeight: 200
MyLabel {
text: "Console output"
}
}
}
Rectangle {
id: inspector
color: "#565656"
Layout.fillHeight: true
Layout.preferredWidth: 200
Layout.minimumWidth: 200
MyLabel {
text: "Properties inspector"
}
}
ScrollView {
contentItem: inspector
}
}
}
}
Are you trying to get your inspector element to be scrollable? You'll want to put the element to be scrolled within the the ScrollView.
i.e.
ScrollView {
Rectangle {
id: inspector
color: "#565656"
Layout.fillHeight: true
Layout.preferredWidth: 200
Layout.minimumWidth: 200
MyLabel {
text: "Properties inspector"
}
// Make the thing really big.
width: 1000
height: 1000
}
}
This will cause your inspector to show up with scroll bars if you set the width and height as I did above.
I want to use a loader object in a ColumnLayout object in this form:
Item{
width: 500
height: 300
focus: true
Keys.onLeftPressed: state = "matrix"
ColumnLayout{
id: panel
anchors.fill: parent
RowLayout{
Layout.minimumHeight: 30
Text {
Layout.fillWidth: true
text: "some"
}
Slider{
Layout.fillWidth: true
}
Button {
text: "otro"
}
}
Loader {
id: load
Layout.fillWidth: true
height: 30
width: 30
}
}
states: [
State {
name: "matrix"
PropertyChanges {
target: load
sourceComponent: tab
}
}
]
Component {
id:tab
Rectangle {
color: "red"
height: 30
width: 30
}
}
}
I use a key event for change the state property, but "tab" component don't load in the root item.
Can any one help me fix this problem?
A Loader cannot have the layout.fillWidth. It must be set when the component load :
Item{
width: 500
height: 300
focus: true
Keys.onLeftPressed: state = "matrix"
ColumnLayout{
id: panel
anchors.fill: parent
RowLayout{
Layout.minimumHeight: 30
Text {
Layout.fillWidth: true
text: "some"
}
Slider{
Layout.fillWidth: true
}
Button {
text: "otro"
}
}
Loader { id: load } // no property here
}
states: [
State {
name: "matrix"
PropertyChanges {
target: load
sourceComponent: tab;
Layout.fillWidth: true; // the layout is set here
}
}
]
Component {
id:tab
Rectangle {
color: "red"
width:30
height:30;
}
}
}