Unsolved Right menu bar glitch
-
Hello,
My application is a menu bar that can be on the left or right of the screen. When the user hovers over the bar, it extends to show more options. This works very well when the menu bar is on the left of the screen. My application window is then located at x=5 and I extend the width of the window when hovered. I am using Qt on Windows with MinGW 5.7
The problem is when the menu bar is on the right. Things are more complex since the application window gets filled towards the right. I mean that we must give an "x" position and a width which will fill from "x" to "x+width". However, in this case, I would like to give an "x" and fill to the left. Unfortunately, we can't give negative width.
I thought of using a transformation : "transform: Scale { origin.x: 0; origin.y: 0; xScale: -1}" but we can't do that on an application window.
So what I did was to use set the position to "x:Screen.width-mainwin.width" to auto-adjust the position. However, it create glitches as you can see on the following video. It works when the bar is on the left but not when it's on the right (in fact it's worse than we see on the video, I think the screen capture did not get everything but you can seee the flickering). At some times, we can see the red bar momentarily going to the middle of the screen.
https://drive.google.com/open?id=0B5jjRZXY3i_zeTdqWjlpMTE5dkkThe blue area is the application window. The red area is the bar containing the shortcuts (it should not move). The green area is the additional information.
Here are the two codes:
LEFT MENU BARimport QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtQuick.Window 2.0 ApplicationWindow { id: mainwin visible: true width: 100 height: Screen.height*0.8 title: qsTr("Hello World") flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint color:"blue" y:5 x:5 Rectangle { anchors.left: parent.left anchors.top:parent.top anchors.bottom: parent.bottom width:80 id:rect1 color:"red" MouseArea { anchors.fill:parent hoverEnabled: true z:2 id:marea1 propagateComposedEvents: true onClicked: mouse.accepted = false; onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; onDoubleClicked: mouse.accepted = false; onPositionChanged: mouse.accepted = false; onPressAndHold: mouse.accepted = false; onEntered: { mainwin.width=500 rect2.visible=true } onExited: { mainwin.width=100 rect2.visible=false } } Rectangle { id:rect2 visible:false anchors.left:rect1.right anchors.top:rect1.top anchors.bottom:rect1.bottom width:400 color:"green" } } }
RIGHT MENU BAR
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtQuick.Window 2.0 ApplicationWindow { id: mainwin visible: true width: 100 height: Screen.height*0.8 title: qsTr("Hello World") flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint color:"blue" y:5 x:Screen.width-mainwin.width-5 Rectangle { anchors.right: parent.right anchors.top:parent.top anchors.bottom: parent.bottom width:80 id:rect1 color:"red" MouseArea { anchors.fill:parent hoverEnabled: true z:2 id:marea1 propagateComposedEvents: true onClicked: mouse.accepted = false; onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; onDoubleClicked: mouse.accepted = false; onPositionChanged: mouse.accepted = false; onPressAndHold: mouse.accepted = false; onEntered: { mainwin.width=500 rect2.visible=true } onExited: { mainwin.width=100 rect2.visible=false } } Rectangle { id:rect2 visible:false anchors.right:rect1.left anchors.top:rect1.top anchors.bottom:rect1.bottom width:400 color:"green" } } }
Thank you so much !
Alex
-
Hi,
I think that changing the dimension of the main window while moving its x coordinate is the problem.
In fact you are moving everything, even your MouseArea! So the state of your MouseArea is rapidly changing between the "onEntered" and "onExited" state while your main window is moving. That's why it's glitching.What I propose as a possible solution is to enable only one of the two states at a time. So when the window is closed only the "onEntered" signal will be processed, while when it is open the "onExited" code will run.
Switching from one state to the other cannot be instant, of course, otherwise your system will be glitchy as now. So I propose to set a Timer which in some milliseconds will switch your state from one to the other.
Here's my code for your right menu bar:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtQuick.Window 2.0 ApplicationWindow { id: mainwin visible: true width: 100 height: Screen.height*0.8 title: qsTr("Hello World") flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint color:"blue" y:5 x:Screen.width-mainwin.width-5 Rectangle { property bool opened: false // this is your window state anchors.right: parent.right anchors.top:parent.top anchors.bottom: parent.bottom width:80 id:rect1 color:"red" MouseArea { anchors.fill:parent hoverEnabled: true z:2 id:marea1 propagateComposedEvents: true onClicked: mouse.accepted = false; onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; onDoubleClicked: mouse.accepted = false; onPositionChanged: mouse.accepted = false; onPressAndHold: mouse.accepted = false; onEntered: { if(rect1.opened === false) // here check the state { mainwin.width=500 rect2.visible=true move_window.running=true // run the timer } } onExited: { if(rect1.opened === true) // here check the state { mainwin.width=100 rect2.visible=false move_window.running=true // run the timer } } } Rectangle { id:rect2 visible:false anchors.right:rect1.left anchors.top:rect1.top anchors.bottom:rect1.bottom width:400 color:"green" } Timer { id: move_window interval: 250 running: false onTriggered: // when the timer starts, it will switch your state { if(rect1.opened === true) rect1.opened = false else rect1.opened = true } } } }
If changing the main window width is not mandatory for your project, I would suggest to set it as fixed, and change the width of your rectangles with respect to the MouseArea signals. In this way you can assure that the MouseArea will not be moved from its location.
That's my trivial example:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtQuick.Window 2.0 ApplicationWindow { id: mainwin visible: true width: Screen.width*0.8 height: Screen.height*0.8 title: qsTr("Hello World") flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint color:"transparent" y:5 x:Screen.width - mainwin.width - 5 Rectangle { anchors.right: parent.right anchors.top:parent.top anchors.bottom: parent.bottom width:80 id:rect1 color:"red" MouseArea { anchors.fill:parent hoverEnabled: true z:2 id:marea1 onEntered: { rect2.width=500 } onExited: { rect2.width=0 } } } Rectangle { anchors.right: rect1.left anchors.top:parent.top anchors.bottom: parent.bottom width:0 id:rect2 color:"green" } Rectangle { anchors.right: rect2.left anchors.top:parent.top anchors.bottom: parent.bottom width:20 id:rect3 color:"blue" } }
Of course the main window will cover part of your screen, even if it is transparent.
-
@Marco-Pellin Thank you very much for your answer.
I tried your first code but it has the same glitch. You can see it better if you set "blue" and "green" to "transparent". But in fact, my code does not change the MouseArea. The MouseArea is supposed to remain over the red rectangle which is supposed to always remains at the same place and with the same width. This red rectangle is attached to the rigght of the application window (anchors.right: parent.right). However, what is stange is that when we hover on the red rectangle, it momentarily switch to the left of the application window.As four your second code, I really need to modify the width of the application window. Otherwise, even if it's transparent, the user won't have access to the content under it (he will see it but won't be able to interact with it...).
Thank you very much !
Alex