在窗体中摆放窗口部件

一共有三种基本方法用于管理窗体上子窗口部件的布局:绝对位置法、人工布局法和布局管理器法。

绝对位置法

绝对位置法是一种最原始的摆放窗口部件的方法。这可以通过对窗体的各个子窗口部件分配固定的大小和位置以及对窗体分配固定的大小实现。

FindFileDialog.h

#ifndef FINDFILEDIALOG_H
#define FINDFILEDIALOG_H#include <QDialog>class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTableWidget;class FindFileDialog : public QDialog
{Q_OBJECTpublic:FindFileDialog(QWidget *parent = 0);private:QLabel *namedLabel;QLabel *lookInLabel;QLineEdit *lookInLineEdit;QLineEdit *namedLineEdit;QCheckBox *subfoldersCheckBox;QTableWidget *tableWidget;QLabel *messageLabel;QPushButton *findButton;QPushButton *stopButton;QPushButton *closeButton;QPushButton *helpButton;
};#endif

FindFileDialog.cpp

#include <QtWidgets>#include "findfiledialog.h"FindFileDialog::FindFileDialog(QWidget *parent): QDialog(parent)
{namedLabel = new QLabel(tr("&Named:"), this);namedLineEdit = new QLineEdit(this);namedLabel->setBuddy(namedLineEdit);lookInLabel = new QLabel(tr("&Look in:"), this);lookInLineEdit = new QLineEdit(this);lookInLabel->setBuddy(lookInLineEdit);subfoldersCheckBox = new QCheckBox(tr("Include subfolders"), this);QStringList labels;labels << tr("Name") << tr("In Folder") << tr("Size")<< tr("Modified");tableWidget = new QTableWidget(this);tableWidget->setColumnCount(4);tableWidget->setHorizontalHeaderLabels(labels);messageLabel = new QLabel(tr("0 files found"), this);messageLabel->setFrameShape(QLabel::Panel);messageLabel->setFrameShadow(QLabel::Sunken);findButton = new QPushButton(tr("&Find"), this);stopButton = new QPushButton(tr("Stop"), this);closeButton = new QPushButton(tr("Close"), this);helpButton = new QPushButton(tr("Help"), this);connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));//绝对位置设置namedLabel->setGeometry(9, 9, 50, 25);namedLineEdit->setGeometry(65, 9, 200, 25);lookInLabel->setGeometry(9, 40, 50, 25);lookInLineEdit->setGeometry(65, 40, 200, 25);subfoldersCheckBox->setGeometry(9, 71, 256, 23);tableWidget->setGeometry(9, 100, 256, 100);messageLabel->setGeometry(9, 206, 256, 25);findButton->setGeometry(271, 9, 85, 32);stopButton->setGeometry(271, 47, 85, 32);closeButton->setGeometry(271, 84, 85, 32);helpButton->setGeometry(271, 199, 85, 32);setWindowTitle(tr("Find Files or Folders"));setFixedSize(365, 240);
}

main.cpp

#include <QApplication>#include "findfiledialog.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);FindFileDialog dialog;dialog.show();return app.exec();
}


绝对位置法有很多缺点:
● 用户无法改变窗口的大小。
● 如果用户选择了一种不常用的大字体,或者当应用程序被翻译成另外一种语言时,也许会把一些文本截断。
● 对于某些风格的平台,这些窗口部件可能会具有并不合适的尺寸大小。
● 必须人工计算这些位置和大小。这样做不仅非常枯燥乏味且极易出错,并且还会让后期的维护工作变得痛苦万分。

人工布局法

尽管还是需要给定窗口部件的绝对位置,但是利用人工布局方法给定的大小尺寸总是可以和窗口的大小成比例,这比完全依靠手写代码要好得多了。通过重新实现窗体的resizeEvent()函数,该函数可以设置窗体中的子窗口部件的几何形状,就可以实现人工布局法。

FindFileDialog.h

#ifndef FINDFILEDIALOG_H
#define FINDFILEDIALOG_H#include <QDialog>class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTableWidget;class FindFileDialog : public QDialog
{Q_OBJECTpublic:FindFileDialog(QWidget *parent = 0);protected:void resizeEvent(QResizeEvent *event);private:QLabel *namedLabel;QLabel *lookInLabel;QLineEdit *lookInLineEdit;QLineEdit *namedLineEdit;QCheckBox *subfoldersCheckBox;QTableWidget *tableWidget;QLabel *messageLabel;QPushButton *findButton;QPushButton *stopButton;QPushButton *closeButton;QPushButton *helpButton;
};#endif

