How to edit App menu from Qt Creator? - qt

I start "QML App with controls" project in Qt Creator. I see that I can add to canvas different kind of controls, but I do not see how I can in graphical mode edit menu like: File, View, Edit... In constructor on canvas it's simple do not exists, but it's exists of running app, like http://img.ctrlv.in/img/15/10/03/560f856edb26c.png

You can create the menu in the main.qml file, here is an example application:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
menuBar: MenuBar {
Menu {
title: qsTr("&File")
MenuItem {
text: qsTr("&Open")
onTriggered: messageDialog.show(qsTr("Open action triggered"));
}
MenuItem {
text: qsTr("Save")
onTriggered: messageDialog.show(qsTr("Save action triggered"));
}
}
Menu {
title: qsTr("&Help")
MenuItem {
text: qsTr("About")
onTriggered: messageDialog.show(qsTr("About: test QML app with menu"));
}
}
}
MainForm {
anchors.fill: parent
button1.onClicked: messageDialog.show(qsTr("Button 1 pressed"))
button2.onClicked: messageDialog.show(qsTr("Button 2 pressed"))
}
MessageDialog {
id: messageDialog
title: qsTr("Message Test")
function show(caption) {
messageDialog.text = caption;
messageDialog.open();
}
}
}

Related

Assign MenuItem.Shortcut give Invalid attached object assignment

The following code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.5
import QtQuick.Controls.Styles 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("This is my application title!")
ColumnLayout
{
id: col1
spacing: 2
MenuBar
{
Menu {
title: "File"
MenuItem {
text: "Open"
Shortcut: "Ctrl+O"
onTriggered: console.log("Ctrl+O trigged")
}
MenuItem { text: "Paste link from Ctrl+V" }
MenuItem { text: "Save log as" }
}
Menu { title: "Help" }
Menu { title: "About" }
Menu { title: "Exit" }
}
}
Give the following error:
qrc:/main.qml:25:21: Invalid attached object assignment
the line on error is Shortcut: "Ctrl+O". The Qt documentation give example like this. What am I missing?
edit: added documentation link.
edit 2: updated imports
In qml there are at least 2 groups of controls:
Qt Quick Controls 1
Qt Quick Controls 2
These groups have components with the same one that is the cause of your error since you try to apply the property of the MenuItem from one group to another (check the imports so that you realize the error).
QQC1 MenuItem
QQC2 MenuItem
Depending on which group you want to use, there are different options:
Qt QuickControls 1
import QtQuick 2.12
import QtQuick.Controls 1.4
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("This is my application title!")
menuBar: MenuBar{
Menu {
title: "File"
MenuItem {
text: "Open"
shortcut: "Ctrl+O"
onTriggered: console.log("Ctrl+O trigged")
}
MenuItem{ text: "Paste link from Ctrl+V" }
MenuItem { text: "Save log as" }
}
Menu { title: "Help" }
Menu { title: "About" }
Menu { title: "Exit" }
}
}
Qt QuickControls 2
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("This is my application title!")
menuBar: MenuBar{
Menu {
title: "File"
Action {
text: "Open"
shortcut: "Ctrl+O"
onTriggered: console.log("Ctrl+O trigged")
}
Action { text: "Paste link from Ctrl+V" }
Action { text: "Save log as" }
}
Menu { title: "Help" }
Menu { title: "About" }
Menu { title: "Exit" }
}
}
Possibly you are going to have a similar problem with styles so it is recommended that you read this answer where I point out that using namespace can be a solution if you want to combine components of both modules.
Note: QML is case sensitive, in the docs you indicate it indicates shortcut but you use Shortcut.

QtQuick button shows outside of dialog

I'm trying to make a customizable single button error message dialog in QtQuick, but when I open the dialog the "Ok" button is shown outside of it:
it looks like this
When I open the dialog again, it works normally, the button is shown at the right place.
Here is a minimal working example :
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Controls 2.4
Window {
visible: true
width: 640
height: 480
Button {
text: "Open Dialog"
onClicked: {
dialog.show("This text can be customized.")
}
Dialog {
id: dialog
standardButtons: Dialog.Ok
title: "Error"
modal: true
function show(txt) {
label.text = txt
open()
}
Label {
id: label
}
}
}
}
I'm using Qt 5.11.3 with QtQuick 2.11, build target is Desktop GCC 64 bits.
Is this a bug? What am I doing wrong?
It seems to be a bug in Qt 5.11.3 or in my installation of it on Linux.
Here is the workaround I used, basically recreating the Dialog from a regular Popup :
import QtQuick 2.0
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
Popup {
x: (parent.width-width)/2
y: (parent.height-height)/2
modal: true
closePolicy: Popup.NoAutoClose
property var title: "Error"
property var msg: ""
function show(message) {
msg = message
open()
}
ColumnLayout {
spacing: 30
Label {
Layout.alignment: Qt.AlignLeft
Layout.preferredHeight: 5
font.bold: true
text: title
}
Label {
text: msg
}
Button {
Layout.alignment: Qt.AlignRight
text: "Ok"
onClicked: {
close()
}
}
}
}

