Qt 窗口的尺寸

本文通过多个案例,详细说明关于Qt窗体尺寸的一些重要问题

默认尺寸

对于一个Qt的窗口(继承于QWidget),获取其窗体尺寸的方法size();

以一个Qt创建Qt Widgets Application项目的默认生成代码为基础,做如下测试

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    this->resize(1200,800);
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
}

第一个this->size()输出QSize(640, 480),即MainWindow具有默认的尺寸640*480

第二个this->size()输出QSize(1200, 800)

实际上,继承于QWidget的控件,例如QPushButton,QLineEdit等也会获得默认的尺寸640*480

    QWidget* page=new QWidget;
    qDebug()<<".."<<page->size();
    QPushButton* btn=new QPushButton;
    qDebug()<<".."<<btn->size();
    QLineEdit* edt=new QLineEdit;
    qDebug()<<".."<<edt->size();

以上输出都是QSize(640, 480)

布局之后的尺寸
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    this->resize(1200,800);
    QWidget* page=new QWidget;
    qDebug()<<".."<<page->size();
    QVBoxLayout* layout=new QVBoxLayout(page);
    QPushButton* btn=new QPushButton;
    qDebug()<<".."<<btn->size();
    QLineEdit* edt=new QLineEdit;
    qDebug()<<".."<<edt->size();

    layout->addWidget(btn);
    layout->addWidget(edt);

    this->setCentralWidget(page);

    qDebug()<<".."<<page->size();
    qDebug()<<".."<<btn->size();
    qDebug()<<".."<<edt->size();
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    //当界面显示出来之后,点击按钮查看控件尺寸
    connect(btn,&QPushButton::clicked,[=]{
        qDebug()<<".."<<page->size();
        qDebug()<<".."<<btn->size();
        qDebug()<<".."<<edt->size();
    });
}

以上代码this->setCentralWidget(page);之后的三个打印对应的尺寸应该是多少?

依然还是 QSize(640, 480)

而connect()方法中的三个打印对应的值则分别为

.. QSize(1200, 800)
.. QSize(1178, 28)
.. QSize(1178, 24)

以上代码说明两个问题:

(1)将控件加入到布局,然后放入了父窗体中,则控件的尺寸会根据父窗体的布局重新设置

(2)控件尺寸的重新设置发生在窗体显示出来后(绘制时)

 固定尺寸

 以下代码实现在主窗体上布局多个按钮和子窗体,实现点击按钮切换每个子窗体的隐藏和可见。

但是存在问题:

(1)4个子窗体平分了主窗体的尺寸;

(2)隐藏一个子窗体后,其他的子窗体尺寸被更改(窗体重绘时会重新设置尺寸)

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    this->resize(1200,800);

    QWidget* page=new QWidget;
    QVBoxLayout* layout=new QVBoxLayout(page);

    QScrollArea* contentArea=new QScrollArea;
    contentArea->setWidgetResizable(true);
    contentArea->setWidget(page);

    for(int i=0;i<4;i++)
    {
        QWidget* p=new QWidget;
        //设置窗体背景色,使得区分背景,可见
        p->setStyleSheet("background-color:green");
        QPushButton* b=new QPushButton;
        layout->addWidget(b);
        layout->addWidget(p);
        connect(b,&QPushButton::clicked,[p]{
            //点击按钮后窗体切换显示和隐藏效果
            p->setVisible(!p->isVisible());
        });
    }
    this->setCentralWidget(contentArea);
}

如果需要设置子窗体在重绘时不改变尺寸,那么需要设置其尺寸

例如在QWidget* p=new QWidget;下方增加 p->setFixedHeight(300);

这样隐藏和显示一个子窗体不会对任意其他的子窗体的尺寸造成影响。

更改后会发现,当隐藏完所有的子窗体后,所有的按钮被均匀布局在了主窗体,如果想要的效果是按钮从主窗体从上往下紧密排列,可以在layout添加完所有的控件和窗口后,添加一个stretch,即在this->setCentralWidget(contentArea);上一行添加layout->addStretch();

窗体实际尺寸

