2011-03-24 110 views
5

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

我遇到的,并不是所有的问题都妥善解决:

  1. frameGeometry并不总是填充窗口之前已经上映之前。

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

  3. ,以显示它是不可能知道sizeHint或大小是否将被应用,或者两者之间的其他东西之前。也就是说,尺寸政策并不可预测。

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

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

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

有没有人有可行的解决方案?

+0

看到我最新的编辑。第一次编辑是不安全的。 – TonyK 2011-03-25 07:35:43

回答

6

编辑看起来更科学:我已经改变通话的任意数量 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。 (在这些调用中,各种子小部件和子子小部件本身递归地大小。)

+0

谢谢,我之前没有真正注意到“DontShowOnScreen”属性。从我看过的代码和Qt缺陷报告中,我知道为什么必须调用processEvents:有一个懒惰的大小评估,生成大小的代码仅在响应某些事件(如show和resize)时被调用。我查看了代码,尽管调整函数确实存在,但没有*可能性直接调用它们。 – 2011-03-24 11:18:34

+0

所以试试这个。 – TonyK 2011-03-24 12:41:44

+0

是的,我肯定会实现并尝试第一点:定位代码的其余部分与我现在的大致相同。 – 2011-03-24 13:00:24

-1

您是否尝试过激活布局。它迫使它来计算尺寸和这个电话后定位

QLayout ::激活()

,你的部件应该有自己正确的尺寸。

+2

我有,它没有帮助。 – 2011-08-27 07:30:28

1

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

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.希望它也可以在其他平台上运行。

+0

当我这样做时,我的日志会被警告垃圾邮件:WindowsWindow :: setGeometryDp:无法设置几何图形450x394 + -50000 + -50000 – RvdK 2015-07-24 13:59:22

+0

尝试更小或更好的东西,将其移动到正在运行的计算机的可见区域外,以确保它适用于任何显示器配置。 – 2015-07-24 18:12:53

+0

我最终使用了这个解决方案:http://stackoverflow.com/a/16690448/47351 – RvdK 2015-07-26 13:10:37