FindFileDialog.cpp

#include <QtWidgets>#include "findfiledialog.h"FindFileDialog::FindFileDialog(QWidget *parent): QDialog(parent)
{namedLabel = new QLabel(tr("&Named:"), this);namedLineEdit = new QLineEdit(this);namedLabel->setBuddy(namedLineEdit);lookInLabel = new QLabel(tr("&Look in:"), this);lookInLineEdit = new QLineEdit(this);lookInLabel->setBuddy(lookInLineEdit);subfoldersCheckBox = new QCheckBox(tr("Include subfolders"), this);QStringList labels;labels << tr("Name") << tr("In Folder") << tr("Size")<< tr("Modified");tableWidget = new QTableWidget(this);tableWidget->setColumnCount(4);tableWidget->setHorizontalHeaderLabels(labels);messageLabel = new QLabel(tr("0 files found"), this);messageLabel->setFrameShape(QLabel::Panel);messageLabel->setFrameShadow(QLabel::Sunken);findButton = new QPushButton(tr("&Find"), this);stopButton = new QPushButton(tr("Stop"), this);closeButton = new QPushButton(tr("Close"), this);helpButton = new QPushButton(tr("Help"), this);connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));setWindowTitle(tr("Find Files or Folders"));setMinimumSize(265, 190);resize(365, 240);
}void FindFileDialog::resizeEvent(QResizeEvent * /* event */)
{int extraWidth = width() - minimumWidth();int extraHeight = height() - minimumHeight();namedLabel->setGeometry(9, 9, 50, 25);namedLineEdit->setGeometry(65, 9, 100 + extraWidth, 25);lookInLabel->setGeometry(9, 40, 50, 25);lookInLineEdit->setGeometry(65, 40, 100 + extraWidth, 25);subfoldersCheckBox->setGeometry(9, 71, 156 + extraWidth, 23);tableWidget->setGeometry(9, 100, 156 + extraWidth,50 + extraHeight);messageLabel->setGeometry(9, 156 + extraHeight, 156 + extraWidth,25);findButton->setGeometry(171 + extraWidth, 9, 85, 32);stopButton->setGeometry(171 + extraWidth, 47, 85, 32);closeButton->setGeometry(171 + extraWidth, 84, 85, 32);helpButton->setGeometry(171 + extraWidth, 149 + extraHeight, 85,32);
}

在FindFileDialog构造函数中,我们把窗体的最小大小设置为265 x 190,把它的初始大小设置为365x240。在resizeEvent()处理器中,将多余的任意空间都留给了那些希望变长或者变高的窗口部件。这样就确保了当用户重新改变该窗体大小时,可以稳步地缩放它。

main.cpp

#include <QApplication>#include "findfiledialog.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);FindFileDialog dialog;dialog.show();return app.exec();
}


就像前面的绝对位置法一样,人工布局法需要程序员对很多手写代码中的常量进行计算。像这样来编写代码的确是一件烦人的事情,尤其是在改变设计的时候更是如此,并且它仍旧存在文本会被截断的危险。通过考虑子窗口部件的大小提示,就可以避免这种风险,但是那样将会使代码变得更为复杂。

布局管理器法

对于在窗体上如何摆放窗口部件,最简便易行的解决方法是使用Qt的布局管理器。布局管理器会为每种类型的窗口部件提供一些合理的默认值,并且也会考虑每一个窗口部件的大小提示,这些大小提示又通常会取决于该窗口部件的字体、风格和内容。布局管理器也会充分考虑其最小和最大尺寸,并且会自动通过调整布局来响应字体的变化、内容的改变以及窗口大小的调整。

最为重要的三种布局管理器是:QHBoxLayout、QVBoxLayout和QGridLayout。 这三个类从QLayout中派生出来,而QLayout类为布局提供了基本框架。这三个类可以得到Qt设计师的完全支持,并且也可以直接在代码中使用它们。

FindFileDialog.h

