我该怎么做:我想在中央屏幕上显示我的主窗口。
6 回答
如果使用 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
}
}
Dielson 的回答要好得多,特别是因为没有提到小部件......无论如何,这是他回答的一个更简单的版本:
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
}
正如 Alexander 所提到的,这种绑定可能会导致奇怪的调整大小行为。因此,最好使用 Dielson 的答案。我唯一要提到的是,在 QML 中使用 setter 并不常见。例如,某些系统(我相信它们被称为属性拦截器)甚至依赖于设置的属性来执行动画。所以比较常见的做法如下:
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
}
}
在检查了两个回复并使用 Qt 5.9.1 实际调试代码后,它显示原始回复存在多个问题:
- 除非我们想看到调整大小的奇怪效果,否则无法将 [x, y] 绑定到 [width, height]。
- 尽管 [x, y] 的变化
Component.onCompleted
似乎是合乎逻辑的,但对于 2 个不同 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
}
}
}
PS 如果是这样,我使用ApplicationWindow
了派生自的类型,Window
它应该与Window
定位行为一致。
在显示它之前,您需要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);
}
从那里提出一个通用版本来计算用户的中心屏幕(如果存在)应该相当简单。
亚历山大的回答几乎已经足够好了。但是,在 KDE 上,我观察到以下行为:窗口首先在监视器 1 上打开,然后立即移动到监视器 2。在这种情况下,引用的答案总是强制窗口到监视器 1。
由于尝试检测这种行为可能需要相当多的代码,我只是通过使用 Timer 找到了一个简单的解决方案:
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 或更高版本;在 macOS 上使用 Qt 5.15 测试):
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;
}
}