windows Qt 在屏幕上正确放置新窗口,鼠标居中,移入屏幕

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5417201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:29:51  来源:igfitidea点击:

Qt place new window correctly on screen, center over mouse, move into screen

c++windowsqtgnomekde

提问by edA-qa mort-ora-y

After many months of trying, searching, reviewing code, etc. I'm unable to find a solution to properly positioning a new window in QT. In my most basic case I simply want to get the final size of the window and center it under the mouse. It will be shifted to ensure that no part of the window is outside of the screen. I do not wish to have the window appear then move into position, that produces visual jarring, particularly with desktop FX turned on.

经过数月的尝试、搜索、代码等,我无法找到在 QT 中正确定位新窗口的解决方案。在我最基本的情况下,我只想获得窗口的最终大小并将其居中放置在鼠标下方。它将被移动以确保窗口的任何部分都不在屏幕之外。我不希望窗口出现然后移动到位,这会产生视觉冲击,尤其是在打开桌面 FX 的情况下。

The problems I've encountered, not all of which have proper solutions:

我遇到的问题,并不是所有的问题都有合适的解决方案:

  1. frameGeometry is not always populated before the window has been shown before.

  2. frameGeometry is sometimes just completely wrong, in particular on Windows 7.

  3. Prior to display it is not possible to know whether sizeHint or size will be applied, or something else in between. That is, the size policy does not appear predictable.

  1. frameGeometry 在之前显示窗口之前并不总是填充。

  2. frameGeometry 有时完全错误,尤其是在 Windows 7 上。

  3. 在显示之前,不可能知道是否会应用 sizeHint 或 size ,或者介于两者之间。也就是说,规模政策似乎不可预测。

Note that I know how to save/restore geometry of a previously created window. Despite QT defects here as well I have a working solution.

请注意,我知道如何保存/恢复以前创建的窗口的几何图形。尽管这里也有 QT 缺陷,但我有一个可行的解决方案。

Also note that I cannot use the window manager default placement. For non-MDI apps on a multi-monitor setup their placement is terrible (often not even being on the same monitor as the mouse).

另请注意,我无法使用窗口管理器的默认位置。对于多显示器设置上的非 MDI 应用程序,它们的位置很糟糕(通常甚至与鼠标不在同一显示器上)。

I'd also like to avoid sub-classing all widgets and dialogs just to implement the solution, as it would not be generic. If this is the only possible way then I'd be willing to consider it (should event filters also not be an option).

我还想避免为了实现解决方案而对所有小部件和对话框进行子类化,因为它不是通用的。如果这是唯一可能的方法,那么我愿意考虑它(如果事件过滤器也不是一种选择)。

Does anybody have good workable solutions?

有人有好的可行的解决方案吗?

回答by TonyK

Editedto look more scientific: I have changed the arbitrary number of calls to processEventswith a loop that checks the return value.

编辑为看起来更科学:我已经processEvents使用检查返回值的循环更改了任意数量的调用 。

Edited again:It seems that the new version is not safe: it can get stuck in the loop. So I've put a limit in the number of iterations.

再次编辑:似乎新版本不安全:它可能会卡在循环中。所以我限制了迭代次数。

Original:
Tell me about it. If I may be permitted to quote from my own code:

原文:
说说看。如果允许我引用我自己的代码:

// BIG PAIN: We want to get the dialog box to caluclate its own size. But there is
// no simple way to do this. The following seems to work, but only if processEvents
// is called at least twice. God knows why:
setAttribute (Qt::WA_DontShowOnScreen, true) ; // Prevent screen flicker
show() ;

QEventLoop EventLoop (this) ;
for (int i = 0 ; i < 10 ; i++)
  if (!EventLoop.processEvents()) break ;

hide() ;
setAttribute (Qt::WA_DontShowOnScreen, false) ;

int x = 99 ; // whatever
int y = 99 ; // whatever

// Make sure it fits on the screen
QRect ScreenRect = qApp -> desktop() -> availableGeometry (ApplicationData -> mainWindow) ;

if (x + frameGeometry().width() > ScreenRect.right())
  x = ScreenRect.right() - frameGeometry().width() ;
if (x < ScreenRect.x()) x = ScreenRect.x() ;

if (y + frameGeometry().height() > ScreenRect.bottom())
  y = ScreenRect.bottom() - frameGeometry().height() ;
if (y < ScreenRect.y()) y = ScreenRect.y() ;

move (x, y) ;

Try this, with varying numbers of calls to processEvents. (In these calls, the various sub-widgets and sub-sub-widgets size themselves recursively.)

试试这个,调用不同数量的processEvents. (在这些调用中,各种子小部件和子子小部件以递归方式调整自己的大小。)

回答by Daniel Hedberg

Regarding the problem of not being able to query a window for its size before its been shown, there is a simple workaround. You can move the window to somewhere far outside the screen before showing it. For instance to center a main window on the primary screen without flickering I do the following:

关于在显示之前无法查询窗口大小的问题,有一个简单的解决方法。您可以在显示之前将窗口移动到屏幕之外的某个位置。例如,为了使主窗口在主屏幕上居中而不闪烁,我执行以下操作:

MainWindow mainWindow;
QRect primaryScreenGeometry(QApplication::desktop()->screenGeometry());
mainWindow.move(-50000,-50000);
mainWindow.show();
mainWindow.move((primaryScreenGeometry.width() - mainWindow.width()) / 2.0,
                (primaryScreenGeometry.height() - mainWindow.height()) / 2.0);

I've only tested this code on Windows XP and Qt 4.8.x. Hopefully it works on other platforms as well.

我只在 Windows XP 和 Qt 4.8.x 上测试过这段代码。希望它也适用于其他平台。

回答by Konstantinos Gaitanis

Have you tried activating the layout. It forces it to calculate sizes and positions

您是否尝试过激活布局。它迫使它计算大小和位置

QLayout::activate()

QLayout::activate()

after this call, your widgets should have their correct size.

在此调用之后,您的小部件应该具有正确的大小。