【Qt】Qt的GUI设计与制作(上篇:常用控件、布局)

基础控件

笼统地讲,Qt控件主要分为三大种类:

  • 基础控件(Basic Widget):按钮(Button)、下拉列表框(Combo Box)、滚动(Scroll)等可直接使用的控件;
  • 组合控件(Organizer Widget):分割(Splitter)、选项卡(Tab Bar)、按钮组(Button Group)等组合控件;
  • 抽象控件类(Abstract Widget Class):基本控件的基类。

由于Qt的控件数量确实是很多,可以参考链接:All Classes | Qt 5.11

下面就对其中的一些常用控件进行说明和讲解:

QCheckBox和QButtonGroup

Qt中的QCheckBox控件的特点是提供了可以多选的用户界面。QCheckBox有Check和UnCheck两个选项,可以任选其一。第一个参数为CheckBox的项目文本,第二个可以声明父类。

QCheckBox* chk = new QCheckBox("Q&t",this);

“&”字符表示可以使用CheckBox的快捷键,快捷键Alt+E可以激活或禁用CheckBox。

应用程序中可以使用QButtonGroup将CheckBox分为多个组:

QButtonGroup* group = new QButtonGroup(this);

参数来指定父类。可使用成员函数addButton()来讲CheckBox包含在组内。

CheckBox的特点是多选,而若使用QButtonGroup,可以使用setExclusive()函数,将CheckBox的属性转换为单选。

例子:

由于是第一个案例,就将所有的文件都详细地列举出来:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <Qcheckbox>
#include <Qbuttongroup>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:                                //槽函数的声明
    void chkChanged();

private:
    Ui::MainWindow *ui;
    QCheckBox* exclusive[3];
    QCheckBox* non_exclusive[3];
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    this->resize(270,191);       // 重新设置窗体大小
    this->centralWidget();       // 将窗体放置在屏幕中间
    QString str1[] = {"Game","Office","Develop"};
    QString str2[] = {"P&rogramming","Q&t","O&S"};
    int xpos = 30 ;
    int ypos = 30 ;
    QButtonGroup* chk_group[2]; // 按钮组控件,只是逻辑上的分类而已
    chk_group[0] = new QButtonGroup(this);
    chk_group[1] = new QButtonGroup(this);
    for(int i=0;i<3;i++)
    {
        exclusive[i] = new QCheckBox(str1[i],this);                //指定文本
        exclusive[i]->setGeometry(xpos,ypos,100,30);                //指定位置
        chk_group[0]->addButton(exclusive[i]);                    //指定分组

        non_exclusive[i] = new QCheckBox(str2[i],this);
        non_exclusive[i]->setGeometry(xpos+120,ypos,100,30);
        chk_group[1]->addButton(non_exclusive[i]);

        ypos += 40 ;
    }
    chk_group[0]->setExclusive(false);         // 单选失能
    chk_group[1]->setExclusive(true);         // 单选使能

    connect(exclusive[0],SIGNAL(clicked()),this,SLOT(chkChanged()));        //槽函数
    connect(exclusive[1],SIGNAL(clicked()),this,SLOT(chkChanged()));
    connect(exclusive[2],SIGNAL(clicked()),this,SLOT(chkChanged()));

    //ui->setupUi(this);
}