#ifndef FINDFILEDIALOG_H
#define FINDFILEDIALOG_H#include <QDialog>class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTableWidget;class FindFileDialog : public QDialog
{Q_OBJECTpublic:FindFileDialog(QWidget *parent = 0);private:QLabel *namedLabel;QLabel *lookInLabel;QLineEdit *lookInLineEdit;QLineEdit *namedLineEdit;QCheckBox *subfoldersCheckBox;QTableWidget *tableWidget;QLabel *messageLabel;QPushButton *findButton;QPushButton *stopButton;QPushButton *closeButton;QPushButton *helpButton;
};#endif

FindFileDialog.cpp

#include <QtWidgets>#include "findfiledialog.h"FindFileDialog::FindFileDialog(QWidget *parent): QDialog(parent)
{namedLabel = new QLabel(tr("&Named:"));namedLineEdit = new QLineEdit;namedLabel->setBuddy(namedLineEdit);lookInLabel = new QLabel(tr("&Look in:"));lookInLineEdit = new QLineEdit;lookInLabel->setBuddy(lookInLineEdit);subfoldersCheckBox = new QCheckBox(tr("Include subfolders"));QStringList labels;labels << tr("Name") << tr("In Folder") << tr("Size")<< tr("Modified");tableWidget = new QTableWidget;tableWidget->setColumnCount(4);tableWidget->setHorizontalHeaderLabels(labels);messageLabel = new QLabel(tr("0 files found"));messageLabel->setFrameShape(QLabel::Panel);messageLabel->setFrameShadow(QLabel::Sunken);findButton = new QPushButton(tr("&Find"));stopButton = new QPushButton(tr("Stop"));closeButton = new QPushButton(tr("Close"));helpButton = new QPushButton(tr("Help"));connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));QGridLayout *leftLayout = new QGridLayout;leftLayout->addWidget(namedLabel, 0, 0);leftLayout->addWidget(namedLineEdit, 0, 1);leftLayout->addWidget(lookInLabel, 1, 0);leftLayout->addWidget(lookInLineEdit, 1, 1);leftLayout->addWidget(subfoldersCheckBox, 2, 0, 1, 2);leftLayout->addWidget(tableWidget, 3, 0, 1, 2);leftLayout->addWidget(messageLabel, 4, 0, 1, 2);QVBoxLayout *rightLayout = new QVBoxLayout;rightLayout->addWidget(findButton);rightLayout->addWidget(stopButton);rightLayout->addWidget(closeButton);rightLayout->addStretch();rightLayout->addWidget(helpButton);QHBoxLayout *mainLayout = new QHBoxLayout;mainLayout->addLayout(leftLayout);mainLayout->addLayout(rightLayout);setLayout(mainLayout);setWindowTitle(tr("Find Files or Folders"));
}

main.cpp

#include <QApplication>
#include "findfiledialog.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);FindFileDialog dialog;dialog.show();return app.exec();
}


通过一个QHBoxLayout,一个QGridIayout和一个QVBoxIayout,该布局就得到处理,如下图所示。通过外面的QHBoxLayout,就把左侧的QGridI ayout和右侧的QVBoxLayout 一个挨一个地放在了一起。对话框周围的边白和两个子窗口部件之间的间隔均被设置为默认值,该值取决于当前窗口部件的风格,但通过QLayout: : setContentsMargins()和QLayout::setSpacing(),可以对它们的值进行修改。

在Qt设计师中,也可以通过可视化的方式创建出同样的对话框,即:通过把这些子窗口部件摆放在大致的地方,选择那些需要摆放在一起的窗口部件,然后再单击Form->Lay Out Horizontally,Form->Lay Out Verically,或者Layout ->Lay Out in a Grid即可。之前我们就是使用这种方法创建了用于Spreadsheet应用程序的Go to Cell对话框和Sort对话框的。

QHBoxLayout和QVBoxLayout的用法相当简单明了,但QGridLayout的用法则稍微有些麻烦。QGridLayout的工作基于一个二维单元格。在这个布局中,左上角的QLabel的位置是(0,0),而与之相应的QLineEdit的位置是(0, 1)。QCheckBox 占用两列,也就是位置为(2, 0)和(2,1)的两个单元格。在它下面的QTreeWidget和QLable也占用两列。对于QGridLayout::addWidget( )的调用遵循如下的语法形式:

layout->addwidget (widget, row, column, rowSpan, columnSpan);