如果MainWindow设置的高度为600,而它的中心窗体高度为800,该怎样显示?

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    this->resize(800,600);
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    //默认情况下MainWindow没有centralWidget
    QWidget* center=new QWidget;
    qDebug()<<"center:"<<center->size();
    QVBoxLayout* layout=new QVBoxLayout(center);
    QWidget* page1=new QWidget;
    page1->setStyleSheet("background-color:green");
    page1->setFixedHeight(400);
    QWidget* page2=new QWidget;
    page2->setFixedHeight(400);
    page2->setStyleSheet("background-color:yellow");
    layout->addWidget(page1);
    layout->addWidget(page2);
    qDebug()<<"center:"<<center->size();
    this->setCentralWidget(center);
    //此时输出QSize(800, 600)
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    qDebug()<<"w size:"<<w.size();
    return a.exec();
}

以上代码执行时,MainWindow构造函数中的输出mainwindow的窗体高度为600,但是在窗口显示(执行了w.show())之后,它的高度却是829

给窗体设置某个尺寸,实际显示的时候窗体根据布局,不一定恰好按照给定的尺寸来显示

尺寸不够引起重叠的窗体

如果主窗体设置了固定高度600,而它的中心窗体设置固定高度1200?

此时,肯定主窗体显示不全page1和page2

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    this->resize(800,600);
    this->setFixedHeight(600);
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    //默认情况下MainWindow没有centralWidget
    QWidget* center=new QWidget;
    center->resize(800,500);
    qDebug()<<"center:"<<center->size();
    QVBoxLayout* layout=new QVBoxLayout(center);
    QWidget* page1=new QWidget;
    page1->setStyleSheet("background-color:green");
    page1->setFixedHeight(600);
    QWidget* page2=new QWidget;
    page2->setFixedHeight(600);
    page2->setStyleSheet("background-color:yellow");
    layout->addWidget(page1);
    layout->addWidget(page2);
    qDebug()<<"center:"<<center->size();
    this->setCentralWidget(center);
    //此时输出QSize(800, 600)
    qDebug()<<"MainWindow::MainWindow:"<<this->size();
    QTimer::singleShot(1000,[=](){
        //为什么page1和page2的高度是600,而实际显示的界面没有600?
        //事实上page1和page2的高度都是600,界面上也是600,但是page1和page2重叠了一部分
        qDebug()<<"page1:"<<page1->size();
        qDebug()<<"page2:"<<page2->size();
        qDebug()<<"center:"<<center->size();
        qDebug()<<"sizeHint:"<<layout->sizeHint();
        qDebug()<<"MainWindow::MainWindow:"<<this->size();
    });
}

这里输出了layout的sizeHit(),为1229,layout上放置了page1和page2,他们的高度600+600=1200,29是布局周边留下的空白部分。

最小高度限制

这里展示了一个实际项目中遇到的问题,需要在一个页面中放置多个表格,并且每个表格要直接显示至少5行,更多行的时候滚动条显示。

以下代码是从项目中抽取的问题特征部分:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(800,600);
    QWidget* page=new QWidget;
    QVBoxLayout* layout=new QVBoxLayout(page);

    QScrollArea* contentArea=new QScrollArea;
    contentArea->setWidgetResizable(true);
    contentArea->setWidget(page);

    for(int i=0;i<4;i++)
    {
        TableWidget* p=new TableWidget;
        QPushButton* b=new QPushButton;
        layout->addWidget(b);
        layout->addWidget(p);
        connect(b,&QPushButton::clicked,[p]{
            //点击按钮后窗体切换显示和隐藏效果
            p->setVisible(!p->isVisible());
            qDebug()<<"p size:"<<p->size();
        });
    }
    layout->addStretch();
    this->setCentralWidget(contentArea);
}

 TableWidget只是一个平凡的QTableWidget实例,它设置了默认表格有6行8列,

TableWidget::TableWidget()
{
    this->setRowCount(6);
    this->setColumnCount(8);
}

上述代码的效果:

目前的问题是每个表格高度都被挤压了,只显示了一行。

一种解决问题的思路是,在表格初始化时,设置最小高度限制:

TableWidget::TableWidget()
{
    this->setMinimumHeight(250);
    this->setRowCount(6);
    this->setColumnCount(8);
}

 一个更复杂的示例

以下是一个更复杂一些的示例,这个示例有助于理解Qt在布局控件的过程中对尺寸的更改。