How to open a dialog from a MenuBar QML

I'm trying to open a "About" dialog from the menubar.
I have a MainMenuBar.qml that looks like this:
import QtQuick 2.12
import './dialogs'
Labs.MenuBar {
// Various menus omitted
AboutDialog {
id: about_dialog
}
Labs.Menu {
title: qsTr('&Help')
Labs.MenuItem {
text: qsTr('&About')
onTriggered: about_dialog.open()
}
}
}
And my AboutDialog.qml:
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
Dialog {
title: qsTr('id_about')
width: 500
height: 350
standardButtons: Dialog.Ok
Page {
anchors.fill: parent
header: RowLayout {
Image {
Layout.margins: 16
source: "../ic_home.png"
}
}
Label {
anchors.fill: parent
anchors.margins: 32
wrapMode: Text.WordWrap
text: qsTr("Hello world")
}
}
}
When clicking "About" I get:
/src/MainMenuBar.qml: QML Dialog: cannot find any window to open popup in.
I suppose that happens because I am opening it from the menubar and not from a window - is that possible? What should I do?
Nevermind, I figured it out.
AboutDialog.qml shouldn't be declared in MainMenuBar.qml, should be declared in main.qml instead.
MainMenuBar.qml
import QtQuick 2.12
import './dialogs'
Labs.MenuBar {
// Various menus omitted
Labs.Menu {
title: qsTr('&Help')
Labs.MenuItem {
text: qsTr('&About')
onTriggered: about_dialog.open()
}
}
}
main.qml
Item {
MainMenuBar { }
AboutDialog {
id: about_dialog
}
}

QML scope: Invalid alias reference

I get the following error: qrc:/main.qml:17 Invalid alias reference. Unable to find id "button2". The error can be reproduced by the following qml file:
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
id: root
property alias myprop: button2
SplitView {
id: splitView
orientation: Qt.Vertical
SplitView {
id: splitView1
orientation: Qt.Horizontal
TabView {
Tab{
title: "Tab1"
}
Tab{
title: "Tab2"
ColumnLayout {
GridLayout {
Button {
id: button2
text: qsTr("test button")
}
}
}
}
}
}
}
}
}
It seems I have a misunderstanding about qml scope. I thought the parent can access the ids of all of its children?

How to keep a single instance of the window?

I have the next QML:
import Qt.labs.platform 1.0
SystemTrayIcon {
visible: true
iconSource: "qrc:/icons/ic_tray.png"
menu: Menu {
MenuItem {
text: qsTr("Settings")
onTriggered: {
// Don't create a new object if it exists, just show
var settings = Qt.createComponent("main.qml")
var form = settings.createObject(this)
form.show()
}
}
MenuItem {
text: qsTr("Quit")
onTriggered: Qt.quit() // Just hide an existing
}
}
}
How to create main.qml one time only and after just show/hide?
P.S. I'm learning Qt including QtQuick 2 only
Depending on how your application is structured, the best way could be to pass in the window that the tray icon shall control as a property from "further up" your user interface structure.
First, extend your tray icon component and add a "window" property to it:
import QtQuick 2.9
import QtQuick.Window 2.2
import Qt.labs.platform 1.0
SystemTrayIcon {
id: trayIcon
// this property holds the window the tray icon controls:
property Window window
visible: true
iconSource: "qrc:/icons/ic_tray.png"
menu: Menu {
MenuItem {
text: qsTr("Settings")
onTriggered: {
trayIcon.window.show();
}
}
MenuItem {
text: qsTr("Quit")
onTriggered: Qt.quit() // Just hide an existing
}
}
}
Now, you could instantiate your tray icon e.g. in your main window like this:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: mainWindow
width: 800
height: 600
TrayIcon { window: mainWindow }
}
In this case, the tray icon would control the main window itself; however, you can easily create a single instance of a settings window within the main window and pass that one to the tray icon.
You can create the component in the onCompleted.
SystemTrayIcon {
visible: true
iconSource: "qrc:/icons/ic_tray.png"
menu: Menu {
MenuItem {
text: qsTr("Settings")
property var form
onTriggered: {
form.show()
}
Component.onCompleted: {
// Don't create a new object if it exists, just show
var settings = Qt.createComponent("Test.qml")
form = settings.createObject(this)
}
}
MenuItem {
text: qsTr("Quit")
onTriggered: Qt.quit() // Just hide an existing
}
}
}

Resources