QML Force窗口将显示在第一个屏幕上

时间:2019-05-19 15:48:23

标签: c++ qt qml

我具有以下QML组件:

import QtQuick 2.3
import QtQuick.Window 2.3

Window
{
  id: main
  visible: true
  width: 500
  height: 500

  screen: Qt.application.screens[0]

  Text
  {
    text: "Hello World!"
  }
}

使用以下方式:

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QString>

int main(int argc, char** argv)
{
    QApplication app{argc, argv};
    QQmlApplicationEngine engine;
    engine.load(QUrl{QStringLiteral("qrc:/main.qml")});
    return app.exec();
}

我正在两个屏幕的系统上运行它。

只要我拥有screen: Qt.application.screens[0],该窗口将始终在启动应用程序时显示在鼠标所在的屏幕上。

如果我将其更改为screen: Qt.application.screens[1],则无论当前鼠标位置如何,该窗口将始终显示在第二个屏幕上。

Qt.application.screens[2]似乎不存在。

现在有两个问题:screen: Qt.application.screens[0]的这种行为是否可预期,即该数组中的第一个元素是否始终是当前屏幕?

如果是的话,我实际上如何获得第一个屏幕?

已经在Qt版本5.9.6和5.12.3上进行了尝试。

3 个答案:

答案 0 :(得分:1)

在两屏虚拟桌面上,我将尝试在指定屏幕之后立即设置窗口坐标。应该使用以下代码将窗口置于Qt.application.screens数组的第一个屏幕中央:

  screen: Qt.application.screens[0]
  x: screen.virtualX + ((screen.width - width) / 2)
  y: screen.virtualY + ((screen.height - height) / 2)

注意,我使用了virtualXvirtualY属性,即虚拟桌面内屏幕的坐标。这样,窗口将居中放置在其所属的任何屏幕上。

顺便说一句,可以完全省略screen属性,仅设置坐标:

  x: 0
  y: 0

上面的代码会将窗口定位到左屏幕的左上角,即虚拟桌面的绝对左上角。

答案 1 :(得分:0)

如果我正确理解了这个问题,那么Qt.application.screens[0]意味着只访问以下数组的第一个元素:https://doc.qt.io/qt-5/qguiapplication.html#screens。文档中没有描述此方法的QScreen实例的顺序,但是看起来第0个索引表示第一个屏幕。但是,还有另一种方法来获取第一个屏幕。但是,请记住,说“第一个屏幕”并不是完全正确的命名。您可以实际交换屏幕,然后哪个屏幕是第一个屏幕?您应该了解Qt不知道您是否已物理交换屏幕。因此,对于这种类型的屏幕有更正确的要求。 Qt将您可能视为第一个屏幕的屏幕称为主屏幕。访问该屏幕的方法如下:https://doc.qt.io/qt-5/qguiapplication.html#primaryScreen-prop

换句话说,可以通过以下方法满足您的需求:您应该使用screen: Qt.application.screens[0]而不是screen: Qt.application.primaryScreen。第一种方法也可能会起作用,但是primaryScreen的使用比第一种方法更具声明性和清晰度。

答案 2 :(得分:0)

  

该数组中的第一个元素是否始终是当前屏幕?

您可以自己检查数组,只需将以下代码放入Window范围内即可:

Component.onCompleted: {

    var screens = Qt.application.screens
    for(var i in screens)
    {
        console.log("screens[" + i + "]")
        for(var p in screens[i])
        {
            var member = screens[i][p]
            if(typeof member !== "function")
            {
                console.log("   " + p + ": " + member)
            }
        }
    }
}

除制造商/型号外,您可以通过它们的virtualXvirtualY属性来确定哪个屏幕(例如,如果您的虚拟桌面由两个1920x1080全高清屏幕并排组成) ,则左边的将有virtualX: 0,右边的将有virtualX: 1920)。

据我所知,数组不会更改以反映哪个窗口托管窗口:它应该镜像QGuiApplication::screens列表,您也可以在main中检查该列表,然后加载qml:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QScreen>
#include <QDebug>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    int id = 0;
    for(QScreen * s : app.screens())
    {
        qDebug() << "[" << id++ << "]";
        qDebug() << "   geometry: " << s->geometry();
        qDebug() << "   primary: " << (app.primaryScreen() == s);
    }

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}