其中,widget是要插入到布局中的子窗口部件,(row, column)是由该窗口部件所占用的左上角单元格,rowSpan是该窗口部件要占用的行数,而columnSpan是该窗口部件要占用的列数。如果省略了这些参数,则参数rowSpan 和colunnSpan将会取默认值1。

addStretch()调用告诉垂直布局管理器,它会占满布局中这一处的空间。通过添加一个拉伸项,就相当于已经告诉布局管理器,需要占用Close按钮和Help按钮之间的全部多余空间。在Qt设计师中,可以通过插入一个分隔符(spacer)来达到同样的效果,分隔符会显示成蓝色的"弹簧"形状。

如果往布局中添加一个窗口部件或者从布局中移除一个窗口部件,布局都会自动适应所产生的这些新情况。如果对一个子窗口部件调用了hide()或者show(),也同样能够做到自动适应。如果一个子窗口部件的大小提示发生了变化,布局将会自动进行调整,从而把新的大小提示考虑进去。还有布局管理器也会自动根据窗体中子窗口部件的最小大小提示和大小提示,从总体上为这个窗体设置一个最小尺寸。

我们只是简单地把窗口部件放置到布局中,并且使用一定的分隔符元素(拉伸因子)来占用任何多余的空间。但在某些情况下,由此形成的布局看起来可能还不是我们最想要的形式。在这些情形中,可以通过改变要摆放的窗口部件的大小尺寸策略和大小提示来调整布局。

一个窗口部件的大小策略会告诉布局系统应该如何对它进行拉伸或者压缩。Qt为它所有的内置窗口部件都提供了合理的默认大小策略值,但是由于不可能为每一种可能产生的布局都提供唯一的默认值,所以在一个窗体中,开发人员改变它上面的一个或两个窗口部件的大小策略是非常普遍的现象。一个QSizePolicy既包含一个水平分量也包含一个垂直分量。

以下是一些最为常用的取值:
● Fixed的意思是该窗口部件不能被拉伸或者压缩。窗口部件的大小尺寸总是保持为其大小提示的尺寸。
● Minimun的意思是该窗口部件的大小提示就是它的最小大小。再不能把窗口部件压缩到比这个大小提示还要小的大小,但是如有必要,可以拉伸它来填充尽可能多的空间。
● Maximum的意思是该窗口部件的大小提示就是它的最大大小。但是可以把该窗口部件压缩成它的最小大小提示的尺寸。
● Preferred 的意思是该窗口部件的大小提示就是它比较合适的大小。但是如果需要,还是可以对该窗口部件进行拉伸或者压缩。
● Expanding的意思是可以拉伸或者压缩该窗口部件,并且它特别希望能够变长变高。

Preferred和Expanding描述成了同样的效果。但是,它们之间到底有何不同呢?在重新改变一个既包含有Preferred又包含有Expanding 窗口部件的窗体的尺寸大小时,多出来的空间就会分配给Expanding窗口部件,而Prered窗口部件仍旧会按照原有大小提示而保持不变。

这里还有另外两种大小规则:MinimumExpanding和Ignored。前者仅仅用于Qt老版本的极少数情况中,但是如今它已经不再会被用到了。一种比较好的方式是使用Expanding,并且再适当地对minimumSizeHint( )进行重新实现即可。后者与Expanding相似,只是它可以忽略窗口部件的大小提示和最小大小提示。

除了大小规则中包含的水平方向和垂直方向两个分量之外,QSizePolicy类还保存了水平方向和垂直方向的一一个拉伸因子。这些拉伸因子可以用来说明在增大窗体时,对不同的子窗口部件应使用的不同放大比例。例如,假定在一个QTextEdit的上面还有一个QTreeWidget,并且希望这个,QTextEdit的高度能够是QTreeWidget高度的两倍,那么就可以把这个QTextEdit 在垂直方向上的拉伸因子设置为2,而把QTreeWidget在垂直方向上的拉伸因子设置为1。

影响布局方式的另一种方法是设置它的子窗口部件的最小大小、最大大小或固定大小。当布局管理器在摆放这些窗口部件的时候,它就会考虑这些约束条件。并且如果这样还不够的话,还可以对子窗口部件的类进行派生并且重新实现sizeHint()函数,由此获得所需的大小提示。

