我尝试将子窗口实现为弹出窗口,当用户点击它时,该子窗口应该会消失。按照this question设置的示例,我想出了这个:
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: win
width: 360
height: 360
color: "black"
Rectangle {
id: block
width: 20
height: 20
color: "green"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
console.log( "Entered" );
menu.visible = true;
menu.requestActivate();
}
}
Window {
id: menu
width: 100
height: 100
x: win.x + block.width
y: win.y + block.height
flags: Qt.Popup
color: "red"
visible: false
onActiveChanged: {
console.log( "Pop up:", active );
if ( !active ) {
visible = false;
}
}
}
}
onActiveChanged: {
console.log( "Main win:", active );
}
}
但是,在外部单击时,弹出窗口不会消失,调试输出为:
// Main win opens
qml: Main win: true
// Green square entered
qml: Entered
qml: Main win: true
qml: Pop up: true
// Clicked outside of the pop up
qml: Pop up: true
qml: Main win: true
正如您所看到的,当弹出窗口变为活动状态时,主窗口不会失去焦点,因此当用户在其外部单击时,整体焦点不会改变。那么这种方法应该如何运作呢?
答案 0 :(得分:0)
我发现的解决方案感觉相当hackish,但它有效,它是独立的,并且可以扩展。
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: win
width: 360
height: 360
color: "black"
Rectangle {
id: block
width: 20
height: 20
color: "green"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
menu.visible = true;
}
}
Rectangle {
id: menu
width: 100
height: 100
anchors.top: parent.bottom
anchors.left: parent.right
color: "red"
visible: false
Loader {
id: exitAreaLoader
Component {
id: exitArea
MouseArea {
x: 0
y: 0
parent: menu.getRoot()
width: if ( parent !== null ) { return parent.width }
height: if ( parent !== null ) { return parent.height }
onPressed: {
var pnt = Qt.point( mouse.x - menu.parent.width,
mouse.y - menu.parent.height );
if ( !menu.contains( pnt ) )
{
console.log( "Closing", pnt );
menu.visible = false;
exitAreaLoader.sourceComponent = undefined;
} else {
mouse.accepted = false;
}
}
}
}
}
onVisibleChanged: {
if ( visible ) {
console.log( "Opening" );
exitAreaLoader.sourceComponent = exitArea;
}
}
function getRoot() {
var par = parent;
while ( par.parent !== null ) {
par = par.parent;
}
return par;
}
}
}
}
一般原则是,当菜单/弹出/下拉菜单可见时,Loader
会创建MouseArea
作为整个QObject
树中最后代的子项(这可以保证窗口内的所有鼠标事件都将被它接收。但是,这意味着MouseArea
也会捕获指向弹出窗口所包含的任何鼠标事件,因此我们必须明确测试并拒绝该事件。
真的很遗憾没有官方对象,one was requested years ago并且它似乎有adopted by Ubuntu,但这对于跨平台开发来说并不是很有用。