代码目的是在主界面上加载多个Drawer页面,Drawer页面是一种类似抽屉的盒子,可以打开关闭(显示隐藏)

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(800,600);
    QWidget* page=new QWidget;
    page->setMinimumHeight(1000);
    //layout用来装载drawer
    QVBoxLayout* layout=new QVBoxLayout(page);
    Drawer* d1=new Drawer;
    Drawer* d2=new Drawer;
    Drawer* d3=new Drawer;
    Drawer* d4=new Drawer;
    QList<Drawer*> drawers{d1,d2,d3,d4};
    for(int i=0;i<1;i++)
    {
        QVBoxLayout* lay=new QVBoxLayout;
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addStretch();
        drawers.at(i)->setContentLayout(lay);
    }

    for(int i=1;i<4;i++)
    {
        QVBoxLayout* lay=new QVBoxLayout;
        lay->addWidget(new TableWidget);
        drawers.at(i)->setContentLayout(lay);
    }


    //以下的stretch使得drawer可以往页面上面顶
    for(int i=0;i<4;i++)
        layout->addWidget(drawers.at(i));

    layout->addStretch();


    QScrollArea* contentArea=new QScrollArea;
    contentArea->setWidgetResizable(true);
    contentArea->setWidget(page);

    this->setCentralWidget(contentArea);


    QTimer::singleShot(1000,[=](){
        qDebug()<<"MainWindow::MainWindow:"<<this->size()<<","<<this->sizeHint();
        qDebug()<<"d2:size:"<<d2->size()<<","<<d2->sizeHint();
    });

}

 Drawer提供一个按钮,用于交互显示隐藏页面,和一个接口用于设置页面显示的内容(设置一个布局)

Drawer::Drawer(QWidget *parent)
    : QWidget{parent}
{
    QVBoxLayout* layout=new QVBoxLayout;
    layout->addSpacing(0);
    layout->setContentsMargins(0,0,0,0);
    QToolButton* btn=new QToolButton;
    layout->addWidget(btn);
    area=new QScrollArea;
    area->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    layout->addWidget(area);
    this->setLayout(layout);
    connect(btn,&QToolButton::clicked,[=]{
        area->setVisible(!area->isVisible());
        qDebug()<<"drawer size:"<<this->size()<<this->minimumHeight();
//        if(!area->isVisible())
//        {
//            this->setFixedHeight(30);
//        }
//        else
//        {
//            this->setFixedHeight(minHeight);
//        }
    });
}

void Drawer::setContentLayout(QLayout *lay)
{
    area->setLayout(lay);
//    minHeight=this->minimumHeight();
}

 其中TableWidget依然是QTableWidget的简单实例

TableWidget::TableWidget()
{
    this->setRowCount(6);
    this->setColumnCount(8);
}

以上代码的效果如下:

存在的问题是:

(1)表格默认只展示了两行,

(2)并且关闭了一个Drawer后,其他Drawer的尺寸会发生变化

其中,前面对(2)问题的处理是设置固定的尺寸p->setFixedHeight(300);

对应这里就是在Drawer的构造函数第一行加 this->setFixedHeight(300);但是这样一来,会发现每个Drawer之间重叠了,就是尺寸不够引起了窗体重叠,300*400=1200>1000,主窗体中的滚动区域的窗体设置的最小高度1000.

另外隐藏所有的Drawer页面后,剩余的按钮又均匀分布在了主界面。

这里的效果和前面固定尺寸一节遇到的问题看似相同,而实际上却不一样,前面的问题通过在布局的最后增加stretch解决,这里显然不能。

这里遇到的问题是由于按钮点击后隐藏的不是整个Drawer,而只是Drawer中的area,Drawer依然是可见的,因此处于整个主界面的布局之中。这里当Drawer中的area被隐藏后,Drawer页面本身被重新布局了,即只有一个QToolButton参与了布局,所以能看到按钮被布局在了Drawer的中央。

那么,这种情况下该怎样实现效果:

(1)隐藏所有的Drawer的area后,只剩下按钮顶格显示在主页面

(2)表格默认显示至少5行

(3)隐藏一个Drawer不会对其他的Drawer尺寸产生影响

