如何在桌面上弹跳 QWidget
我正在尝试在屏幕上弹起 QWidget。这是我尝试过的代码。
class Window : public QMainWindow {
public:
void moveEvent(QMoveEvent* aEvent) override;
};
void Window::moveEvent(QMoveEvent* aEvent) {
QSizeF screenSize = QGuiApplication::primaryScreen()->screenSize();
QRect oldRect = this->geometry();
QRect newRect = oldRect;
QPoint offset;
if (newRect.left() == 0) {
offset.setX(1);
}
else if (newRect.right() == screenSize.width()) {
offset.setX(-1);
}
if (newRect.top() == 0) {
offset.setX(1);
}
else if (newRect.bottom() == screenSize.height()) {
offset.setX(-1);
}
newRect.setTopLeft(newRect.topLeft() + offset);
newRect.setBottomRight(newRect.bottomRight() + offset);
QTimer::singleShot(1, [this, newRect]() {
setGeometry(newRect);
});
}
int main(int argc, char** argv) {
QApplication app{argc, argv};
Window* w = new Window();
w->show();
w->setGeometry(w->geometry());
return app.exec();
}
然而,窗口并没有在屏幕上移动,而是在原地有些抖动。当我用鼠标移动窗口并放开时。它在桌面上偶尔移动,这也不是我想要的。
有谁知道这是否可能?如果是这样,有人知道这样做的正确方法吗?
I am trying to bounce a QWidget around the screen. This is the code i tried.
class Window : public QMainWindow {
public:
void moveEvent(QMoveEvent* aEvent) override;
};
void Window::moveEvent(QMoveEvent* aEvent) {
QSizeF screenSize = QGuiApplication::primaryScreen()->screenSize();
QRect oldRect = this->geometry();
QRect newRect = oldRect;
QPoint offset;
if (newRect.left() == 0) {
offset.setX(1);
}
else if (newRect.right() == screenSize.width()) {
offset.setX(-1);
}
if (newRect.top() == 0) {
offset.setX(1);
}
else if (newRect.bottom() == screenSize.height()) {
offset.setX(-1);
}
newRect.setTopLeft(newRect.topLeft() + offset);
newRect.setBottomRight(newRect.bottomRight() + offset);
QTimer::singleShot(1, [this, newRect]() {
setGeometry(newRect);
});
}
int main(int argc, char** argv) {
QApplication app{argc, argv};
Window* w = new Window();
w->show();
w->setGeometry(w->geometry());
return app.exec();
}
However, the window does not move around the screen, but somewhat jitters in place. When i move the window with the mouse and let go. It moves sporadically around the desktop, which is also not what i want.
Does anyone know if this is possible? If so, does anyone know the right way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
发布的代码存在几个问题,包括:
Window 类没有任何成员变量来跟踪其当前的运动方向。如果不保持该状态,就不可能正确计算沿该运动方向的下一个位置。
从
moveEvent()
内部驱动动画有点棘手,因为moveEvent()
被调用以响应setGeometry()
以及响应用户实际用鼠标移动窗口;这使得意外的反馈循环成为可能,从而导致意外的行为。代码假定屏幕的可用表面积从
(0,0)
开始,到(screenSize.width(),screenSize.height())
结束,这不一定是一个有效的假设。屏幕的实际可用区域是由availableGeometry()
给出的矩形。当调用
setGeometry()
时,您正在设置Qt程序实际可以绘制到的窗口区域的新位置。然而,这只是窗口所占据的实际屏幕区域的 99% 子集,因为窗口还包括非 Qt 控制的区域,如标题栏和窗口边框。这些部分也需要适合availableGeometry()
,否则窗口将无法完全定位在您想要的位置,这可能会导致异常(例如窗口“卡”在屏幕顶部边缘)无论如何,这是我重写代码以实现更接近正确的“弹跳窗口”的尝试。请注意,如果您尝试用鼠标拖动窗口,而窗口也尝试自行移动,则仍然会出现一些问题;理想情况下,Qt 程序可以检测标题栏上的鼠标按下事件,并使用它来禁用其自动画,直到相应的鼠标向上事件发生之后,但 AFAICT 如果不诉诸操作系统特定的黑客技术,这是不可能的,因为窗口标题栏拖动是由操作系统处理的,而不是由 Qt 处理的。因此,我在这里不执行该逻辑。
There are several problems with the posted code, including:
The
Window
class doesn't have any member-variable to keep track of its current direction of motion. Without keeping that state, it's impossible to correctly calculate the next position along that direction of motion.Driving the animation from within
moveEvent()
is a bit tricky, sincemoveEvent()
gets called in response tosetGeometry()
as well as in response to the user actually moving the window with the mouse; that makes unexpected feedback loops possible, resulting in unexpected behavior.The code assumes that the screen's usable surface area starts at
(0,0)
and ends at(screenSize.width(),screenSize.height())
, which isn't necessarily a valid assumption. The actual usable area of the screen is a rectangle given byavailableGeometry()
.When calling
setGeometry()
, you are setting the new location of the area of the window that the Qt program can actually draw into. However that's only a 99% subset of the actual on-screen area taken up by the window, because the window also includes the non-Qt-controlled regions like the title bar and the window-borders. Those parts need to fit into theavailableGeometry()
also, otherwise the window won't be positioned quite where you wanted it to be, which can lead to anomalies (like the window getting "stuck" on the top-edge of the screen)In any case, here's my attempt at rewriting the code to implement a closer-to-correct "bouncing window". Note that it's still a bit glitchy if you try to mouse-drag the window around while the window is also trying to move itself around; ideally the Qt program could detect the mouse-down-event on the title bar and use that to disable its self-animation until after the corresponding mouse-up-event occurs, but AFAICT that isn't possible without resorting to OS-specific hackery, because the window-title-bar-dragging is handled by the OS, not by Qt. Therefore, I'm leaving that logic unimplemented here.