void MainWindow::chkChanged(){                    //槽函数的定义
    for(int i=0 ; i<3 ; i++)
    {
        if(exclusive[i]->checkState())                //判断是否选中
        {
            qDebug("checkbox %d selected",i+1);
        }
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

运行这段程序:

注意:如果程序异常结束,直接退出。极大的可能性是有变量只定义了,没有初始化,就使用了。

QComboBox

Qt中的Qt是实现下拉列表功能的控件。其常用用法如下:

    combo = new QComboBox(this);
    combo->setGeometry(100,100,200,30);                //指定位置

    combo->addItem("Application");                    //添加条目
    combo->addItem("Graphics");
    combo->addItem("Database");
    combo->addItem("Network");

    connect(combo,SIGNAL(currentIndexChanged(int)),this,SLOT(valueChanged()));        //槽函数

void MainWindow::valueChanged(){
    int current_index = combo->currentIndex();                            //得到当前的选项
    qDebug("Current ComboBox Index: %d",current_index);
}

除了上述的函数之外,还有一些常用函数:

QString str = combo->currentText();        //得到条目内容
combo->removeItem(3);                //根据索引删除条目
combo->count();                //获取条目数目

QDate类和QDateEdit控件

QDateEdit是用于显示和编辑日期的控件,可以使用QDateEdit类提供的功能显示日期。其常用用法如下:

        QDate dt1 = QDate(1994,10,13);                            //不使用new,不是指针
        QDate dt2 = QDate::currentDate();                        //获取当前日期

        dateEdit[0] = new QDateEdit(dt1.addYears(2),this);           //1996-10-13
        dateEdit[0]->setGeometry(10,10,140,40);

        dateEdit[1] = new QDateEdit(dt1.addMonths(2),this);            //1994-12-13
        dateEdit[1]->setGeometry(160,10,140,40);

        dateEdit[2] = new QDateEdit(dt1.addDays(2),this);              //1994-10-15
        dateEdit[2]->setGeometry(310,10,140,40);

        dateEdit[3] = new QDateEdit(dt2,this);
        dateEdit[3]->setGeometry(10,60,140,40);

        if(QDate::isValid(2016,02,30))                    //判断日期是否合法
        {
            qDebug()<<"2016-02-30是合法日期";
        }
        else
        {
            qDebug()<<"2016-02-30是非法日期";
        }
        
        if(QDate(2016,02,21).isValid())                //判断日期是否合法
        {
            qDebug()<<"2016-02-21是合法日期";
        }
        else
        {
            qDebug()<<"2016-02-21是非法日期";
        }

        QDate dt3 = QDate::fromString("2016.02.01","yyyy.MM.dd");            //将字符串转化为QDate
        QDate dt4 = QDate::fromString("02-01","MM-dd");
        qDebug()<<"字符串1格式化得到的时间"<<dt3.toString();
        qDebug()<<"字符串2格式化得到的时间"<<dt4.toString();

        qDebug()<<"TextDate格式(默认):"<<dt3.toString(Qt::TextDate);        //将QDate转化为字符串
        qDebug()<<"ISO格式:"<<dt3.toString(Qt::ISODate);
        qDebug()<<"各国表现方式:"<<dt3.toString(Qt::SystemLocaleDate);

        QString longWeek = dt3.longDayName(dt3.dayOfWeek());                //将返回的星期的数字改成“星期x”的字符串
        QString longMonth = dt3.longMonthName(dt3.month());                //将返回的月的数字改成“x月”的字符串
        QString strDateLong = QString("%1 %2").arg(longWeek).arg(longMonth);    //拼接字符串

        QString shortWeek = dt3.longDayName(dt3.dayOfWeek());                //将返回的星期的数字改成“周x”的字符串
        QString shortMonth = dt3.longMonthName(dt3.month());                //将返回的月的数字改成“x月”的字符串
        QString strDateShort = QString("%1 %2").arg(shortWeek).arg(shortMonth);    //拼接字符串

        qDebug()<<"短名称"<<strDateShort;
        qDebug()<<"长名称"<<strDateLong;

        connect(dateEdit[3],SIGNAL(dateChanged(QDate)),this,SLOT(dateChanged()));

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::dateChanged()
{
    QDate dt = dateEdit[3]->date();                        //获得日期

    switch (dt.dayOfWeek()) {                            //返回在本周的星期x
    case 1:
        qDebug()<<"星期一,"<<"今年第"<<dt.dayOfYear()<<"天";            //返回在今年的第x天
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";        //返回该月、年的天数
        break;
    case 2:
        qDebug()<<"星期二,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    case 3:
        qDebug()<<"星期三,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    case 4:
        qDebug()<<"星期四,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    case 5:
        qDebug()<<"星期五,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    case 6:
        qDebug()<<"星期六,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    case 7:
        qDebug()<<"星期七,"<<"今年第"<<dt.dayOfYear()<<"天";
        qDebug()<<"该月总共"<<dt.daysInMonth()<<"天,该年总共"<<dt.daysInYear()<<"天";
        break;
    default:
        break;
    }
}

QTime类和QTimeEdit控件

QTime类是可以显示并编辑时、分、秒、毫秒。QTimeEdit控件可以把QTime类中读取的时间显示到GUI。其常用用法如下:

    QTime ti1 = QTime(6,24,55,432);
    QTime ti2 = QTime::currentTime();                //当前时间

    qte[0] = new QTimeEdit(ti1,this);            //默认显示样式
    qte[0]->setGeometry(10,30,150,30);

    qte[1] = new QTimeEdit(ti1.addSecs(2),this);              //6:24:57:432
    qte[1]->setGeometry(10,70,150,30);
    qte[1]->setDisplayFormat("AP hh:mm:ss:zzz");            //指定显示样式

    qte[2] = new QTimeEdit(ti1.addMSecs(100),this);            //6:24:57:532
    qte[2]->setGeometry(10,110,150,30);
    qte[2]->setDisplayFormat("AP hh:mm:ss:zzz");

    QTime ti3 ;
    ti3 = new QTimeEdit(QTime::fromString("23:30:30","hh:mm:ss"),this);        //将字符串转化为QTime
    qDebug()<<"当前时间"<<ti3.toString("AP hh:mm:ss:zzz");                    //将QTime转化为字符串

    QTime ti4  ;
    ti4.start();                                        //通过start()和elapsed()函数计算过程时间
    for(int i=0;i<10000;i++)
    {
        for(int i=0;i<1000;i++)
        {

        }
    }
    qDebug()<<"刚刚经过了"<<ti4.elapsed()<<"毫秒";

    QTime ti5 = QTime(6,25,34,323);
    qDebug()<<ti5.hour()<<ti5.minute()<<ti5.second();                //获取时间的时分秒,返回值为int

QDateTime和QDateTimeEdit控件

QDateTime类用于编辑日期和时间并提供GUI,通过QDateTimeEdit控件显示其得到的日期和时间。

QDateTimeEdit控件不仅仅可以使用QDateTime类,也可以使用QDate类和QTime类。

这里就只说一点:QDateTimeEdit可以指定日期和时间的变更范围:

    dt[1] = new QDateTimeEdit(QDateTime::currentDateTime(),this);
    dt[1]->setMaximumDateTime(QDateTime::currentDateTime().addYears(2));
    dt[1]->setMinimumDateTime(QDateTime::currentDateTime().addYears(-2));
    dt[1]->setDisplayFormat("yyyy");
    dt[1]->setGeometry(10,90,100,50);

QPushButton和QFocusFrame

QPushButton是按钮控件,QFocusFrame可以控制其他空间外的Paintable区域。比如:在控件外使用外层线时(表示该按钮被选中),可以使用该控件。

在Qt中,点击QPushButton控件的请求(Apply)、取消(Cancel)、是(Yes)、否(No)等按钮时,都会触发事件,QPushButton控件提供了处理这些事件的GUI。其常用用法如下:

    int ypos = 30 ;
    for(int i=0;i<3;i++)
    {
        btn[i] = new QPushButton(QString("第%1个按钮").arg(i),this);        //定义按钮
        btn[i]->setGeometry(10,ypos,300,40);

        ypos += 50 ;
    }

    connect(btn[0],SIGNAL(clicked(bool)),SLOT(btn_clicked()));            //槽函数
    connect(btn[1],SIGNAL(clicked(bool)),SLOT(btn_clicked()));
    connect(btn[2],SIGNAL(clicked(bool)),SLOT(btn_clicked()));


    btn_frame = new QFocusFrame(this);            //在控件外绘制外层线
    btn_frame->setWidget(btn[0]);                    //将控件包含到QFocusFrame中
    btn_frame->setAutoFillBackground(true);

void MainWindow::btn_clicked()                    //定义槽函数
{
    qDebug()<<"触发clicked事件";
}

其实除了clicked()事件之外,还有两个事件:

    connect(btn[0],SIGNAL(clicked(bool)),SLOT(btn_clicked()));
    connect(btn[0],SIGNAL(pressed(bool)),SLOT(btn_pressed()));                //按下
    connect(btn[0],SIGNAL(released(bool)),SLOT(btn_released()));            //释放

QFontComboBox

QFontComboBox控件提供GUI,该界面用于在GUI上选择字体。如果要向用户提供字体选择界面,可以使用QFontComboBox提供字体列表。该控件按照罗马字母顺序排列字体。其常用用法如下:

    int ypos = 30 ;
    for(int i=0 ; i<5;i++)
    {
       fc[i] = new QFontComboBox(this);                    //定义QFontComboBox对象
       fc[i]->setGeometry(10,ypos,300,30);                    //定义位置
       ypos += 40 ;
    }

    fc[0]->setFontFilters(QFontComboBox::AllFonts);                //全部字体
    fc[1]->setFontFilters(QFontComboBox::ScalableFonts);              //能自动变换扩大和缩小等形态的字体
    fc[2]->setFontFilters(QFontComboBox::NonScalableFonts);            //不能自动转换形态的字体
    fc[3]->setFontFilters(QFontComboBox::MonospacedFonts);            //固定宽度的字体
    fc[4]->setFontFilters(QFontComboBox::ProportionalFonts);            //均衡宽度和幅度的字体

    label = new QLabel("用此标签查看字体效果",this);
    label->setGeometry(10,230,200,30);

    connect(fc[0],SIGNAL(currentFontChanged(QFont)),this,SLOT(changedFont(QFont)));        //槽函数,获得QFont字体
    connect(fc[0],SIGNAL(currentIndexChanged(int)),this,SLOT(changedIndex(int)));        //槽函数,获得字体索引号

void MainWindow::changedFont(const QFont& f)
{
    label->setFont(f);                            //设置标签的显示字体
}

void MainWindow::changedIndex(int index)
{
    qDebug()<<index;
}

QLabel和QLCDNumber

QLabel控件在应用程序上显示文本和图像。QLCDNumber控件可以在应用程序上输出文本,只显示数字,也可以以数字时钟的形式显示数字。而且QLCDNumber显示时间时,同时使用“:”字符。其常用用法如下:

    QLabel* lbl[2];
    lbl[0]=new QLabel("Qt Programming",this);            //定义标签
    lbl[0]->setGeometry(10,30,200,40);
    
    QPixmap pix=QPixmap("resources/browser.png");        //定义QPixmap类
    lbl[1]=new QLabel(this);
    lbl[1]->setPixmap(pix);
    lbl[1]->setGeometry(10,70,100,100);

QPixmap类是用于在GUI上描绘图像的API。ALabel控件利用成员函数setPixmap()将使用QPixmap描述的图像显示到GUI。

QImage image("/resources/dj.jpg");
lbl->setPixmap(QPixmap::fromImage(image));

QLCDNumber控件可以用数字时钟的形式显示数字。其常用用法为:

    QLCDNumber* lcd[2];
    lcd[0] = new QLCDNumber(2,this);                    //第一个参数为显示数字的个数
    lcd[0]->display("24");                            //将要显示的数字或“:”
    lcd[0]->setGeometry(150,30,200,100);

    lcd[1] = new QLCDNumber(5,this);
    lcd[1]->display("12:30");
    lcd[1]->setGeometry(150,150,200,100);
    
    lcd[1]->setSegmentStyle(QLCDNumber::Filled);            //显示风格:显示与字体相同的颜色
    lcd[1]->setSegmentStyle(QLCDNumber::Outline);            //显示风格:显示与窗口背景相同的颜色
    lcd[1]->setSegmentStyle(QLCDNumber::Flat);            //显示风格:不显示字体外框线的风格

QLineEdit

QLineEdit控件提供用户可以输入文本的GUI。编辑文本时提供信号,并把编辑的QLineEdit控件文本和QString字符串作为参数传递给槽函数。其常用用法如下:

    edit=new QLineEdit("请输入:",this);
    edit->setGeometry(10,30,200,40);

    edit->setEchoMode(QLineEdit::Normal);             // 显示模式:与默认类型一致
    edit->setEchoMode(QLineEdit::NoEcho);             // 显示模式:隐藏输入文本,不改变光标位置
    edit->setEchoMode(QLineEdit::Password);             // 显示模式:用*表示文本
    edit->setEchoMode(QLineEdit::PasswordEchoOnEdit);    // 显示模式:若编辑文本与默认相同,失去焦点显示

    lbl=new QLabel("文本框内容为:",this);
    lbl->setGeometry(10,80,350,30);

    connect(edit,SIGNAL(textChanged(QString)),this,SLOT(textChanged(QString)));            //槽函数

void MainWindow::textChanged(QString str)                    //槽函数实现
{
    lbl->setText("文本框内容为:"+str);
}

QMenu和QMenuBar

QMenu和QMenuBar类控件用于在应用程序上提供GUI菜单功能。QMenu是制作菜单的作用,提供成员函数addAction()和addMenu()。成员函数addAction()没有下级菜单,直接连接到要执行的功能;成员函数addMenu()关联到下级菜单。最终将QMenu创建的控件与QMenuBar连接,完成菜单制作。

    lbl = new QLable("",this);

    menu[0] = new QMenu("文件");
    menu[0]->addAction("编辑");
    menu[0]->addAction("查看");
    menu[0]->addAction("工具");

    act[0] = new QAction("新建",this);                        //新建QAction
    act[0]->setShortcut(Qt::CTRL | Qt::Key_A );                //创建菜单快捷键
    act[0]->setStatusTip("这是一个新建菜单");                    //添加ToolTip功能

    act[1] = new QAction("打开",this);
    act[1]->setCheckable(true);                            //添加校验功能

    menu[1] = new QMenu("保存");
    menu[1]->addAction(act[0]);
    menu[1]->addAction(act[1]);

    menu[2] = new QMenu("打印");
    menu[2]->addAction("打印设置");
    menu[2]->addMenu(menu[1]);

    menuBar = new QMenuBar(this);                            //新建QMenuBar
    menuBar->addMenu(menu[0]);
    menuBar->addMenu(menu[2]);
    menuBar->setGeometry(0,0,this->width(),30);

    connect(menuBar,SIGNAL(triggered(QAction*)),this,SLOT(trigerMenu(QAction*)));            //槽函数

void MainWindow::trigerMenu(QAction* act)                        //定义槽函数
{
    if(act->text() == "新建")
    {
        QString str = QString("选择菜单:%1".arg(act[0]->text));            //拼接字符串
        lbl->setText(str);
    }
}

QRadioButton和QButtonGroup

QRadioButton控件为用户提供多选一功能,可以和QButtonGroup联合一起使用。其常用用法如下:

    group[0] = new QButtonGroup(this);
    group[1] = new QButtonGroup(this);

    QString str0[3] = {"笔记本","电话","打印机"};
    QString str1[3] = {"萝卜","白菜","青椒"};

    int xpos = 10 , ypos = 30 ;
    for(int i=0;i<3;i++)
    {
        radio0[i] = new QRadioButton(str0[i],this);
        group[0]->addButton(radio0[i]);
        radio0[i]->setGeometry(xpos,ypos,100,30);

        radio1[i] = new QRadioButton(str1[i],this);
        group[1]->addButton(radio1[i]);
        radio1[i]->setGeometry(xpos+110,ypos,100,30);

        ypos += 50 ;
    }

    radio0[2]->setChecked(true);                    //设置单选的选择

QToolBar和QAction

QToolBar控件向窗口提供了类似工具栏的GUI。由于菜单栏存在二级菜单,所以提供了QMenu类来连接QAction;而工具栏不需要二级工具,所以直接连接QAction,添加到QToolBar。其常用用法如下:

    toolbar=new QToolBar(this);

    act[0]=new QAction("Open",this);
    act[1]=new QAction("New",this);

    act[0]->setShortcut(Qt::Key_Control|Qt::Key_E);
    act[0]->setToolTip("Open a file.");

    toolbar->addAction(act[0]);
    toolbar->addAction(act[1]);
    
    toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);                //只显示图标
    toolbar->setToolButtonStyle(Qt::ToolButtonTextOnly);                //只显示按钮名称
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);                //在文本内显示图标
    toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);                //在文本下显示图标