Qt4_Find File对话框相关推荐

  1. html input type=file 文件上传; 图片上传; 图片闪烁

    (1)input file 对话框和 获取选中文件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  2. vc 打开文件对话框获取选择文件路径

    #include<Windows.h> int getfilename(wchar_t *buf, int len) {     OPENFILENAME ofn;     buf[0] ...

  3. Tkinter 对话框

    文章更新于:2020-04-26 注0:原英文教程地址:zetcode.com 注1:Introduction to Tkinter 参见:关于Tkinter的介绍 注2:Layout managem ...

  4. MFC模式对话框与非模式对话框 消息处理顺序 与非模式对话框的焦点问题、显示、关闭以及交互问题

    对话框有两种创建方式:DoModal和Creat. 其中DoModal创建的是模态的对话框,而Creat创建的是非模态的对话框下面总结下他们的不同. 对于模态的对话框,在该对话框被关闭前,用户将不能在 ...

  5. erdas几何校正_ERDAS遥感图像的几何校正

    1 实习二 遥感图像的几何校正 一.目的和要求 1 .了解图像几何校正的基本含义 2 .掌握图像几何校正的方法和过程 二.实习内容 这里的几何校正实质上的含义是将图像数据投影到平面上, 使其符合地图投 ...

  6. cad的文字嵌入线条_带你玩转CAD!

    CAD画图已经成为化工人的必备技能.什么,这么多CAD必备技巧你居然还不知道?我该拿什么拯救你,我最最最最最最亲爱的旁友!!!下面给大家整理了50个相见恨晚的CAD技巧,带你玩转CAD!!相见恨晚的5 ...

  7. windows中PyCharm的安装和使用

    PyCharm的安装和使用 1.Pycharm的安装 2.Pycharm的使用 2.1新建项目与运行py程序 2.2 python解释器的配置并与PyCharm关联 2.3终端界面 PyCharm是专 ...

  8. 使用 Ant 自动生成项目构建版本

    引言 对 于多版本项目,要提供新版本来跟上新功能或缺陷报告增加的速度,并同时仍然保持可接受的质量水平,可能是一项不小的挑战.构建自动化可确保准确性和消除人 为错误的可能性,从而部分地解决此问题.自动化 ...

  9. ArcGIS Desktop 9.3.1安装流程

    1. 打开安装文件夹,点击ESRI.exe文件,进入安装页面.首先安装ArcGIS License Manager. 注:先把arcgis.efl9和Arc_Info9.lic文件中的server名称 ...

最新文章

  1. 数学建模清风第二次直播:模拟退火算法
  2. leetcode剑指 Offer 14- I. 剪绳子(动态规划)
  3. Node.js server使用
  4. 格密码教程(二):格的基本定义,格基转换
  5. Spring : SpringBootConfiguration 注解
  6. Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
  7. PLSQL 连接不上
  8. 解决anaconda与pycharm冲突导致import无法使用
  9. Android Fingerprint完全解析(二) :Fingerprint启动流程
  10. 带头节点 (非头指针) 双向循环链表 (doubly linked list)
  11. 计算机里的二进制什么意思,二进制是什么,为什么计算机要使用二进制?
  12. android 缓存头像,android 实现类似微信缓存和即时更新好友头像
  13. Ansys Zemax | 如何在 Apple Mac 电脑上运行 OpticStudio 或其他 Zemax 应用程序
  14. Android多开分身 v7.2 破解永久VIP付费版
  15. 微信小程序云端增强 SDK接入
  16. jQuery获取子类第n个元素
  17. kafka命令行使用
  18. 康佳d550 java_康佳 D550:整体外观图
  19. continue / break 跳出指定层循环
  20. 【风险】自动驾驶公司Starsky的危机启示录

热门文章

  1. Intellij IDEA-我常用的快捷键
  2. accp8.0 网页编程_某程序员月入上万!为何却说:我希望自己从来没有学过编程? - C/C++爱好者...
  3. date()---求N个月后的1号
  4. Maven项目POM文件错误,提示“Plugin execution not covered by lifecycle configuration”的解决方案...
  5. WIN10 64位 JDK的安装
  6. nlog自定义文件名
  7. JavaScript 运行机制详解:再谈Event Loop
  8. Android开发之 shape的使用
  9. Javascript对象扩展 - JsPoint类
  10. CSS绝对定位absolute元素的初始包含块不是body元素,也不是html元素