Qt4_Find File对话框

Qt 专栏收录该内容
127 篇文章 2 订阅

在窗体中摆放窗口部件

一共有三种基本方法用于管理窗体上子窗口部件的布局:绝对位置法、人工布局法和布局管理器法。
在这里插入图片描述

绝对位置法

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

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_OBJECT

public:
    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_OBJECT

public:
    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_OBJECT

public:
    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()函数,由此获得所需的大小提示。

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

qzh_1234

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值