QWidget

之前介绍的控件均继承自QWidget。例如,从鼠标、键盘或窗口接受的事件可以在QPushButton类等控件中使用,而这正是因为它们继承自QWidget。

创建自定义控件时,要创建的控件也可以继承QWidget类。QWidget既可以是父窗口也可以是子窗口。在头文件中,可以明示QWidget是父窗口还是子窗口。

#include <QWidget>

class Widget:public QWidget
{
	Q_OBJECT
	
public:
	Widget(QWidget *parent=0);
	~Widget();
}

若QWidget *parent=0,parent为0,则QWidget是父窗口,否则是子窗口。此处虽然明示了parent=0,但未明示时,parent默认值也是0。

 

布局管理器

布局管理器可以依据窗口的大小变更布局控件的位置和大小。下面将介绍Qt布局管理器相关API的使用方法。

之前都是使用setGeometry()在GUI上布局控件,此函数可以利用绝对坐标。但是这种方法的问题在于,用户不能动态的改变窗口的大小,因为不能动态改变用绝对坐标布局的控件大小。

因此,为了在窗口大小发生改变时调整控件大小,Qt提供了布局管理器。布局管理器可以根据窗口的大小调整空间的大小。此外,如果隐藏或显示布局管理器,则其包含的所有控件也随之隐藏或显示。

