如何像 Skype 一样将 QDialog 粘贴到屏幕边框?
Posted
技术标签:
【中文标题】如何像 Skype 一样将 QDialog 粘贴到屏幕边框?【英文标题】:HowTo stick QDialog to Screen Borders like Skype do? 【发布时间】:2010-04-26 11:10:45 【问题描述】:很久以前,我试图找到方法如何将 QDialog 窗口粘贴到我的小项目(如 Skype 窗口)的屏幕边框上,但我失败了。可能是我没有在正确的位置查看此代码,所以现在我正在这里寻找解决方案,在堆栈上! :)
那么,是否有人处理过某种类型的代码、链接、示例?
在我看来,我们必须重新实现 QDialog moveEvent 函数,如下所示,但该代码不起作用:
void CDialog::moveEvent(QMoveEvent * event)
QRect wndRect;
int leftTaskbar = 0, rightTaskbar = 0, topTaskbar = 0, bottomTaskbar = 0;
// int top = 0, left = 0, right = 0, bottom = 0;
wndRect = this->frameGeometry();
// Screen resolution
int screenWidth = QApplication::desktop()->width();
int screenHeight = QApplication::desktop()->height();
int wndWidth = wndRect.right() - wndRect.left();
int wndHeight = wndRect.bottom() - wndRect.top();
int posX = event->pos().x();
int posY = event->pos().y();
// Snap to screen border
// Left border
if (posX >= -m_nXOffset + leftTaskbar &&
posX <= leftTaskbar + m_nXOffset)
//left = leftTaskbar;
this->move(leftTaskbar, posY);
return;
// Top border
if (posY >= -m_nYOffset &&
posY <= topTaskbar + m_nYOffset)
//top = topTaskbar;
this->move(posX, topTaskbar);
return;
// Right border
if (posX + wndWidth <= screenWidth - rightTaskbar + m_nXOffset &&
posX + wndWidth >= screenWidth - rightTaskbar - m_nXOffset)
//right = screenWidth - rightTaskbar - wndWidth;
this->move(screenWidth - rightTaskbar - wndWidth, posY);
return;
// Bottom border
if (posY + wndHeight <= screenHeight - bottomTaskbar + m_nYOffset &&
posY + wndHeight >= screenHeight - bottomTaskbar - m_nYOffset)
//bottom = screenHeight - bottomTaskbar - wndHeight;
this->move(posX, screenHeight - bottomTaskbar - wndHeight);
return;
QDialog::moveEvent(event);
谢谢。
【问题讨论】:
【参考方案1】:如您所想,您可以在 moveEvent 函数中实现这一点。 我想下面的代码可以解决问题,但是由于我在这里没有什么要测试的,所以我将编写一些伪代码:
首先获取可用的屏幕区域:
const QRect screen = QApplication::availableGeometry(this);
// This get the screen rect where you can drag a dialog
然后获取对话框相对于桌面的位置(如果您的对话框是其他小部件的子级,则需要将小部件相对于桌面的坐标转换为相对于桌面的坐标):
const QRect dialog = geometry();
// Do here transformation
现在测试对话框是否靠近屏幕边框
if( abs(dialog.left()-screen.left() < OFFSET )
move(screen.left(), dialog.top();
else if( abs(dialog.top()-screen.top() < OFFSET )
move(dialog.left(), screen.top() )
// etc. for the 2 other cases
让我知道它是否有效
【讨论】:
@Patrice Bernassola:感谢您的回复。我认为,我必须更新我的示例,因为它更适合测试/编辑......因为我是一个长期的 linux 用户,在 KDE 中有一个针对这种情况的全局解决方案:所有窗口/对话框都可以粘贴到 Windows 边框,所以查看 KDE 源代码可能是个好主意...【参考方案2】:在QWidget
文档中的pos
属性description 中,有以下关于在移动事件处理方法中移动窗口的警告。
警告:在
moveEvent()
内调用move()
或setGeometry()
可以 导致无限递归。
也就是说,没有合适的方法将对话框窗口粘贴在屏幕边框内。
注意: 您在 KDE 中观察到的行为来自窗口管理器。实际上,窗口管理器是安排应用程序窗口(如对话框)以在屏幕上显示它们的一种。 KDE 窗口管理器有一个选项可以使所有应用程序窗口(称为客户端)粘在边框上。
【讨论】:
感谢您的回复。明天我会尝试你的解决方案,但在原始帖子中有一个代码...... 实际上不起作用的代码...我能够恢复小部件的位置,以便它可以粘在屏幕边框上。但在某些极端情况下,事件处理开始无限循环。我可以恢复代码,但你现在应该知道它在某些情况下不起作用。 是的,我检查过了,它只适用于顶部边框,而不适用于其他边框。这很可悲,但这意味着我们正在以正确的方式解决这个问题......以上是关于如何像 Skype 一样将 QDialog 粘贴到屏幕边框?的主要内容,如果未能解决你的问题,请参考以下文章
Delphi:如何创建像 Skype 一样的 Windows 自动启动应用程序?
如何在聊天中回复特定消息,就像使用 html css javascript/jquery 的 skype/whatsapp