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

发布于 2024-10-26 06:29:50 字数 628 浏览 4 评论 0原文

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

我遇到的问题,并非所有问题都有正确的解决方案:

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

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

  3. 在显示之前,不可能知道 sizeHint 或 size 是否会出现错误。被应用,或介于两者之间的其他东西。也就是说,大小策略似乎不可预测。

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

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

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

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

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.

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.

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.

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).

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月下客 2024-11-02 06:29:50

编辑看起来更科学:我已将任意数量的调用更改为
processEvents 带有一个检查返回值的循环。

再次编辑:新版本似乎不安全:它可能会陷入循环。所以我对迭代次数设置了限制。

原文:
告诉我吧。如果允许我引用我自己的代码:

// 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) ;

尝试一下,对 processEvents 进行不同数量的调用。 (在这些调用中,各种子小部件和子子小部件递归地调整自身大小。)

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

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.)

小巷里的女流氓 2024-11-02 06:29:50

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

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);

我仅在 Windows XP 和 Qt 4.8.x 上测试了此代码。希望它也适用于其他平台。

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.

七度光 2024-11-02 06:29:50

您是否尝试过激活布局。 在此调用之后,它强制它计算

QLayout::activate() 的

大小和位置,您的小部件应该具有正确的大小。

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

QLayout::activate()

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文