Qt提供的布局管理器
布局管理器含义
QHBoxLayout水平布局控件
QVBoxLayout垂直布局控件
QGridLayout将控件布置成网格状
QFormLayout表单布局控件

需要注意的是:

  • 表中的布局管理器可以嵌套使用。
  • Creating a main window without a central widget is not supported. You must have a central widget even if it is just a placeholder.  也就是说,布局管理器必须是在一个Widget上才能够完成。

所以:如果在QT中,想要对MainWindow的布局进行设置,首先要先定义一个widget。格式如下:

QWidget *window = new QWidget;
    ...
window->setLayout(layout);

水平、垂直、网格、表单布局

为窗口提供一个好布局的最佳方式是使用内置的布局管理器:QHBoxLayout、QVBoxLayout、QGridLayout和QFormLayout。这些类都派生自QLayout,QLayout又派生自QObject(非QWidget),布局窗口自动地把子窗口按照它们被构造地顺序进行布局。要生成更复杂的布局,可以在其它布局里面嵌入另一个布局。

QHBoxLayout:把子窗口从左到右排列在一个水平行上。

QVBoxLayout:把子窗口从上到下排列在一个垂直列上。

QGridLayout:把子窗口排列在一个二维的网格中,窗口可占据多个单元格。

QFormLayout:把子窗口按照标签-输入框的形式排列在两列。

