QML - позиция главного окна при запуске (центр экрана)

Как я могу сделать следующее: я хочу, чтобы при запуске мое главное окно отображалось на центральном экране.


person AntyaDev    schedule 23.01.2012    source источник


Ответы (6)


Вам нужно будет setGeometry наверху виджет до того, как вы его покажете. Самый простой способ определить, какая геометрия вам нужна, - это QDesktopWidget . Попробуйте приведенный ниже пример (создайте QPushButton, нажимайте его, перемещая виджет по разным экранам), и вы поймете, что я имею в виду:

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{   
  ui->setupUi(this);
  connect(ui->pushButton, SIGNAL(released()), this, SLOT(ButtonPressed()));
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::ButtonPressed()
{
  qDebug() << QApplication::desktop()->screenCount();
  qDebug() << QApplication::desktop()->screenNumber();
  qDebug() << QApplication::desktop()->screenGeometry(this);
}

Оттуда должно быть достаточно просто придумать универсальную версию, которая будет работать с центральным экраном пользователя (если он существует).

person sam-w    schedule 23.01.2012

При использовании QtQuick это возможно:

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0

ApplicationWindow {
    visible: true
    width: 320
    height: 480
    Component.onCompleted: {
        // Commenting this to use properties instead of setters
        //setX(Screen.width / 2 - width / 2);
        //setY(Screen.height / 2 - height / 2);
        x = Screen.width / 2 - width / 2
        y = Screen.height / 2 - height / 2
    }
}
person Dielson Sales    schedule 26.07.2014
comment
По удобству использования это лучший ответ для меня. Проголосовало за - person JustWe; 15.06.2018
comment
Как указано в комментариях к другому ответу, лучше использовать свойство screen вместо синглтона Screen. Ссылаясь на документацию по типу Screen: Обратите внимание, что тип экрана недействителен для Component.onCompleted, потому что элемент или окно к этому времени не отображались на экране. - person Ignitor; 08.01.2021

Ответ Дильсона намного лучше, тем более что виджеты не упоминались ... во всяком случае, вот еще более простая версия его ответа:

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    visible: true
    x: Screen.width / 2 - width / 2
    y: Screen.height / 2 - height / 2
    width: 320
    height: 480
}

Как упоминал Александр, эта привязка может привести к странному поведению при изменении размера. Из-за этого лучше использовать ответ Дильсона. Единственное, что я хотел бы упомянуть, это то, что в QML не принято использовать сеттеры; некоторые системы (я считаю, что они называются перехватчиками свойств) даже полагаются на свойства, установленные, например, для выполнения анимации. Таким образом, наиболее распространенный подход выглядит следующим образом:

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    visible: true
    width: 320
    height: 480

    Component.onCompleted: {
        x = Screen.width / 2 - width / 2
        y = Screen.height / 2 - height / 2
    }
}
person Mitch    schedule 17.10.2014
comment
Для ApplicationWindow есть свойство screen. - person Tomilov Anatoliy; 08.05.2018
comment
Либо люди этого не видят сразу, либо не пробовали? Кстати, а как насчет ситуации с несколькими мониторами? Тогда единственно правильным способом было бы использовать свойство screen для Window. doc.qt.io/qt-5/ qml-qtquick-window-window.html # screen-prop - person Alexander V; 22.09.2018
comment
Не уверен. Это могло сработать (изменить размер без проблем) еще в 2014 году. - person Mitch; 23.09.2018
comment
Абсолютно точно и проверил буквально вчера на Ubuntu с 2-мя мониторами разных размеров. В зависимости от того, какой монитор является основным и имеет индекс 0 или Screen, возникает ошибка некорректного центрирования окна. - person Alexander V; 23.09.2018
comment
Я сказал, что не уверен - я говорю за себя. Хорошо, что вы проверяете это, но я не учитываю в своем ответе настройки с несколькими мониторами, поэтому не стесняйтесь предлагать свои собственные. - person Mitch; 23.09.2018
comment
Сотрите это. Предоставляю и свой ответ. - person Alexander V; 25.09.2018

После изучения обоих ответов и фактической отладки кода с помощью Qt 5.9.1 он показывает более одной проблемы с исходными ответами:

  1. Невозможно привязать [x, y] к [width, height], если мы не хотим видеть странные эффекты при изменении размера.
  2. Несмотря на то, что изменение [x, y] в Component.onCompleted кажется логичным, оно не работает должным образом с двумя мониторами с разным DPI (как в системах, над которыми я сейчас работаю).
  3. Необходимо использовать Window.screen вместо Screen одноэлементного типа. Таким образом мы получим фактический экран, соответствующий окну.
  4. Чтобы полностью отвязать [x, y] от динамических значений, но фактического экрана окна в момент показа начального окна, мы теперь используем onScreenChanged, который является обработчиком изменения свойства screen.

Это решение является более полным и использует Window.screen свойство:

ApplicationWindow {
    id: window
    property bool screenInit: false

    title: qsTr("App Window Positioning")
    visible: true

    height: Theme.windowHeight // initial
    width: Theme.windowWidth   // initial

    Connections {
        target: window
        onScreenChanged: if (!screenInit) {
            // we have actual screen delivered here for the time when app starts
            screenInit = true
            window.x = screen.width / 2 - Theme.windowWidth / 2
            window.y = screen.height / 2 - Theme.windowHeight / 2
        }
    }
}

P.S. В таком случае я использовал тип ApplicationWindow, производный от Window, и он должен соответствовать поведению позиционирования Window.

person Alexander V    schedule 24.09.2018
comment
Я тестировал это с Qt 5.15 на macOS, но onScreenChanged не вызывается при первоначальном отображении окна. Только когда окно перемещается на другой экран. Может быть, когда-нибудь это изменится ... - person Ignitor; 08.01.2021

Ответ Александра почти достаточно хорош. Однако в KDE я наблюдаю следующее поведение: окно сначала открывается на Мониторе 1, а затем сразу перемещается на Монитор 2. В этой ситуации указанный ответ всегда переводит окно на Монитор 1.

Поскольку попытка обнаружить такое поведение, вероятно, потребует довольно много кода, я просто выбрал простое решение, используя таймер:

ApplicationWindow {
  id: window

  visible: true
  height: 320
  width: 480

  function setCoordinates() {
    x += screen.width / 2 - width / 2
    y += screen.height / 2 - height / 2
  }

  Timer {
    id: timer
    running: true
    repeat: false
    interval: 10
    onTriggered: {
      window.setCoordinates();
    }
  }
}

Это устанавливает координаты окна после ожидания в течение 10 мс (надеюсь, за это время DE выполнил свою работу).

person Oskar    schedule 28.12.2018

Все остальные ответы отсутствуют, чтобы учесть расположение экрана, что может привести к отображению окна не на том экране. Возможно, это работало в предыдущей версии Qt, но, похоже, больше не работает с последними версиями Qt.

Следующее решение работает для меня с многоэкранным режимом с другой настройкой DPI (требуется Qt 5.9 или новее; протестировано с Qt 5.15 на macOS):

import QtQuick 2.9
import QtQuick.Window 2.9

Window {
    id: root
    visible: true
    width: 320
    height: 480

    Component.onCompleted: {
        root.x = root.screen.virtualX + root.screen.width / 2 - root.width / 2;
        root.y = root.screen.virtualY + root.screen.height / 2 - root.height / 2;
    }
}
person Ignitor    schedule 08.01.2021