Как я могу сделать следующее: я хочу, чтобы при запуске мое главное окно отображалось на центральном экране.
QML - позиция главного окна при запуске (центр экрана)
Ответы (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);
}
Оттуда должно быть достаточно просто придумать универсальную версию, которая будет работать с центральным экраном пользователя (если он существует).
При использовании 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
}
}
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
}
}
ApplicationWindow
есть свойство screen
.
- person Tomilov Anatoliy; 08.05.2018
screen
для Window
. doc.qt.io/qt-5/ qml-qtquick-window-window.html # screen-prop
- person Alexander V; 22.09.2018
После изучения обоих ответов и фактической отладки кода с помощью Qt 5.9.1 он показывает более одной проблемы с исходными ответами:
- Невозможно привязать [x, y] к [width, height], если мы не хотим видеть странные эффекты при изменении размера.
- Несмотря на то, что изменение [x, y] в
Component.onCompleted
кажется логичным, оно не работает должным образом с двумя мониторами с разным DPI (как в системах, над которыми я сейчас работаю). - Необходимо использовать
Window.screen
вместоScreen
одноэлементного типа. Таким образом мы получим фактический экран, соответствующий окну. - Чтобы полностью отвязать [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
.
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 выполнил свою работу).
Все остальные ответы отсутствуют, чтобы учесть расположение экрана, что может привести к отображению окна не на том экране. Возможно, это работало в предыдущей версии 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;
}
}