代码布局

下面的代码创建一个管理五个按钮的水平布局,上面的第一张图所示:

QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");

QHBoxLayout *layout = new QHBoxLayout;            //新建一个布局
layout->addWidget(button1);                        //添加控件
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);

window->setLayout(layout);
window->show();

对于QVBoxLayout代码是相同的,除了QHBoxLayout 和QVBoxLayout区别以外。对于QGridLayout有点不同,因为需要指定子控件的行和列的位置:

QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");

QGridLayout *layout = new QGridLayout;
layout->addWidget(button1, 0, 0);
layout->addWidget(button2, 0, 1);
layout->addWidget(button3, 1, 0, 1, 2);
layout->addWidget(button4, 2, 0);
layout->addWidget(button5, 2, 1);

window->setLayout(layout);
window->show();

第三个QPushButton占据2列。通过指定QGridLayout:: addWidget()的第五参数为2来实现。

QFormLayout将在一行上添加两个控件,通常是QLabel和QLineEdit。在同一行中添加QLabel和QLineEdit,将把QLineEdit设置为QLabel的伙伴。下面的代码将使用QFormLayout将3个QPushButton和相应QLineEdit排列起来。

QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QLineEdit *lineEdit1 = new QLineEdit();
QPushButton *button2 = new QPushButton("Two");
QLineEdit *lineEdit2 = new QLineEdit();
QPushButton *button3 = new QPushButton("Three");
QLineEdit *lineEdit3 = new QLineEdit();

