Qt安卓,新的QML窗口无法正常工作。

7

我有这个主窗口:

ApplicationWindow {
    id : mainWindow
    width: 640
    height: 480
    visible: true

    Button{
        text: "go back to form 1"
        onClicked: {
            form2.visible = true;
        }
    }

    SecondForm{
        id: form2
    }
}

第二个窗口是:
Window{
    id: main
    width: 640
    height: 480
    x: 0
    y: 0
    visible: false;
    Button{
        text: "go back to form 1"
        onClicked: {
            main.visible = false;
        }
    }
}

桌面版没问题,但在安卓上运行应用时,它的行为很奇怪!当我点击主窗口中的按钮时,会出现以下错误:W/Qt ( 8903): (null):0 ((null)): QEGLPlatformContext::swapBuffers(): eglError: 12301, this: 0x6b46e7c0 尽管似乎已调用第二个表单,并且主窗口变为非活动状态。但是第二个窗口不可见。尽管我看不到里面的表单和按钮,但当我触摸预期放置按钮的区域时,显然它起作用,第二个窗口消失,然后第一个窗口再次变为活动状态。
当我试图通过点击安卓返回按钮回到主窗口时,它回到了主窗口并出现以下警告:W/Qt ( 8903): (null):0 ((null)): Can't find surface 2
  • 请问如何强制 qt 显示第二个窗口?
  • 根据这篇文章,Qt 应用程序只包含一个可以从 Android 应用程序启动的活动。这是否意味着没有办法拥有多个窗口?我的意思是,只有一个活动的几个 qml 窗口。
  • 如果是这种情况,请问是否有替代方法来开发至少从用户角度看起来是多视图的应用程序?
  • 您对清空应用程序窗口的所有内容并替换为第二个窗口的内容有什么看法?如果我们添加一些过渡效果,它看起来像安卓中的活动转换。但我担心性能问题。
谢谢任何帮助。
1个回答

8

可能在Android上,您只能使用一个窗口。这是有道理的,因为实际上每个Android应用程序都是一个单窗口应用程序,即使那些不是全屏的应用程序也是如此。

这就是为什么尝试创建第二个窗口时会出现错误,这不是强制Qt执行此操作的问题,而是Android不支持这种“桌面中心”的用户界面范例的问题。问题似乎是多个可见表面的问题,而不是多个窗口本身,在Android中可能存在仅支持一个可见表面的限制(这就是为什么控件即使不显示也可以工作 - 对象在内存中存在),您可以“离屏”尽可能多的内容,但是仍然必须将它们合成到可见表面上,这对于多个窗口来说没有太多意义——Android甚至不支持此功能。

您必须找到一种方法在单个窗口中组合多个窗口的内容,无论是同时还是仅根据用户请求。

  • 您可以实施一些布局管理来将主窗口分成不同的区域,以容纳来自辅助窗口的内容。但是这样做可能会导致您的“工作区域”缩小到不可接受的范围。如果您需要同时在屏幕上显示所有内容,则这是您唯一的解决方案。好的一面是,即使使用多个窗口,您也会受到显示尺寸的限制,除非它们重叠。

  • 对于偶尔需要的内容,您可以将其放在不同的选项卡中,或者有一些停靠的图标来显示和隐藏该内容,它将出现在主窗口的顶部,您可以将其设置为全屏或仅部分使用,然后将其隐藏回去。

  • 最后但并非最不重要的是,您可以使用堆栈视图,QML带有一个,甚至支持动画过渡 - 您可能需要做一些额外的工作来使您的应用程序适应“堆栈方式”运行,这是您从一开始就应该做的事情,视觉堆栈是移动应用程序中最常用的方法,需要在其上打开多个对话框。

在这个例子中,我修改了你的代码,使用了一个堆栈视图,并从第二个表单向第一个表单返回一个值,以说明你可以完成这个任务的一种方式(或者你可以只使用一个属性)。
ApplicationWindow {
    id: main
    width: 640
    height: 480
    visible: true

    StackView {
        id: stack
        anchors.fill: parent
    }

    Component {
        id: form1
        Rectangle {
            width: 640
            height: 480
            color: "lightblue"
            function setText(text) { txt.text = text }
            Column {
                Button {
                    text: "open form2"
                    onClicked: stack.push(form2)
                }
                Text {
                    id: txt
                    text: "text has not been set yet"
                }
            }
        }
    }

    Component {
        id: form2
        Rectangle {
            id: f2
            width: 640
            height: 480
            color: "lightgreen"
            Column {
                TextEdit {
                    id: txt
                    text: "enter text here"
                }

                Button {
                    text: "set text"
                    onClicked: {
                        var prev = stack.get(f2.Stack.index - 1)
                        prev.setText(txt.text)
                        stack.pop()
                    }
                }
            }
        }
    }

    Component.onCompleted: stack.push(form1)
}

当然,您可以将表单放在不同的qml文件中,并且不需要使用 Component 。为了清晰起见,我把它们都放在一起。您还可以更改默认的滑动动画而无需自定义动画。
下次您想制作适用于桌面和移动设备的应用程序时,请避免使用所有目标设备上都不可用的功能,这样您就可以避免回头寻找替代方法。

嗨,感谢您的回复。这是一种为移动设备构建用户界面的简洁而美观的方式。有没有办法让安卓系统中的返回按钮与此StackView一起工作?我希望按下返回按钮可以从堆栈中弹出。目前按下返回按钮会退出应用程序。 - a.toraby
我还发现了另一种使用Window组件和QML Loader元素来改变当前窗口内容的方法。它允许您使用source属性动态更改加载的QML文件。你认为哪个更有效?StackView还是Loader? - a.toraby
1
@a.toraby - 使用“Loader”就不同了 - 它可以用另一个元素替换一个元素,但第一个元素将不再存在,因此您将无法进行数据传输,如果“返回”到第一个元素,则会再次创建为空,失去之前输入的所有数据。 - dtech
1
检查 https://dev59.com/54Pba4cB1Zd3GeqPupoE 和 https://dev59.com/82DVa4cB1Zd3GeqPbkJs,以使后退按钮按您所需的方式行事。 - dtech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接