Here is my sample code:
Window{
id: root
title: "Hello"
Window{
id: child
title: "Wnd1"
}
}
here is the result when i activate click the root:
Is there any way to force root be on top of child when I activate it?
Finally I have found a solution, it is looks not very elegant but it works
Window {
QtObject{
property Window child: Window {
visible: true
}
}
visible: true
}
You can use one of appropriate flags, for example Qt::WindowStaysOnTopHint
Window {
width: 600
height: 400
title: qsTr("Parent window")
visible: true
flags: Qt.WindowStaysOnTopHint
Window {
width: 300
height: 200
title: qsTr("Child window")
visible: true
}
}
But what a reason do do that? You will not be able to communicate with the child window.
Related
Learning qml and trying to separate main window and settings in different files. I have a SettingsView.qml with simple Dialog and Have a main.qml where I call menu and call my settings dialog to popup. When I had a Dialog in main.qml it was fine and it had been resizing with whole window properly. But after I had moved it to different file the behaviour changed. Now also I recieve a message: "refSettingsDialog is not defined". I would be gratefull for any advices.
upd: Closed. No need in properties here etc just basics. And do not call id from another file. Atleast, as I understand it by now
SettingsView.qml
Dialog{
id: settingsDialog
modal: true
focus: true
title: "Settings"
standardButtons: Dialog.Ok | Dialog.Cancel
onAccepted: {
settingsDialog.close()
}
onRejected: {
settingsDialog.close()
}
}
main.qml
ApplicationWindow {
visible: true
id: screen
property alias mainScreen: screen
width: 640
height: 480
property alias screenWidth: screen.width
property alias screenHeight: screen.height
title: qsTr("McdtViewer")
Material.theme: Material.Dark
Material.accent: Material.Yellow
SystemPalette { id: activePalette }
//toolbar
header: ToolBar {
RowLayout {
spacing: 20
anchors.fill: parent
ToolButton {
icon.name: contentSwiper.currentIndex === 1 ? "Back" : "пустой"
onClicked: {
if (contentSwiper.currentIndex === 1){
contentSwiper.pop()
}
}
}
Label {
id: titleLabel
text: contentSwiper.currentIndex === 0? "ExpWatcher": "ExpView"
font.pixelSize: 20
elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
}
ToolButton {
icon.name: "menu"
onClicked: optionsMenu.open()
Menu {
id: optionsMenu
x: parent.width - width
transformOrigin: Menu.TopRight
MenuItem {
text: "Settings"
//calling the instance of settingView which we declared in the bottom
onTriggered: {
settingsView.open()
}
}
}
}
}
}
}
// making instance of settingsDialog here so the width will be calculated properly.
SettingsView{
id: settingsView
x: Math.round((screenWidth - width) / 2)
y: Math.round(screenHeight / 6)
width: Math.round(Math.min(screenWidth, screenHeight) / 3 * 2)
}
}
I have 4 QML files: MainMenu.qml, AppArea.qml, Result.qml and main.qml.
When my app starts, I want to see first page as MainMenu.qml fullscreen. There is a button (on MainMenu.qml) to start AppArea.qml. When I click the the button, I want to start AppArea.qml as fullscreen new window.
There is a button (on AppArea.qml), when I click that button, I want to show Result.qml but I want to see Result.qml on AppArea.qml, I mean when Result.qml come outs, AppArea.qml will not disappear but Result.qml will appear on AppArea.qml.
There is a button on Result.qml. When I click the button, the Repeater in AppArea.qml will regenerate, because maybe model of Repeater changing like 1, 2, 3, 4.... There is a button on AppArea.qml, when I click the button, I want to open MainMenu.qml as a fullscreen new window like AppArea.qml.
Actually you can think basic: My app is a game like this:
How way should I choose for these jobs?
In addition to the mentioned post, in your case you are using the component from qml file, so you need to load the component first, your main.qml can be like this:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
id: mainWindow
title: "Main window"
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: mainMenuLoader
}
Component.onCompleted: {
mainMenuLoader.source="mainMenu.qml"
var mainMenu = mainMenuLoader.item.createObject(mainWindow);
mainWindow.hide()
}
}
and your mainMenu.qml can look like this:
import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Controls 2.2
Component {
id: mainMenu
Window {
id:mmenu
title: "Main Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id: appAreaLoader
}
Text {
text: "This is mainMenu"
}
Button{
id: loadAppArea
anchors.centerIn: parent
text: "Start Game"
onClicked: {
appAreaLoader.source="appArea.qml"
var appArea = appAreaLoader.item.createObject(mainMenu);
hide()
}
}
}
}
you will need to do the same for successive windows ...etc.
While for result, you need to use a MouseArea:
appArea.qml:
Component {
id: appMenu
Window {
id:appMenuWindow
title: "App Menu"
width: 600
height: 600
visible: true
flags: Qt.Dialog
modality: Qt.ApplicationModal
Loader{
id:anotherLoader
visible: true
anchors.left: appMenuText.left
anchors.top: appMenuText.bottom
width: parent.width/3
height: parent.height/3
}
Text {
id: appMenuText
text: "This is App Area"
anchors.centerIn: parent
}
Button{
id: loadResult
text: "Show Result"
onClicked: {
anotherLoader.source = "result.qml"
anotherLoader.visible=true
}
}
Button{
anchors.right: parent.right
id: loadMainMenu
text: "Open main Menu"
onClicked: {
hide()
//mmenu.show()
anotherLoader.setSource("main.qml")
}
}
}
}
result.qml:
Rectangle{
color: "green"
Text {
anchors.centerIn: parent
id: resultxt
text: qsTr("This is result, Click to close")
}
MouseArea {
anchors.fill: parent
onClicked: { anotherLoader.visible = false
}
}
}
I am a beginner in QMl and have worked more on StackWidget in QT C++.In QML i am confused to use stackView and have written following code:
Window {
visible: true
width: 640
height: 480
title: qsTr("Stack view")
MainForm {
StackView {
id: stackView
x: 0
y: 0
width: 360
height: 360
initialItem: page1
Rectangle {
id: page1
//anchors.fill: parent
color: "lightgreen"
Button {
id: buttonPage1
text: "back to 2"
anchors.centerIn: parent
onClicked: {
stackView.pop() //**Is THIS CORRECT**
stackView.push(page2) //**Is THIS CORRECT**
}
}
TextEdit {
id: te1
width: 105
height: 40
text: "enter"
}
}
Rectangle {
id: page2
//anchors.fill: parent
color: "lightblue"
Button {
id: buttonPage2
text: "back to 1"
anchors.centerIn: parent
onClicked: {
stackView.pop() //**Is THIS CORRECT**
}
}
TextEdit {
id: te2
width: 109
height: 29
text: "enter"
}
}
}
}
}
Below are the questions:
In StackWidget i was using setCurrentIndex to set the desired page and I know that in QML i should use push and pop. In that case how to use push and pop to navigate between page1 and page2 based on some selection. ?
Initially, can I load all the pages to the stackView?
How to save the content in the page when I pop an item from stackView?
I know that I will not exactly answer your question on how to use the StackView, that is because I think you don't want to have a StackView following your description.
The use-case of a StackView is, when you have the pages - as the names suggests - on a stack. If you only want to switch between pages, where it is not determinable, which one is logically below another, the StackView is not what you want, and you might want to consider a SwipeView.
In the SwipeView the pages coexist in a side-by-side manner. Since Qt 5.9 they have a interactive property with which you might disable the swipe behaviour.
Here you can choose the page you want to show by setting the currentIndex.
However, the SwipeView will create its pages as needed, to reduce the memory and CPU load (effectively disabling bindings of unloaded pages). This might result in data loss, if the data is not stored in a model outside the page itself.
If you want to have all the pages loaded at the same time, and you only want to switch the visible one, you might go with a simple custom component:
Item {
property int currentIndex
Page1 { visible: parent.currentIndex === 0 }
Page2 { visible: parent.currentIndex === 1 }
Page3 { visible: parent.currentIndex === 2 }
...
}
Or you go like:
MyView.qml
Item {
id: root
property int currentIndex: 0
default property Item newContent
onNewContentChanged: {
newContent.parent = root
newContent.visible = Qt.binding(bindingsClosure(root.children.length - 1))
}
function bindingsClosure(index) { return function() { return root.currentIndex === index } }
}
main.qml
MyView {
Page1 { }
Page2 { }
Page3 { }
}
All my dialogs appear on the top left corner of screen instead of the center.
What is the best way to let the dialogs be placed automatically correct?
import QtQuick 2.7
import QtQuick.Controls 2.2
ApplicationWindow {
id: mainWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component.onCompleted: {
showMessageBox('Hey this actually works!');
}
function showMessageBox(message) {
var component = Qt.createComponent("MessageDialog.qml")
if(component.status == Component.Ready) {
var dialog = component.createObject(mainWindow)
dialog.title = qsTr("Information")
dialog.text = message
dialog.open()
} else
console.error(component.errorString())
}
}
With a very simple MessageDialog.qml:
import QtQuick 2.7
import QtQuick.Controls 2.2
Dialog {
standardButtons: DialogButtonBox.Ok
property alias text : textContainer.text
Text {
id: textContainer
anchors.fill: parent
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignTop
}
}
The documentation hints, that the Dialog is a descendent of Popup which has x/y-coordinates.
I think those would be a good start to position it.
To your avail:
parent.width - which should be the width of your window
width - which should be your Dialogs width
parent.height
height
Calculate the right positions, and you should be fine.
With this you can create a new base class CenteredDialog.qml
Dialog {
x: (parent.width - width) / 2
y: (parent.height - height) / 2
}
and then use CenteredDialog instead of Dialog all the time.
Further, for dynamic instantiation you might declare the Component in the file, and only set the properties upon instantiation using the component.createObject(parentObject, { property1Name : property1Value, property2Name : property2Value ... }) syntax.
You can set x/y position (like derM said), but you have to recalculate every size change of ApplicationWindow!
Here is another solution:
ApplicationWindow {
id: mainWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component.onCompleted: {
showMessageBox('Hey this actually works!');
}
Item {
anchors.centerIn: parent
width: msgDialog.width
height: msgDialog.height
MessageDialog {
id: msgDialog
title: qsTr("Information")
visible: false
}
}
function showMessageBox(message) {
msgDialog.text = message
msgDialog.visible = true
}
UPDATE: with dynamic instantiation:
Item {
id: dialogParent
anchors.centerIn: parent
}
function showMessageBox(message) {
var component = Qt.createComponent("MessageDialog.qml")
if(component.status === Component.Ready) {
var dialog = component.createObject(dialogParent)
dialog.title = qsTr("Information")
dialog.text = message
dialog.open()
dialogParent.width = dialog.width
dialogParent.height = dialog.height
} else {
console.error(component.errorString())
}
}
For a generic code which works anywhere, including out of Window/ApplicationWindow, you should use Overlay parent :
Dialog {
parent: Overlay.overlay // <------- global Overlay object
readonly property int margin: 16
width: parent ? (parent.width / 2 - margin) : 128
height: content.height + margin
x: parent ? ((parent.width - width) / 2) : 0
y: parent ? ((parent.height - height) / 2) : 0
modal: true
Label {
id: content
...
}
}
As of Qt 5.12 you can use anchors.centerIn attached property.
Dialog {
anchors.centerIn: parent
// ...
}
Then it will be centered on its parent. If you want it to be centered on its window, just set its parent to Overlay.overlay.
anchors.centerIn: Overlay.overlay
I have a TabView. Each Tab is in the separate file (here for simplicity I composed all the code in one file). I'd like to launch some function using Enter key or a Button. All is ok when I click the Buttons. But when I press Enter, nothing happens (onTriggered event handler is never executed) and I also get an error:
QQuickAction::event: Ambiguous shortcut overload: Return
If I have only one Tab the problem does not occur and the onTriggered handler is correctly executed.
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
Item {
width: 640
height: 480
TabView {
id: tabView
currentIndex: 0
anchors.fill: parent
Layout.minimumWidth: 360
Layout.minimumHeight: 360
Layout.preferredWidth: 480
Layout.preferredHeight: 640
Tab {
id: tab1
active: true
title: "One"
Item {
id: item
x: 16
y: 8
width: 640
height: 480
Action {
id: calcDataAction
text: "Run"
shortcut: StandardKey.InsertParagraphSeparator
tooltip: "one"
onTriggered: {
console.log("one")
}
}
Button {
action: calcDataAction
id: calcButton
x: 20
y: 20
height: 40
width: 100
}
}
}
Tab {
id: tab2
active: true
title: "Two"
Item {
id: item2
x: 16
y: 8
width: 640
height: 480
Action {
id: calcDataAction2
text: "Run"
shortcut: StandardKey.InsertParagraphSeparator
tooltip: "two"
onTriggered: {
console.log("two")
}
}
Button {
action: calcDataAction2
id: calcButton2
x: 20
y: 20
height: 40
width: 100
}
}
}
}
}
How can I solve it?
As a workaround I could use the following shortcut binding in the Action :
shortcut: tab1.activeFocus ? StandardKey.InsertParagraphSeparator : ""
But the problem is that, first I need (don't know why) to click on all tabs' headers, before events could trigger...
Action has a property enabled, like almost all visual and non-visual types in QML. If enabled - by default it is - an Action can be triggered.
Having all the Actions active at the same time does not make sense since only a single Tab can be visible. Hence, an approach to solve the issue would be to just enable one Action at a time, the one associated to the currently visible tab, that is:
enabled: <tab_id>.visible
Following your code, a minimal example looks like this:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
width: 300
height: 200
visible: true
TabView {
id: tabView
anchors.fill: parent
Tab {
id: tab1
title: "One"
Action {
id: calcDataAction
enabled: tab1.visible
shortcut: "Ctrl+O"
onTriggered: console.log(tab1.title)
}
}
Tab {
id: tab2
title: "Two"
Action {
id: calcDataAction2
enabled: tab2.visible
shortcut: "Ctrl+O"
onTriggered: console.log(tab2.title)
}
}
}
}