一种方式是要在Drawer显示隐藏切换的时候同时设置固定的尺寸;这个固定的尺寸要使得表格至少显示5行

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(800,600);
    QWidget* page=new QWidget;
    //给page设置了最小高度后,每个drawer的高度会高一些
    page->setMinimumHeight(1200);
    //layout用来装载drawer
    QVBoxLayout* layout=new QVBoxLayout(page);
    Drawer* d1=new Drawer;
    Drawer* d2=new Drawer;
    Drawer* d3=new Drawer;
    Drawer* d4=new Drawer;
    QList<Drawer*> drawers{d1,d2,d3,d4};
    for(int i=0;i<1;i++)
    {
        QVBoxLayout* lay=new QVBoxLayout;
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addWidget(new QLineEdit);
        lay->addStretch();
        //需要提前设置Drawer的最小高度
        drawers.at(i)->setMinimumHeight(200);
        drawers.at(i)->setContentLayout(lay);
    }

    for(int i=1;i<4;i++)
    {
        QVBoxLayout* lay=new QVBoxLayout;
        lay->addWidget(new TableWidget);
        //需要提前设置Drawer的最小高度
        drawers.at(i)->setMinimumHeight(300);
        drawers.at(i)->setContentLayout(lay);
    }


    //以下的stretch使得drawer可以往页面上面顶
    for(int i=0;i<4;i++)
        layout->addWidget(drawers.at(i));

    layout->addStretch();


    QScrollArea* contentArea=new QScrollArea;
    contentArea->setWidgetResizable(true);
    contentArea->setWidget(page);

    this->setCentralWidget(contentArea);


    QTimer::singleShot(1000,[=](){
        qDebug()<<"MainWindow::MainWindow:"<<this->size()<<","<<this->sizeHint();
        qDebug()<<"d2:size:"<<d2->size()<<","<<d2->sizeHint();
    });

}
TableWidget::TableWidget()
{
    this->setRowCount(6);
    this->setColumnCount(8);
}
Drawer::Drawer(QWidget *parent)
    : QWidget{parent}
{
    QVBoxLayout* layout=new QVBoxLayout;
    layout->addSpacing(0);
    layout->setContentsMargins(0,0,0,0);
    QToolButton* btn=new QToolButton;
    layout->addWidget(btn);
    area=new QScrollArea;
    area->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    layout->addWidget(area);
    this->setLayout(layout);
    connect(btn,&QToolButton::clicked,[=]{
        area->setVisible(!area->isVisible());
        qDebug()<<"drawer size:"<<this->size()<<this->minimumHeight();
        //这里根据area显示和隐藏的状态动态调整整个drawer的高度
        if(!area->isVisible())
        {
            this->setFixedHeight(30);
        }
        else
        {
            this->setFixedHeight(minHeight);
        }
    });
}

void Drawer::setContentLayout(QLayout *lay)
{
    area->setLayout(lay);
    //这里将预设的最小高度记录下来,用于在area显示隐藏切换时设置drawer的高度
    minHeight=this->minimumHeight();
}

以上代码的效果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式是指将计算机系统嵌入到其他设备或机器中,以完成特定的功能。而Qt界面是一种跨平台的GUI开发工具,可以轻松地创建各种界面和用户交互。因此,使用Qt界面进行嵌入式开发具有以下几个优点。 首先,Qt界面支持多种平台,包括Windows、Linux、Android等,这使得嵌入式设备可以在不同的操作系统中运行。无论是搭载嵌入式Linux系统的智能家居设备,还是运行Android系统的智能手机,都可以使用Qt界面进行开发,并在不同平台上进行部署。 其次,Qt界面提供了丰富的界面控件和布局管理器,可以轻松地创建出美观、易于操作的界面。无论是在小屏幕的智能手表上显示数据,还是在大屏幕的车载导航系统上显示地图,Qt界面都可以根据设备的尺寸和分辨率进行自适应布局,使用户获得良好的使用体验。 第三,Qt界面具有良好的显示性能和响应速度,适合于嵌入式设备的资源有限的情况。通过使用Qt界面,可以有效地管理和优化嵌入式系统的内存和处理器资源,使界面显示流畅,并快速响应用户的操作。 最后,Qt界面还提供了丰富的扩展功能和接口,可以方便地与嵌入式设备的其他功能进行集成。比如,可以通过Qt界面来控制硬件设备的输入输出、读取传感器数据、与网络进行通信等,从而实现更加丰富的嵌入式应用。 综上所述,使用Qt界面进行嵌入式开发可以极大地简化开发过程,提高开发效率,并为嵌入式设备提供更加友好和可靠的界面。无论是在智能家居、车载导航、医疗设备等领域,Qt界面都能发挥重要作用,实现功能的完善和用户体验的优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值