QFormLayout *layout = new QFormLayout;
layout->addRow(button1, lineEdit1);
layout->addRow(button2, lineEdit2);
layout->addRow(button3, lineEdit3);

window->setLayout(layout);
window->show();

使用布局提示:

  • 当使用布局的时候,构建子控件的时候不需要指定parent,布局将会自动的指定parent(使用QWidget::setParent()),使它们成为安装了该布局的界面的子控件。
  • 布局中的控件是安装了该布局的界面的子控件,而非布局自身的,控件只能以控件作为parent,不能是布局。也可以在布局中使用addLayout()来添加布局,内部的布局就会变成它的子布局。

布局管理器的嵌套

布局管理器之间可以相互嵌套,一般使用addLayout()函数来进行添加。

例子:

具体的文件程序为:

#ifndef DIALOG_H
#define DIALOG_H
#include <QtGui/QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QComboBox>
#include <QGridLayout>
#include <QPushButton>
class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget *parent = 0);
    ~Dialog();
    QLabel *label1;
    QLabel *label2;
    QLabel *label3;
    QLabel *label4;
    QLabel *label5;
    QLabel *label6;
    QLabel *label7;
    QLabel *labelOther;
    QLabel *labelIcon;
    QLineEdit *lineEditUser;
    QLineEdit *lineEditName;
    QComboBox *comboBoxSex;
    QTextEdit *textEditDepartment;
    QLineEdit *lineEditAge;
    QTextEdit *textEditDisc;
    QPushButton *pushButtonIcon;
    QPushButton *pushButtonOK;
    QPushButton *pushButtonExit;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    setWindowTitle(tr("User Name"));
    label1 = new QLabel(tr("User Name"));
    label2 = new QLabel(tr("Name"));
    label3 = new QLabel(tr("Sex"));
    label4 = new QLabel(tr("Department"));
    label5 = new QLabel(tr("Age"));
    labelOther = new QLabel(tr("Remark"));
    
    labelOther->setFrameStyle(QFrame::Panel | QFrame::Sunken);     //label继承自QFrame,可以设置凹陷或阴影状态,用|即可
    lineEditUser = new QLineEdit;
    lineEditName = new QLineEdit;
    
    comboBoxSex = new QComboBox;                                    //QComBox的使用,insertItem插入项
    comboBoxSex->insertItem(0,tr("Female"));
    comboBoxSex->insertItem(1,tr("Male"));
    textEditDepartment = new QTextEdit();
    lineEditAge = new QLineEdit;
    
    QGridLayout *leftLayout = new QGridLayout();                    //左半边子布局网格布局
    
    int labelCol=0;                            //只有两列,所以定义两个变量labelCol表示第0列,contentCol表示第一列
    int contentCol=1;
    leftLayout->addWidget(label1,0,labelCol);
    leftLayout->addWidget(lineEditUser,0,contentCol);
    leftLayout->addWidget(label2,1,labelCol);
    leftLayout->addWidget(lineEditName,1,contentCol);
    leftLayout->addWidget(label3,2,labelCol);
    leftLayout->addWidget(comboBoxSex,2,contentCol);
    
    leftLayout->addWidget(label4,3,labelCol,Qt::AlignTop);        //注意这里的部门标签,设置为顶部对齐方式,可以和textEdit对齐,看运行效果
    leftLayout->addWidget(textEditDepartment,3,contentCol);
    leftLayout->addWidget(label5,4,labelCol);
    leftLayout->addWidget(lineEditAge,4,contentCol);
    
    leftLayout->addWidget(labelOther,5,labelCol,1,2);            //labelOther坐标(5,0),占了一行布局中两列的位置,看运行效果
    
    leftLayout->setColumnStretch(0,1);            //setColumnStretch设置第0列在布局管理中所占比例为1,第1列在布局管理中所占比例为3,即使对话框大小改变了,两列之间的宽度比依然保持不变
    leftLayout->setColumnStretch(1,3);
    label7  = new QLabel(tr("Head"));
    labelIcon = new QLabel();
    QPixmap icon("man.png");
    labelIcon->resize(icon.width(),icon.height());
    labelIcon->setPixmap(icon);
    pushButtonIcon = new QPushButton;
    pushButtonIcon->setText(tr("Change"));
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setSpacing(20);
    hlayout->addWidget(label7);
    hlayout->addWidget(labelIcon);
    hlayout->addWidget(pushButtonIcon);
    label6 = new QLabel(tr("Individual"));
    textEditDisc = new QTextEdit;
    
    QVBoxLayout *rightLayout = new QVBoxLayout;                //右半部分的竖直对齐
    
    rightLayout->setMargin(10);                                //设置控件到边框的距离
    rightLayout->addLayout(hlayout);
    rightLayout->addWidget(label6);
    rightLayout->addWidget(textEditDisc);
    
    pushButtonOK = new QPushButton(tr("OK"));                        //底布局,两个按钮
    pushButtonExit = new QPushButton(tr("Cancel"));
    QHBoxLayout *bottomLayout = new QHBoxLayout;
    
    bottomLayout->addStretch();                        //addStretch在按钮之前插入一个占位符,使两个按钮能始终靠右对齐,并且在整个对话框的大小发生改变时,保证按钮的大小不发生变化
    bottomLayout->addWidget(pushButtonOK);
    bottomLayout->addWidget(pushButtonExit);
    
    QGridLayout *mainLayout = new QGridLayout(this);            //顶级布局,布局管理的对象会默认被布局管理所在控件管理,即默认指定父窗口
    mainLayout->setMargin(15);
    mainLayout->setSpacing(10);
    mainLayout->addLayout(leftLayout,0,0);
    mainLayout->addLayout(rightLayout,0,1);
    mainLayout->addLayout(bottomLayout,1,0,1,2);
    
    mainLayout->setSizeConstraint(QLayout::SetFixedSize);       //setSizeConstraint(Qlayout::setFixedSize)设定对话框的控件总是最优化显示,并且用户无法改变对话框的大小,所谓最优化显示,即控件都按其sizeHint()的大小显示,sizeHint表示布局管理器中默认尺寸
    
}
Dialog::~Dialog()
{
}

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:上身试试 返回首页