Qml menu popup latency - qt

When my mouse event happened,the menu can popup,but not immediately,it seems a little latency. this is my code, is anything wrong?
My Qt version is 5.15, my system is Windows 10.
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
Window {
visible: true
width: 450
height: 350
title: qsTr("ListView")
property bool refreshFlag: false
Rectangle {
id: rightview
width: 60
height: 300
x: 100
color: "#EEEEEE"
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton | Qt.LeftButton
onClicked: {
console.log(width)
if (mouse.button === Qt.RightButton)
contextMenus.popup()
}
Menu {
id: contextMenus
MenuItem { text: "open" }
MenuItem { text: "save " }
MenuItem { text: "else..." }
}
}
Text {
font.pointSize: 12
text: "content"
}
}
}
this is my screenshot

A couple of issues with your program snippet:
Don't mix QtQuick.Controls 1.x with QtQuick.Controls 2.x
Recommend you update all your references to versions to 2.15
Do not declare Menu inside MouseArea, it doesn't make sense
The MouseArea can be optimized to only accept the RightButton
Declare the Menu at the "top level"
Here's a cleanup of your code:
import QtQuick 2.15
import QtQuick.Controls 2.15
Page {
anchors.fill: parent
Rectangle {
x: 100
width: 60
height: 300
color: "#EEEEEE"
Text {
font.pointSize: 12
text: "content"
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: contextMenus.popup()
}
}
Menu {
id: contextMenus
MenuItem { text: "open" }
MenuItem { text: "save " }
MenuItem { text: "else..." }
}
}
You can Try it Online!
There appears to be no performance issue when I run the above snippet using qmlonline. I don't think the code is an issue. I think we need to get an understanding of:
Your version of Qt
Your platform (i.e. OS, hardware, etc)

Related

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
}
}

How should I start QML files?

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
}
}
}

Adding TabButton dynamically to TabBar in QML

I am trying to add a tabButton to TabBar dynamically on pressing a button but i have spent a lot of time searching but i am not getting how to add, below is the code which i am working on :
MyTabButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.2
Item
{
property int BtnWidth:0
property int BtnHeight:0
property string BtnText: ""
property bool isChecked : false
TabButton
{
id:tabBtn
text:BtnText
width:BtnWidth
height:BtnHeight
}
}
MainForm.qml
import QtQuick 2.4
import QtQuick.Controls 2.2
Rectangle
{
Button
{
id:button
width:100
height:100
anchors.top:parent.top
text:qStr("Add")
onClicked{
//How to add logic here to add tab in below tabBar.
}
}
TabBar
{
id:tabBar
anchors.top:button.bottom
width:500
height:500
}
}
Example:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
width: 360
height: 630
visible: true
header: TabBar {
id: tabBar
}
Component {
id: tabButton
TabButton { }
}
Button {
text: "Add"
anchors.centerIn: parent
onClicked: {
var tab = tabButton.createObject(tabBar, {text: "Tab " + tabBar.count})
tabBar.addItem(tab)
}
}
}
You need to have something like a Component that is a TabButton. Your file MyTabButton.qml won't result in a TabButton, but instead an Item containing a TabButton, but with this, your TabBar does not know what to do.
So your file will need to have TabButton as root element
//MyTabButton.qml
import QtQuick 2.4
import QtQuick.Controls 2.2
TabButton
{
id: tabBtn
// customize as you like
}
Then you create a Component of this in your file where you want to use it. (e.g. main.qml)
import QtQuick 2.4
import QtQuick.Controls 2.0
ApplicationWindow {
width: 800
height: 600
visible: true
TabBar {
id: tabBar
width: 800
height: 50
}
// The component is like a factory for MyTabButtons now.
// Use myTabButton.createObject(parent, jsobject-with-property-assignments) to create instances.
Component {
id: myTabButton
MyTabButton {
/// EDIT ACCORDING TO YOUR COMMENTS ***
Connections {
target: tabBar
onCurrentIndexChanged: doSomething()
}
/// EDIT OVER
}
}
Button {
anchors.centerIn: parent
// Create a object out of the component, and add it to the container
onClicked: tabBar.addItem(myTabButton.createObject(tabBar /*, { object to set properties }*/))
}
}
TabBar inherits Container, which has addItem().
Try it in Window
Row {
anchors.fill: parent
TabBar {
id: tabBar
currentIndex: 0
width: parent.width - addButton.width
TabButton { text: "TabButton" }
}
Component {
id: tabButton
TabButton { text: "TabButton" }
}
Button {
id: addButton
text: "+"
flat: true
onClicked: {
tabBar.addItem(tabButton.createObject(tabBar))
console.log("added:", tabBar.itemAt(tabBar.count - 1))
}
}
}

How to get parent button from ButtonStyle without using id?

I created a component (SidebarMenuButton) that is used in the main qml file multiple times. The button has styles that should be inherited by all it's 'instances'. Here is the SidebarMenuButton.qml:
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Button {
width: buttonNewMessage.width
height: buttonNewMessage.height
anchors {
horizontalCenter: parent.horizontalCenter
topMargin: 5
}
style: ButtonStyle {
background: Rectangle {
color: 'transparent'
}
label: Text {
text: parent.text // undefined here
color: 'white'
font.family: 'Helvetica'
font.pixelSize: 12
font.bold: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
}
And a part of my main qml file:
import QtQuick 2.3
import QtQuick.Window 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Window {
id: main
title: 'Messenger'
width: 1024
height: 768
minimumWidth: 800
minimumHeight: 600
RowLayout {
id: layout
anchors.fill: parent
spacing: 0
Rectangle {
id: sidebar
color: '#3C3E55'
Layout.fillHeight: true
Layout.preferredWidth: 200
ButtonCompanyName {
id: buttonCompanyName
}
ButtonNewMessage {
id: buttonNewMessage
}
SidebarMenuButton {
id: buttonInbox
text: 'Inbox (1)'
anchors.top: buttonNewMessage.bottom
}
SidebarMenuButton {
id: buttonSentMessages
text: 'Sent messages'
anchors.top: buttonInbox.bottom
}
SidebarMenuButton {
id: buttonStarred
text: 'Starred'
anchors.top: buttonSentMessages.bottom
}
}
I commented the line with error. parent there doesn't refer to button so the text in all buttons is empty. I need to access parent button from there and get it's text property. The component has no id cause it's used multiple times and ids are assigned in the main qml file. So the question is: how can I get that button text without id?
There are two ways to set text in your case.
1)The Button for which you are applying the style is available as control property in ButtonStyle class. You can set the the text as text:control.text
Reference:control property(ButtonStyle)
2)You can give an id to the Button in SidebarMenuButton type and access its textproperty.
Button
{
id:button
.
.
.
text: button.text
}
You can assign an id inside your component file that would not conflict with the id you use when you instantiate the component somewhere else. I use the same value for the id of most of my QML components: container so that I can easily reference properties from the root of the item.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Button {
id: container
style: ButtonStyle {
background: Rectangle {
color: 'transparent'
}
label: Text {
text: container.text
}
}
}
Then when you instantiate this component in another file you set whichever id you want and it would still work

Resources