前言

在进行Qt程序开发时,想在不同的地方获取主窗体QMainWindowgeometry或者frameGeometry属性。

解决方案

  1. 将主窗体设计为单例;
  2. 将主窗体指针设置到需要用到主窗体的geometry属性的对象里;
  3. 声明一个全局静态类型,当主窗体位置或者尺寸发生变化时,用于获取主窗体的geometry属性。

第一个更好实现些,创建主窗体类时,直接设计为单例,在需要的地方调用即可;
第二种显得比较冗余,不好管理对象;
第三种实现更灵活,调用也方便。

问题分析

根据QMainWindow帮助手册可知,当窗体尺寸改变时,会触发resizeEvent()事件,但是如果只在resizeEvent()事件里,获取geometry或者frameGeometry属性,当窗体初始化显示、最大化、最小化和移动位置时,获取的geometry信息是错误的。

  • 初次加载时,如下代码所示:
void MainWindow::resizeEvent(QResizeEvent *e)
{
    qDebug().noquote() << this->geometry();
    QMainWindow::resizeEvent(e);
}

初次启动程序,结果如下:

Qt 获取主窗体QMainWindow的geometry_qt


但整个窗体显示一般会在屏幕中央区域,所以说得到的geometry的信息是错误的。

  • 最大化时,输出信息:
  • Qt 获取主窗体QMainWindow的geometry_qt_02

  • 很明显也不对,因为最大化,x()y()应该是(0, 0);反之,双击还原窗体尺寸,得到的geometry也是不对的。
  • 移动位置,没有打印,因为移动位置,尺寸没变化,所以不会进入resizeEvent()事件。

继续翻阅文档,发现还有changeEvent(QEvent *e)moveEvent(QMoveEvent *e)事件,当窗体改变或者移动时触发以上两个事件。
将以上三个事件结合,得到的geometry或者frameGeometry属性就是正确的。

具体示例代码

void MainWindow::resizeEvent(QResizeEvent *e)
{
    qDebug().noquote() << this->frameGeometry();
    s_frameGeometry = this->frameGeometry();
    QMainWindow::resizeEvent(e);
}

void MainWindow::changeEvent(QEvent *e)
{
    qDebug().noquote()<< this->frameGeometry();
    s_frameGeometry = this->frameGeometry();
    QMainWindow::changeEvent(e);
}

void MainWindow::moveEvent(QMoveEvent *e)
{
    qDebug().noquote()<< this->frameGeometry();
    s_frameGeometry = this->frameGeometry();
    QMainWindow::moveEvent(e);
}

当使用时,在调用的地方调用全部变量frameGeometry即可

启动程序,输出信息如下:

Qt 获取主窗体QMainWindow的geometry_解决方案_03