一、Qt 5基本对话框
首先介绍标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框(QFontDialog)、标准输入对话框(QInputDialog)及标准消息对话框(QMessageBox),运行效果如图4.1所示。
按如图4.1所示依次执行如下操作。
(1)单击“文件标准对话框实例”按钮,弹出“文件选择”对话框(open file dialog),如图4.2所示。选中的文件名所在目录路径将显示在图4.1中该按钮右侧的标签中。
(2)单击“颜色标准对话框实例”按钮,弹出“颜色选择”(Select Color)对话框,如图4.3所示。选中的颜色将显示在图4.1中该按钮右侧的标签中。
(3)单击“字体标准对话框实例”按钮,弹出“字体选择”(Select Font)对话框,如图4.4所示。选中的字体将应用于如图4.1所示中该按钮右侧显示的文字。
(4)标准输入对话框包括:标准字符串输入对话框、标准条目选择对话框、标准int类型输入对话框和标准double类型输入对话框。 单击“标准输入对话框实例”按钮,弹出“标准输入对话框实例”界面,如图4.5(a)所示。在“标准输入对话框实例”界面中,若调用“修改姓名”输入框,则为一个QLineEdit,如图4.5(b)所示;若调用“修改性别”列表框,则为一个QComboBox,如图4.5(c)所示;若调用“修改年龄”(int类型)或“修改成绩”(double类型)输入框,则为一个QSpinBox,如图4.5(d)和图4.5(e)所示。每种标准输入对话框都包括一个确定输入(“OK”)按钮和一个取消输入(“Cancel”)按钮。
(5)单击“标准消息对话框实例”按钮,弹出“标准消息对话框实例”界面,如图4.6(a)所示。“标准消息对话框实例”界面包括Question消息框,如图4.6(b)所示;Information消息框,如图4.6(c)所示;Warning消息框,如图4.6(d)所示;Critical消息框,如图4.6(e)所示; About消息框,如图4.6(f)所示;About Qt消息框,如图4.6(g)所示。
(6)如果以上所有的标准消息框都不能满足开发的需求,则下面介绍Qt允许的Custom(自定义)消息框的使用方法。单击“用户自定义消息对话框实例”按钮,弹出“用户自定义消息框”界面,如图4.7所示。
各种标准基本对话框通过调用各自不同的静态函数来完成其功能,具体说明见表4.1。
相 关 类 | 类 说 明 | 静 态 函 数 | 函 数 说 明 |
QFileDialog类 | 标准文件对话框 | getOpenFileName | 获得用户选择的文件名 |
getSaveFileName | 获得用户保存的文件名 | ||
getExistingDirectory | 获得用户选择的已存在的目录名 | ||
getOpenFileNames | 获得用户选择的文件名列表 | ||
QColorDialog类 | 标准颜色对话框 | getColor | 获得用户选择的颜色值 |
QFontDialog类 | 标准字体对话框 | getFont | 获得用户选择的字体 |
QInputDialog类 | 标准输入对话框 | getText | 标准字符串输入对话框 |
getItem | 下拉表条目输入框 | ||
getInt | int类型数据输入对话框 | ||
getDouble | double类型数据输入对话框 | ||
QMessageBox类 | 标准消息对话框 | QMessageBox::question | Question消息框 |
QMessageBox::information | Information消息框 | ||
QMessageBox::warning | Warning消息框 | ||
QMessageBox::critical | Critical消息框 | ||
QMessageBox::about | About消息框 | ||
QMessageBox::aboutQt | About Qt消息框 |
【例】(难度一般)(CH401)完成如图4.1所示的界面显示。
操作步骤如下。
新建Qt Widgets Application,项目名为“DialogExample”,基类选择“QDialog”,类名保持“Dialog”不变,取消“创建界面”复选框的选中状态。
在“dialog.cpp”文件中的Dialog 的构造函数中应该添加如下代码:
setWindowTitle(tr("各种标准对话框的实例"));
以便能够显示该工程的对话框标题。
以下所有程序中凡在用到某个Qt类库时,都要将该类所在的库文件包括到该工程中,将不再重复说明。
标准文件对话框类
QFileDialog类的几个静态函数见表4.1,用户通过这些函数可以很方便地定制自己的文件对话框。其中,getOpenFileName()静态函数返回用户选择的文件名。但是,当用户选择文件时,若选择“取消”(Cancel),则返回一个空串。在此仅详细说明getOpenFileName()静态函数中各个参数的作用,其他文件对话框类中相关的静态函数的参数有与其类似之处。
其函数形式如下:
QString QFileDialog::getOpenFileName
(
QWidget* parent=0, //标准文件对话框的父窗口
const QString & caption=QString(), //标准文件对话框的标题名
const QString & dir=QString(), //注(1)
const QString & filter=QString(), //注(2)
QString * selectedFilter=0, //用户选择的过滤器通过此参数返回
Options options=0 //选择显示文件名的格式,默认是同时显示目录与文件名
)
标准颜色对话框类
getColor()函数是标准颜色对话框QColorDialog类的一个静态函数,该函数返回用户选择的颜色值。下面是getColor()函数形式:
QColor getColor
(
const QColor& initial=Qt::white, //注
QWidget* parent=0 //标准颜色对话框的父窗口
);
标准字体对话框类
getFont()函数是标准字体对话框QFontDialog类的一个静态函数,该函数返回用户所选择的字体,下面是getFont()函数形式:
QFont getFont
(
bool* ok, //注
QWidget* parent=0 //标准字体对话框的父窗口
);
(1)在dialog.h和dialog.cpp完成标准文件对话框类、标准颜色对话框类和标准字体对话框类的创建
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLineEdit>
#include <QGridLayout>
#include "inputdlg.h"
#include "msgboxdlg.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton *fileBtn;
QLineEdit *fileLineEdit;
QGridLayout *mainLayout;
QPushButton *colorBtn;
QFrame *colorFrame;
QPushButton *fontBtn;
QLineEdit *fontLineEdit;
QPushButton *inputBtn;
InputDlg *inputDlg;
QPushButton *MsgBtn;
MsgBoxDlg *msgDlg;
QPushButton *CustomBtn;
QLabel *label;
private slots:
void showFile();
void showColor();
void showFont();
void showInputDlg();
void showMsgDlg();
void showCustomDlg();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <QGridLayout>
#include <QFileDialog>
#include <QPushButton>
#include <QColorDialog>
#include <QFontDialog>
#include <QMessageBox>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("各种标准对话框的实例"));
fileBtn=new QPushButton; //各个控件对象的初始化
fileBtn->setText(tr("文件标准对话框实例"));
fileLineEdit=new QLineEdit; //用来显示选择的文件名
mainLayout=new QGridLayout(this); //布局设计
mainLayout->addWidget(fileBtn,0,0);
mainLayout->addWidget(fileLineEdit,0,1);
connect(fileBtn,SIGNAL(clicked()),this,SLOT(showFile())); //事件关联
colorBtn=new QPushButton; //创建各个控件的对象
colorBtn->setText(tr("颜色标准对话框实例"));
colorFrame=new QFrame;
colorFrame->setFrameShape(QFrame::Box);
colorFrame->setAutoFillBackground(true);
mainLayout->addWidget(colorBtn,1,0); //布局设计
mainLayout->addWidget(colorFrame,1,1);
connect(colorBtn,SIGNAL(clicked()),this,SLOT(showColor())); //事件关联
fontBtn=new QPushButton; //创建控件的对象
fontBtn->setText(tr("字体标准对话框实例"));
fontLineEdit=new QLineEdit; //显示更改的字符串
fontLineEdit->setText(tr("Welcome!"));
mainLayout->addWidget(fontBtn,2,0); //布局设计
mainLayout->addWidget(fontLineEdit,2,1);
connect(fontBtn,SIGNAL(clicked()),this,SLOT(showFont())); //事件关联
inputBtn=new QPushButton; //创建控件的对象
inputBtn->setText(tr("标准输入对话框实例"));
mainLayout->addWidget(inputBtn,3,0); //布局设计
connect(inputBtn,SIGNAL(clicked()),this,SLOT(showInputDlg()));//事件关联
MsgBtn =new QPushButton; //创建控件对象
MsgBtn->setText(tr("标准消息对话框实例"));
mainLayout->addWidget(MsgBtn,3,1);
connect(MsgBtn,SIGNAL(clicked()),this,SLOT(showMsgDlg()));
CustomBtn =new QPushButton;
CustomBtn->setText(tr("用户自定义消息对话框实例"));
label =new QLabel;
label->setFrameStyle(QFrame::Panel|QFrame::Sunken);
mainLayout->addWidget(CustomBtn,4,0);
mainLayout->addWidget(label,4,1);
connect(CustomBtn,SIGNAL(clicked()),this,SLOT(showCustomDlg()));
}
void Dialog::showFile()
{
QString s = QFileDialog::getOpenFileName(this,"open file dialog","/","C++ files(*.cpp);;C files(*.c);;Head files(*.h)");
fileLineEdit->setText(s);
}
void Dialog::showColor()
{
QColor c = QColorDialog::getColor(Qt::blue);
if(c.isValid())
{
colorFrame->setPalette(QPalette(c));
}
}
void Dialog::showFont()
{
bool ok;
QFont f = QFontDialog::getFont(&ok);
if (ok)
{
fontLineEdit->setFont(f);
}
}
void Dialog::showInputDlg()
{
inputDlg =new InputDlg(this);
inputDlg->show();
}
void Dialog::showMsgDlg()
{
msgDlg =new MsgBoxDlg();
msgDlg->show();
}
void Dialog::showCustomDlg()
{
label->setText(tr("Custom Message Box"));
QMessageBox customMsgBox;
customMsgBox.setWindowTitle(tr("用户自定义消息框")); //设置消息框的标题
QPushButton *yesBtn=customMsgBox.addButton(tr("Yes"),QMessageBox:: ActionRole); //(a)
QPushButton *noBtn=customMsgBox.addButton(tr("No"),QMessageBox::ActionRole);
QPushButton *cancelBtn=customMsgBox.addButton(QMessageBox::Cancel);
//(b)
customMsgBox.setText(tr("这是一个用户自定义消息框!")); //(c)
customMsgBox.setIconPixmap(QPixmap("Qt.png")); //(d)
customMsgBox.exec(); //显示此自定义消息框
if(customMsgBox.clickedButton()==yesBtn)
label->setText("Custom Message Box/Yes");
if(customMsgBox.clickedButton()==noBtn)
label->setText("Custom Message Box/No");
if(customMsgBox.clickedButton()==cancelBtn)
label->setText("Custom Message Box/Cancel");
return;
}
Dialog::~Dialog()
{
}
(2)标准输入对话框类在inputdlg.h和inputdlg.cpp里说明
inputdlg.h
#ifndef INPUTDLG_H
#define INPUTDLG_H
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>
#include <QDialog>
class InputDlg : public QDialog
{
Q_OBJECT
public:
InputDlg(QWidget* parent=0);
private slots:
void ChangeName();
void ChangeSex();
void ChangeAge();
void ChangeScore();
private:
QLabel *nameLabel1;
QLabel *sexLabel1;
QLabel *ageLabel1;
QLabel *scoreLabel1;
QLabel *nameLabel2;
QLabel *sexLabel2;
QLabel *ageLabel2;
QLabel *scoreLabel2;
QPushButton *nameBtn;
QPushButton *sexBtn;
QPushButton *ageBtn;
QPushButton *scoreBtn;
QGridLayout *mainLayout;
};
#endif // INPUTDLG_H
inputdlg.cpp
#include "inputdlg.h"
#include <QInputDialog>
InputDlg::InputDlg(QWidget* parent):QDialog(parent)
{
setWindowTitle(tr("标准输入对话框实例"));
nameLabel1 =new QLabel;
nameLabel1->setText(tr("姓名:"));
nameLabel2 =new QLabel;
nameLabel2->setText(tr("周何骏")); //姓名的初始值
nameLabel2->setFrameStyle(QFrame::Panel|QFrame::Sunken);
nameBtn =new QPushButton;
nameBtn->setText(tr("修改姓名"));
sexLabel1 =new QLabel;
sexLabel1->setText(tr("性别:"));
sexLabel2 =new QLabel;
sexLabel2->setText(tr("男")); //性别的初始值
sexLabel2->setFrameStyle(QFrame::Panel|QFrame::Sunken);
sexBtn =new QPushButton;
sexBtn->setText(tr("修改性别"));
ageLabel1 =new QLabel;
ageLabel1->setText(tr("年龄:"));
ageLabel2 =new QLabel;
ageLabel2->setText(tr("21")); //年龄的初始值
ageLabel2->setFrameStyle(QFrame::Panel|QFrame::Sunken);
ageBtn =new QPushButton;
ageBtn->setText(tr("修改年龄"));
scoreLabel1 =new QLabel;
scoreLabel1->setText(tr("成绩:"));
scoreLabel2 =new QLabel;
scoreLabel2->setText(tr("80")); //成绩的初始值
scoreLabel2->setFrameStyle(QFrame::Panel|QFrame::Sunken);
scoreBtn =new QPushButton;
scoreBtn->setText(tr("修改成绩"));
mainLayout =new QGridLayout(this);
mainLayout->addWidget(nameLabel1,0,0);
mainLayout->addWidget(nameLabel2,0,1);
mainLayout->addWidget(nameBtn,0,2);
mainLayout->addWidget(sexLabel1,1,0);
mainLayout->addWidget(sexLabel2,1,1);
mainLayout->addWidget(sexBtn,1,2);
mainLayout->addWidget(ageLabel1,2,0);
mainLayout->addWidget(ageLabel2,2,1);
mainLayout->addWidget(ageBtn,2,2);
mainLayout->addWidget(scoreLabel1,3,0);
mainLayout->addWidget(scoreLabel2,3,1);
mainLayout->addWidget(scoreBtn,3,2);
mainLayout->setMargin(15);
mainLayout->setSpacing(10);
connect(nameBtn,SIGNAL(clicked()),this,SLOT(ChangeName()));
connect(sexBtn,SIGNAL(clicked()),this,SLOT(ChangeSex()));
connect(ageBtn,SIGNAL(clicked()),this,SLOT(ChangeAge()));
connect(scoreBtn,SIGNAL(clicked()),this,SLOT(ChangeScore()));
}
void InputDlg::ChangeName()
{
bool ok;
QString text=QInputDialog::getText(this,tr("标准字符串输入对话框"),
tr("请输入姓名:"), QLineEdit::Normal,nameLabel2->text(),&ok);
if (ok && !text.isEmpty())
nameLabel2->setText(text);
}
void InputDlg::ChangeSex()
{
QStringList SexItems;
SexItems << tr("男") << tr("女");
bool ok;
QString SexItem = QInputDialog::getItem(this, tr("标准条目选择对话框"),
tr("请选择性别:"), SexItems, 0, false, &ok);
if (ok && !SexItem.isEmpty())
sexLabel2->setText(SexItem);
}
void InputDlg::ChangeAge()
{
bool ok;
int age = QInputDialog::getInt(this, tr("标准int类型输入对话框"),
tr("请输入年龄:"), ageLabel2->text().toInt(&ok), 0, 100, 1, &ok);
if (ok)
ageLabel2->setText(QString(tr("%1")).arg(age));
}
void InputDlg::ChangeScore()
{
bool ok;
double score = QInputDialog::getDouble(this, tr("标准double类型输入对话框"),
tr("请输入成绩:"),scoreLabel2->text().toDouble(&ok), 0, 100, 1, &ok);
if (ok)
scoreLabel2->setText(QString(tr("%1")).arg(score));
}
(3)msgboxdlg.h和msgboxdlg.cpp创建消息对话框类
msgboxdlg.h
#ifndef MSGBOXDLG_H
#define MSGBOXDLG_H
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>
#include <QDialog>
class MsgBoxDlg : public QDialog
{
Q_OBJECT
public:
MsgBoxDlg(QWidget* parent=0);
private slots:
void showQuestionMsg();
void showInformationMsg();
void showWarningMsg();
void showCriticalMsg();
void showAboutMsg();
void showAboutQtMsg();
private:
QLabel *label;
QPushButton *questionBtn;
QPushButton *informationBtn;
QPushButton *warningBtn;
QPushButton *criticalBtn;
QPushButton *aboutBtn;
QPushButton *aboutQtBtn;
QGridLayout *mainLayout;
};
#endif // MSGBOXDLG_H
msgboxdlg.cpp
#include "msgboxdlg.h"
#include <QMessageBox>
MsgBoxDlg::MsgBoxDlg(QWidget *parent):QDialog(parent)
{
setWindowTitle(tr("标准消息对话框实例")); //设置对话框的标题
label =new QLabel;
label->setText(tr("请选择一种消息框"));
questionBtn =new QPushButton;
questionBtn->setText(tr("QuestionMsg"));
informationBtn =new QPushButton;
informationBtn->setText(tr("InformationMsg"));
warningBtn =new QPushButton;
warningBtn->setText(tr("WarningMsg"));
criticalBtn =new QPushButton;
criticalBtn->setText(tr("CriticalMsg"));
aboutBtn =new QPushButton;
aboutBtn->setText(tr("AboutMsg"));
aboutQtBtn =new QPushButton;
aboutQtBtn->setText(tr("AboutQtMsg"));
//布局
mainLayout =new QGridLayout(this);
mainLayout->addWidget(label,0,0,1,2);
mainLayout->addWidget(questionBtn,1,0);
mainLayout->addWidget(informationBtn,1,1);
mainLayout->addWidget(warningBtn,2,0);
mainLayout->addWidget(criticalBtn,2,1);
mainLayout->addWidget(aboutBtn,3,0);
mainLayout->addWidget(aboutQtBtn,3,1);
//事件关联
connect(questionBtn,SIGNAL(clicked()),this,SLOT(showQuestionMsg()));
connect(informationBtn,SIGNAL(clicked()),this,SLOT(showInformationMsg()));
connect(warningBtn,SIGNAL(clicked()),this,SLOT(showWarningMsg()));
connect(criticalBtn,SIGNAL(clicked()),this,SLOT(showCriticalMsg()));
connect(aboutBtn,SIGNAL(clicked()),this,SLOT(showAboutMsg()));
connect(aboutQtBtn,SIGNAL(clicked()),this,SLOT(showAboutQtMsg()));
}
void MsgBoxDlg::showQuestionMsg()
{
label->setText(tr("Question Message Box"));
switch(QMessageBox::question(this,tr("Question消息框"),
tr("您现在已经修改完成,是否要结束程序?"),
QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Ok))
{
case QMessageBox::Ok:
label->setText("Question button/Ok");
break;
case QMessageBox::Cancel:
label->setText("Question button/Cancel");
break;
default:
break;
}
return;
}
void MsgBoxDlg::showInformationMsg()
{
label->setText(tr("Information Message Box"));
QMessageBox::information(this,tr("Information消息框"),tr("这是Information消息框测试,欢迎您!"));
return;
}
void MsgBoxDlg::showWarningMsg()
{
label->setText(tr("Warning Message Box"));
switch(QMessageBox::warning(this,tr("Warning消息框"),
tr("您修改的内容还未保存,是否要保存对文档的修改?"),
QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel,
QMessageBox::Save))
{
case QMessageBox::Save:
label->setText(tr("Warning button/Save"));
break;
case QMessageBox::Discard:
label->setText(tr("Warning button/Discard"));
break;
case QMessageBox::Cancel:
label->setText(tr("Warning button/Cancel"));
break;
default:
break;
}
return;
}
void MsgBoxDlg::showCriticalMsg()
{
label->setText(tr("Critical Message Box"));
QMessageBox::critical(this,tr("Critical消息框"),tr("这是一个Critical消息框测试!"));
return;
}
void MsgBoxDlg::showAboutMsg()
{
label->setText(tr("About Message Box"));
QMessageBox::about(this,tr("About消息框"),tr("这是一个About消息框测试!"));
return;
}
void MsgBoxDlg::showAboutQtMsg()
{
label->setText(tr("About Qt Message Box"));
QMessageBox::aboutQt(this,tr("About Qt消息框"));
return;
}
二、工具盒类
【例】(难度一般)(CH402)通过实现类似QQ抽屉效果的实例来介绍QToolBox类的使用,运行效果如图4.8所示。
下面介绍实现的具体步骤。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“MyQQExample”,基类选择“QDialog”,取消“创建界面”复选框的选中状态。
(2)添加该工程的提供主要显示界面的函数所在的文件,在“MyQQExample”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项。单击“Choose...”按钮,在弹出的对话框的“Base class”文本框中输入基类名“QToolBox”(手工添加),在“Class name”文本框中输入类的名称“Drawer”。
(3)单击“下一步”按钮,单击“完成”按钮,添加“drawer.h”头文件和“drawer.cpp”源文件。
#ifndef DRAWER_H
#define DRAWER_H
#include <QToolBox>
#include <QToolButton>
class Drawer : public QToolBox
{
Q_OBJECT
public:
Drawer(QWidget *parent=0,Qt::WindowFlags f=0);
private:
QToolButton *toolBtn1_1;
QToolButton *toolBtn1_2;
QToolButton *toolBtn1_3;
QToolButton *toolBtn1_4;
QToolButton *toolBtn1_5;
QToolButton *toolBtn2_1;
QToolButton *toolBtn2_2;
QToolButton *toolBtn3_1;
QToolButton *toolBtn3_2;
};
#endif // DRAWER_H
#include "drawer.h"
#include <QGroupBox>
#include <QVBoxLayout>
Drawer::Drawer(QWidget *parent, Qt::WindowFlags f):QToolBox(parent,f)
{
setWindowTitle(tr("My QQ")); //设置主窗体的标题
toolBtn1_1 =new QToolButton; //(a)
toolBtn1_1->setText(tr("张三")); //(b)
toolBtn1_1->setIcon(QPixmap("11.png")); //(c)
toolBtn1_1->setIconSize(QPixmap("11.png").size()); //(d)
toolBtn1_1->setAutoRaise(true); //(e)
toolBtn1_1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//(f)
toolBtn1_2 =new QToolButton;
toolBtn1_2->setText(tr("李四"));
toolBtn1_2->setIcon(QPixmap("12.png"));
toolBtn1_2->setIconSize(QPixmap("12.png").size());
toolBtn1_2->setAutoRaise(true);
toolBtn1_2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolBtn1_3 =new QToolButton;
toolBtn1_3->setText(tr("王五"));
toolBtn1_3->setIcon(QPixmap("13.png"));
toolBtn1_3->setIconSize(QPixmap("13.png").size());
toolBtn1_3->setAutoRaise(true);
toolBtn1_3->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolBtn1_4 =new QToolButton;
toolBtn1_4->setText(tr("小赵"));
toolBtn1_4->setIcon(QPixmap("14.png"));
toolBtn1_4->setIconSize(QPixmap("14.png").size());
toolBtn1_4->setAutoRaise(true);
toolBtn1_4->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolBtn1_5 =new QToolButton;
toolBtn1_5->setText(tr("小孙"));
toolBtn1_5->setIcon(QPixmap("155.png"));
toolBtn1_5->setIconSize(QPixmap("155.png").size());
toolBtn1_5->setAutoRaise(true);
toolBtn1_5->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
QGroupBox *groupBox1=new QGroupBox; //(g)
QVBoxLayout *layout1=new QVBoxLayout(groupBox1);//(h)
layout1->setMargin(10); //布局中各窗体的显示间距
layout1->setAlignment(Qt::AlignHCenter); //布局中各窗体的显示位置
//加入抽屉内的各个按钮
layout1->addWidget(toolBtn1_1);
layout1->addWidget(toolBtn1_2);
layout1->addWidget(toolBtn1_3);
layout1->addWidget(toolBtn1_4);
layout1->addWidget(toolBtn1_5);
//插入一个占位符
layout1->addStretch(); //(i)
toolBtn2_1 =new QToolButton;
toolBtn2_1->setText(tr("小王"));
toolBtn2_1->setIcon(QPixmap("21.png"));
toolBtn2_1->setIconSize(QPixmap("21.png").size());
toolBtn2_1->setAutoRaise(true);
toolBtn2_1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolBtn2_2 =new QToolButton;
toolBtn2_2->setText(tr("小张"));
toolBtn2_2->setIcon(QPixmap("22.png"));
toolBtn2_2->setIconSize(QPixmap("22.png").size());
toolBtn2_2->setAutoRaise(true);
toolBtn2_2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
QGroupBox *groupBox2=new QGroupBox;
QVBoxLayout *layout2=new QVBoxLayout(groupBox2);
layout2->setMargin(10);
layout2->setAlignment(Qt::AlignHCenter);
layout2->addWidget(toolBtn2_1);
layout2->addWidget(toolBtn2_2);
toolBtn3_1 =new QToolButton;
toolBtn3_1->setText(tr("小陈"));
toolBtn3_1->setIcon(QPixmap("31.png"));
toolBtn3_1->setIconSize(QPixmap("31.png").size());
toolBtn3_1->setAutoRaise(true);
toolBtn3_1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toolBtn3_2 =new QToolButton;
toolBtn3_2->setText(tr("小李"));
toolBtn3_2->setIcon(QPixmap("32.png"));
toolBtn3_2->setIconSize(QPixmap("32.png").size());
toolBtn3_2->setAutoRaise(true);
toolBtn3_2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
QGroupBox *groupBox3=new QGroupBox;
QVBoxLayout *layout3=new QVBoxLayout(groupBox3);
layout3->setMargin(10);
layout3->setAlignment(Qt::AlignHCenter);
layout3->addWidget(toolBtn3_1);
layout3->addWidget(toolBtn3_2);
//将准备好的抽屉插入ToolBox中
this->addItem((QWidget*)groupBox1,tr("我的好友"));
this->addItem((QWidget*)groupBox2,tr("陌生人"));
this->addItem((QWidget*)groupBox3,tr("黑名单"));
}
其中,
(a) toolBtn1_1 =new QToolButton:创建一个QToolButton类实例,分别对应于抽屉中的每个按钮。
(b) toolBtn1_1->setText(tr("张三")):设置按钮的文字。
(c) toolBtn1_1->setIcon(QPixmap("11.png")):设置按钮的图标。
(d)toolBtn1_1->setIconSize(QPixmap("11.png").size()):设置按钮的大小,本例将其设置为与图标的大小相同。
(e) toolBtn1_1->setAutoRaise(true):当鼠标离开时,按钮自动恢复为弹起状态。
(f) toolBtn1_1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon):设置按钮的ToolButtonStyle属性。
(g) QGroupBox *groupBox1=new QGroupBox:创建一个QGroupBox类实例,在本例中对应每一个抽屉。QGroupBox *groupBox2=new QGroupBox、QGroupBox *groupBox3=new QGroupBox创建其余两栏抽屉。
(h) QVBoxLayout *layout1=new QVBoxLayout(groupBox1):创建一个QVBoxLayout类实例,用来设置抽屉内各个按钮的布局。
(i) layout1->addStretch():在按钮之后插入一个占位符,使得所有按钮能够靠上对齐,并且在整个抽屉大小发生改变时保证按钮的大小不发生变化。
三、进 度 条
Qt提供了两种显示进度条的方式:一种是QProgressBar(如图4.9所示),提供了一种横向或纵向显示进度的控件表示方式,用来描述任务的完成情况;另一种是QProgressDialog(如图4.10所示),提供了一种针对慢速过程的进度对话框表示方式,用于描述任务完成的进度情况。标准的进度条对话框包括一个进度显示条、一个“取消(Cancel)”按钮及一个标签。
【例】(简单)(CH403)实现图4.9和图4.10中的显示进度条。
实现步骤如下。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“Progress”,基类选择“QDialog”,类名命名为“ProgressDlg”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该文件工程的建立。
(2)ProgressDlg类继承自QDialog类,打开“progressdlg.h”头文件,添加如下加黑代码。
#ifndef PROGRESSDLG_H
#define PROGRESSDLG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QProgressBar>
#include <QComboBox>
#include <QPushButton>
#include <QGridLayout>
class ProgressDlg : public QDialog
{
Q_OBJECT
public:
ProgressDlg(QWidget *parent = 0);
~ProgressDlg();
private slots:
void startProgress();
private:
QLabel *FileNum;
QLineEdit *FileNumLineEdit;
QLabel *ProgressType;
QComboBox *comboBox;
QProgressBar *progressBar;
QPushButton *starBtn;
QGridLayout *mainLayout;
};
#endif // PROGRESSDLG_H
(3)构造函数主要完成主界面的初始化工作,包括各控件的创建、布局及信号/槽的连接。打开“progressdlg.cpp”文件,添加以下代码。
#include "progressdlg.h"
#include <QProgressDialog>
#include <QFont>
ProgressDlg::ProgressDlg(QWidget *parent)
: QDialog(parent)
{
QFont font("ZYSong18030",12);
setFont(font);
setWindowTitle(tr("Progress"));
FileNum =new QLabel;
FileNum->setText(tr("文件数目:"));
FileNumLineEdit =new QLineEdit;
FileNumLineEdit->setText(tr("100000"));
ProgressType =new QLabel;
ProgressType->setText(tr("显示类型:"));
comboBox =new QComboBox;
comboBox->addItem(tr("progressBar"));
comboBox->addItem(tr("progressDialog"));
progressBar =new QProgressBar;
starBtn =new QPushButton();
starBtn->setText(tr("开始"));
mainLayout =new QGridLayout(this);
mainLayout->addWidget(FileNum,0,0);
mainLayout->addWidget(FileNumLineEdit,0,1);
mainLayout->addWidget(ProgressType,1,0);
mainLayout->addWidget(comboBox,1,1);
mainLayout->addWidget(progressBar,2,0,1,2);
mainLayout->addWidget(starBtn,3,1);
mainLayout->setMargin(15);
mainLayout->setSpacing(10);
connect(starBtn,SIGNAL(clicked()),this,SLOT(startProgress()));
}
void ProgressDlg::startProgress()
{
bool ok;
int num =FileNumLineEdit->text().toInt(&ok);//(a)
if(comboBox->currentIndex()==0) //采用进度条的方式显示进度
{
progressBar->setRange(0,num); //(b)
for(int i=1;i<num+1;i++)
{
progressBar->setValue(i); //(c)
}
}
else if(comboBox->currentIndex()==1) //采用进度对话框显示进度
{
//创建一个进度对话框
QProgressDialog *progressDialog=new QProgressDialog(this);
QFont font("ZYSong18030",12);
progressDialog->setFont(font);
progressDialog->setWindowModality(Qt::WindowModal); //(d)
progressDialog->setMinimumDuration(5); //(e)
progressDialog->setWindowTitle(tr("Please Wait")); //(f)
progressDialog->setLabelText(tr("Copying...")); //(g)
progressDialog->setCancelButtonText(tr("Cancel")); //(h)
progressDialog->setRange(0,num); //设置进度对话框的步进范围
for(int i=1;i<num+1;i++)
{
progressDialog->setValue(i); //(i)
if(progressDialog->wasCanceled()) //(j)
return;
}
}
}
ProgressDlg::~ProgressDlg()
{
}
其中,
(a) int num =FileNumLineEdit->text().toInt(&ok):获取当前需要复制的文件数目,这里对应进度条的总步进值。
(b) progressBar->setRange(0,num):设置进度条的步进范围从0到需要复制的文件数目。
(c) progressBar->setValue(i):模拟每一个文件的复制过程,进度条总的步进值为需要复制的文件数目。当复制完一个文件后,步进值增加1。
(d) progressDialog->setWindowModality(Qt::WindowModal):设置进度对话框采用模态方式进行显示,即在显示进度的同时,其他窗口将不响应输入信号。
(e) progressDialog->setMinimumDuration(5):设置进度对话框出现需等待的时间,此处设定为5秒(s),默认为4秒。
(f) progressDialog->setWindowTitle(tr("Please Wait")):设置进度对话框的窗体标题。
(g) progressDialog->setLabelText(tr("Copying...")):设置进度对话框的显示文字信息。
(h) progressDialog->setCancelButtonText(tr("Cancel")):设置进度对话框的“取消”按钮的显示文字。
(i) progressDialog->setValue(i):模拟每个文件的复制过程,进度条总的步进值为需要复制的文件数目。当复制完一个文件后,步进值增加1。
(j) if(progressDialog->wasCanceled()):检测“取消”按钮是否被触发,若触发则退出循环并关闭进度对话框。
QProgressBar类有如下几个重要的属性。
minimum、maximum:决定进度条指示的最小值和最大值。
format:决定进度条显示文字的格式,可以有三种显示格式,即%p%、%v和%m。其中,%p%显示完成的百分比,这是默认显示方式;%v显示当前的进度值;%m显示总的步进值。
invertedAppearance:可以使进度条以反方向显示进度。
QProgressDialog类也有几个重要的属性值,决定了进度条对话框何时出现、出现多长时间。它们分别是mininum、maximum和minimumDuration。其中,mininum和maximum分别表示进度条的最小值和最大值,决定了进度条的变化范围;minimumDuration为进度条对话框出现前的等待时间。 进度条使用了一个步进值的概念,即一旦设置好进度条的最大值和最小值,进度条将会显示完成的步进值占总的步进值的百分比,百分比的计算公式为:
百分比=(value()-minimum())/(maximum()-minimum())
四、调色板与电子钟
1、QPalette类
在本节中详细介绍QPalette类的使用方法,该类有两个基本的概念:一个是ColorGroup,另一个是ColorRole。其中,ColorGroup指的是以下三种不同的状态。
QPalette::Active:获得焦点的状态。
QPalette::Inactive:未获得焦点的状态。
QPalette::Disable:不可用状态。
其中,Active状态与Inactive状态在通常情况下,颜色显示是一致的,也可以根据需要设置为不一样的颜色。
ColorRole指的是颜色主题,即对窗体中不同部位颜色的分类。例如,QPalette::Window是指背景色,QPalette::WindowText是指前景色,等等。
QPalette类使用最多、最重要的函数是setColor()函数,其原型如下:
void QPalette::setColor(ColorGroup group,ColorRole role,const QColor & color);
在对主题颜色进行设置的同时,还区分了状态,即对某个主题在某个状态下的颜色进行了设置: void QPalette::setColor(ColorRole role,const QColor & color);
只对某个主题的颜色进行设置,并不区分状态。
QPalette类同时还提供了setBrush()函数,通过画刷的设置对显示进行更改,这样就有可能使用图片而不仅是单一的颜色来对主题进行填充。Qt之前的版本中有关背景色设置的函数如setBackgroundColor()或前景色设置的函数如setForegroundColor()在Qt 5中都被废止,统一由QPalette类进行管理。例如,setBackgroundColor()函数可由以下语句代替:
xxx->setAutoFillBackground(true);
QPalette p = xxx->palette();
p.setColor(QPalette::Window,color);//p.setBrush(QPalette::Window,brush);
xxx->setPalette(p);
【例】(难度一般)(CH404)利用QPalette改变控件颜色的方法。本实例实现的窗体分为两部分:左半部分用于对不同主题颜色的选择,右半部分用于显示选择的颜色对窗体外观的改变。运行效果如图4.11所示。
实现步骤如下。
(1)新建Qt Widgets Application (详见1.3.1节),项目名称为“Palette”,基类选择“QDialog”,类名命名为“Palette”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。
(2)定义的Palette类继承自QDialog类,打开“palette.h”文件,声明实例中所用到的函数和控件,具体代码。
#ifndef PALETTE_H
#define PALETTE_H
#include <QDialog>
#include <QComboBox>
#include <QLabel>
#include <QTextEdit>
#include <QPushButton>
#include <QLineEdit>
class Palette : public QDialog
{
Q_OBJECT
public:
Palette(QWidget *parent = 0);
~Palette();
void createCtrlFrame(); //完成窗体左半部分颜色选择区的创建
void createContentFrame(); //完成窗体右半部分的创建
void fillColorList(QComboBox *);
//完成向颜色下拉列表框中插入颜色的工作
private slots:
void ShowWindow();
void ShowWindowText();
void ShowButton();
void ShowButtonText();
void ShowBase();
private:
QFrame *ctrlFrame; //颜色选择面板
QLabel *windowLabel;
QComboBox *windowComboBox;
QLabel *windowTextLabel;
QComboBox *windowTextComboBox;
QLabel *buttonLabel;
QComboBox *buttonComboBox;
QLabel *buttonTextLabel;
QComboBox *buttonTextComboBox;
QLabel *baseLabel;
QComboBox *baseComboBox;
QFrame *contentFrame; //具体显示面板
QLabel *label1;
QComboBox *comboBox1;
QLabel *label2;
QLineEdit *lineEdit2;
QTextEdit *textEdit;
QPushButton *OkBtn;
QPushButton *CancelBtn;
};
#endif // PALETTE_H
(3)打开“palette.cpp”文件,添加以下代码:
#include "palette.h"
#include <QHBoxLayout>
#include <QGridLayout>
Palette::Palette(QWidget *parent)
: QDialog(parent)
{
createCtrlFrame();
createContentFrame();
QHBoxLayout *mainLayout =new QHBoxLayout(this);
mainLayout->addWidget(ctrlFrame);
mainLayout->addWidget(contentFrame);
}
void Palette::createCtrlFrame()
{
ctrlFrame =new QFrame; //颜色选择面板
windowLabel =new QLabel(tr("QPalette::Window: "));
windowComboBox =new QComboBox; //创建一个QComboBox对象
fillColorList(windowComboBox); //(a)
connect(windowComboBox,SIGNAL(activated(int)),this,SLOT(ShowWindow()));//(b)
windowTextLabel =new QLabel(tr("QPalette::WindowText: "));
windowTextComboBox =new QComboBox;
fillColorList(windowTextComboBox);
connect(windowTextComboBox,SIGNAL(activated(int)),this,SLOT(ShowWindowText()));
buttonLabel =new QLabel(tr("QPalette::Button: "));
buttonComboBox =new QComboBox;
fillColorList(buttonComboBox);
connect(buttonComboBox,SIGNAL(activated(int)),this,SLOT(ShowButton()));
buttonTextLabel =new QLabel(tr("QPalette::ButtonText: "));
buttonTextComboBox =new QComboBox;
fillColorList(buttonTextComboBox);
connect(buttonTextComboBox,SIGNAL(activated(int)),this,SLOT(ShowButtonText()));
baseLabel =new QLabel(tr("QPalette::Base: "));
baseComboBox =new QComboBox;
fillColorList(baseComboBox);
connect(baseComboBox,SIGNAL(activated(int)),this,SLOT(ShowBase()));
QGridLayout *mainLayout=new QGridLayout(ctrlFrame);
mainLayout->setSpacing(20);
mainLayout->addWidget(windowLabel,0,0);
mainLayout->addWidget(windowComboBox,0,1);
mainLayout->addWidget(windowTextLabel,1,0);
mainLayout->addWidget(windowTextComboBox,1,1);
mainLayout->addWidget(buttonLabel,2,0);
mainLayout->addWidget(buttonComboBox,2,1);
mainLayout->addWidget(buttonTextLabel,3,0);
mainLayout->addWidget(buttonTextComboBox,3,1);
mainLayout->addWidget(baseLabel,4,0);
mainLayout->addWidget(baseComboBox,4,1);
}
void Palette::createContentFrame()
{
contentFrame =new QFrame; //具体显示面板
label1 =new QLabel(tr("请选择一个值:"));
comboBox1 =new QComboBox;
label2 =new QLabel(tr("请输入字符串:"));
lineEdit2 =new QLineEdit;
textEdit =new QTextEdit;
QGridLayout *TopLayout =new QGridLayout;
TopLayout->addWidget(label1,0,0);
TopLayout->addWidget(comboBox1,0,1);
TopLayout->addWidget(label2,1,0);
TopLayout->addWidget(lineEdit2,1,1);
TopLayout->addWidget(textEdit,2,0,1,2);
OkBtn =new QPushButton(tr("确认"));
CancelBtn =new QPushButton(tr("取消"));
QHBoxLayout *BottomLayout =new QHBoxLayout;
BottomLayout->addStretch(1);
BottomLayout->addWidget(OkBtn);
BottomLayout->addWidget(CancelBtn);
QVBoxLayout *mainLayout =new QVBoxLayout(contentFrame);
mainLayout->addLayout(TopLayout);
mainLayout->addLayout(BottomLayout);
}
void Palette::ShowWindow()
{
//获得当前选择的颜色值
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[windowComboBox->currentIndex()]);
QPalette p = contentFrame->palette(); //(a)
p.setColor(QPalette::Window,color); //(b)
//把修改后的调色板信息应用到contentFrame窗体中,更新显示
contentFrame->setPalette(p);
contentFrame->update();
}
void Palette::ShowWindowText()
{
QStringList colorList = QColor::colorNames();
QColor color = colorList[windowTextComboBox->currentIndex()];
QPalette p = contentFrame->palette();
p.setColor(QPalette::WindowText,color);
contentFrame->setPalette(p);
}
void Palette::ShowButton()
{
QStringList colorList = QColor::colorNames();
QColor color =QColor(colorList[buttonComboBox->currentIndex()]);
QPalette p = contentFrame->palette();
p.setColor(QPalette::Button,color);
contentFrame->setPalette(p);
contentFrame->update();
}
void Palette::ShowButtonText()
{
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[buttonTextComboBox->currentIndex()]);
QPalette p =contentFrame->palette();
p.setColor(QPalette::ButtonText,color);
contentFrame->setPalette(p);
}
void Palette::ShowBase()
{
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[baseComboBox->currentIndex()]);
QPalette p = contentFrame->palette();
p.setColor(QPalette::Base,color);
contentFrame->setPalette(p);
}
void Palette::fillColorList(QComboBox *comboBox)
{
QStringList colorList = QColor::colorNames(); //(a)
QString color; //(b)
foreach(color,colorList) //对颜色名列表进行遍历
{
QPixmap pix(QSize(70,20)); //(c)
pix.fill(QColor(color)); //为pix填充当前遍历的颜色
comboBox->addItem(QIcon(pix),NULL); //(d)
comboBox->setIconSize(QSize(70,20)); //(e)
comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
//(f)
}
}
Palette::~Palette()
{
}
createCtrlFrame()函数用于创建颜色选择区。
其中,
(a) fillColorList(windowComboBox):向下拉列表框中插入各种不同的颜色选项。
(b) connect(windowComboBox,SIGNAL(activated(int)),this,SLOT(ShowWindow())):连接下拉列表框的activated()信号与改变背景色的槽函数ShowWindow()。
createContentFrame()函数用于显示选择的颜色对窗体外观的改变,具体代码如下:
void Palette::createContentFrame()
{
contentFrame =new QFrame; //具体显示面板
label1 =new QLabel(tr("请选择一个值:"));
comboBox1 =new QComboBox;
label2 =new QLabel(tr("请输入字符串:"));
lineEdit2 =new QLineEdit;
textEdit =new QTextEdit;
QGridLayout *TopLayout =new QGridLayout;
TopLayout->addWidget(label1,0,0);
TopLayout->addWidget(comboBox1,0,1);
TopLayout->addWidget(label2,1,0);
TopLayout->addWidget(lineEdit2,1,1);
TopLayout->addWidget(textEdit,2,0,1,2);
OkBtn =new QPushButton(tr("确认"));
CancelBtn =new QPushButton(tr("取消"));
QHBoxLayout *BottomLayout =new QHBoxLayout;
BottomLayout->addStretch(1);
BottomLayout->addWidget(OkBtn);
BottomLayout->addWidget(CancelBtn);
QVBoxLayout *mainLayout =new QVBoxLayout(contentFrame);
mainLayout->addLayout(TopLayout);
mainLayout->addLayout(BottomLayout);
}
ShowWindow()函数用于响应对背景颜色的选择:
void Palette::ShowWindow()
{
//获得当前选择的颜色值
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[windowComboBox->currentIndex()]);
QPalette p = contentFrame->palette(); //(a)
p.setColor(QPalette::Window,color); //(b)
//把修改后的调色板信息应用到contentFrame窗体中,更新显示
contentFrame->setPalette(p);
contentFrame->update();
}
其中, (a) QPalette p = contentFrame->palette():获得右部窗体contentFrame的调色板信息。 (b) p.setColor(QPalette::Window,color):设置contentFrame窗体的Window类颜色,即背景色,setColor()的第一个参数为设置的颜色主题,第二个参数为具体的颜色值。
ShowWindowText()函数响应对文字颜色的选择,即对前景色进行设置,具体代码如下:
void Palette::ShowWindowText()
{
QStringList colorList = QColor::colorNames();
QColor color = colorList[windowTextComboBox->currentIndex()];
QPalette p = contentFrame->palette();
p.setColor(QPalette::WindowText,color);
contentFrame->setPalette(p);
}
ShowButton()函数响应对按钮背景色的选择:
void Palette::ShowButton()
{
QStringList colorList = QColor::colorNames();
QColor color =QColor(colorList[buttonComboBox->currentIndex()]);
QPalette p = contentFrame->palette();
p.setColor(QPalette::Button,color);
contentFrame->setPalette(p);
contentFrame->update();
}
ShowButtonText()函数响应对按钮上文字颜色的选择:
void Palette::ShowButtonText()
{
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[buttonTextComboBox->currentIndex()]);
QPalette p =contentFrame->palette();
p.setColor(QPalette::ButtonText,color);
contentFrame->setPalette(p);
}
ShowBase()函数响应对可输入文本框背景色的选择:
void Palette::ShowBase()
{
QStringList colorList = QColor::colorNames();
QColor color = QColor(colorList[baseComboBox->currentIndex()]);
QPalette p = contentFrame->palette();
p.setColor(QPalette::Base,color);
contentFrame->setPalette(p);
}
fillColorList()函数用于插入颜色:
void Palette::fillColorList(QComboBox *comboBox)
{
QStringList colorList = QColor::colorNames(); //(a)
QString color; //(b)
foreach(color,colorList) //对颜色名列表进行遍历
{
QPixmap pix(QSize(70,20)); //(c)
pix.fill(QColor(color)); //为pix填充当前遍历的颜色
comboBox->addItem(QIcon(pix),NULL); //(d)
comboBox->setIconSize(QSize(70,20)); //(e)
comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
//(f)
}
}
其中,
(a) QStringList colorList = QColor::colorNames():获得Qt所有内置名称的颜色名列表,返回的是一个字符串列表colorList。
(b) QString color:新建一个QString对象,为循环遍历做准备。
(c) QPixmap pix(QSize(70,20)):新建一个QPixmap对象pix作为显示颜色的图标。
(d) comboBox->addItem(QIcon(pix),NULL):调用QComboBox的addItem()函数为下拉列表框插入一个条目,并以准备好的pix作为插入条目的图标,名称设为NULL,即不显示颜色的名称。
(e) comboBox->setIconSize(QSize(70,20)):设置图标的尺寸,图标默认尺寸是一个方形,将它设置为与pix尺寸相同的长方形。
(f) comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents):设置下拉列表框的尺寸调整策略为AdjustToContents(符合内容的大小)。
(4)运行程序,显示效果如图4.11所示。
2、QTime类
QTime的currentTime()函数用于获取当前的系统时间;QTime的toString()函数用于将获取的当前时间转换为字符串类型。为了便于显示,toString()函数的参数需指定转换后时间的显示格式。
H/h:小时(若使用H表示小时,则无论何时都以24小时制显示小时;若使用h表示小时,则当同时指定AM/PM时,采用12小时制显示小时,其他情况下仍采用24小时制进行显示)。
m:分。
s:秒。
AP/A:显示AM或PM。
Ap/a:显示am或pm。 可根据实际显示需要进行格式设置,例如:
hh:mm:ss A 22:30:08 PM
H:mm:s a 10:30:8 pm
2.1【综合实例】电子时钟
【例】(难度一般)(CH405)通过实现显示于桌面上并可随意拖曳至桌面任意位置的电子时钟综合实例,实践QPalette类、QTime类和mousePressEvent/mouseMoveEvent类的用法。
实现步骤如下。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“Clock”,基类选择“QDialog”,取消“创建界面”复选框的选中状态。
(2)添加该工程的提供主要显示界面的函数所在的文件,在“Clock”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项,单击“Choose...”按钮,在弹出的对话框的“Base class”文本框中输入基类名“QLCDNumber”(手工添加),在“Class name”文本框中输入类的名称“DigiClock”。
(3)单击“下一步”按钮,单击“完成”按钮,添加“digiclock.h”头文件和“digiclock.cpp”源文件。
(4)DigiClock类继承自QLCDNumber类,该类中重定义了鼠标按下事件和鼠标移动事件以使电子时钟可随意拖曳,同时还定义了相关的槽函数和私有变量。打开“digiclock.h”文件,添加如下代码:
#ifndef DIGICLOCK_H
#define DIGICLOCK_H
#include <QLCDNumber>
class DigiClock : public QLCDNumber
{
Q_OBJECT
public:
DigiClock(QWidget *parent=0);
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
public slots:
void showTime(); //显示当前的时间
private:
QPoint dragPosition; //保存鼠标点相对电子时钟窗体左上角的偏移值
bool showColon; //用于显示时间时是否显示“:”
};
#endif // DIGICLOCK_H
(5)在DigiClock的构造函数中,完成外观的设置及定时器的初始化工作,打开“digiclock.cpp”文件,添加下列代码:
#include "digiclock.h"
#include <QTimer>
#include <QTime>
#include <QMouseEvent>
DigiClock::DigiClock(QWidget *parent):QLCDNumber(parent)
{
/* 设置时钟背景 */ //(a)
QPalette p=palette();
p.setColor(QPalette::Window,Qt::blue);
setPalette(p);
setWindowFlags(Qt::FramelessWindowHint); //(b)
setWindowOpacity(0.5); //(c)
QTimer *timer=new QTimer(this); //新建一个定时器对象
connect(timer,SIGNAL(timeout()),this,SLOT(showTime())); //(d)
timer->start(1000); //(e)
showTime(); //初始时间显示
resize(150,60); //设置电子时钟显示的尺寸
showColon=true; //初始化
}
void DigiClock::showTime()
{
QTime time=QTime::currentTime(); //(a)
QString text=time.toString("hh:mm"); //(b)
if(showColon) //(c)
{
text[2]=':';
showColon=false;
}
else
{
text[2]=' ';
showColon=true;
}
display(text); //显示转换好的字符串时间
}
void DigiClock::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
dragPosition=event->globalPos()-frameGeometry().topLeft();
event->accept();
}
if(event->button()==Qt::RightButton)
{
close();
}
}
void DigiClock::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons()&Qt::LeftButton)
{
move(event->globalPos()-dragPosition);
event->accept();
}
}
其中,
(a) QPalette p=palette()、p.setColor(QPalette::Window,Qt::blue)、setPalette(p):完成电子时钟窗体背景色的设置,此处设置背景色为蓝色。QPalette类的具体详细用法参照4.9.1节。
(b) setWindowFlags(Qt::FramelessWindowHint):设置窗体的标识,此处设置窗体为一个没有面板边框和标题栏的窗体。
(c) setWindowOpacity(0.5):设置窗体的透明度为0.5,即半透明。但此函数在X11系统中并不起作用,当程序在Windows系统下编译运行时,此函数才起作用,即电子时钟半透明显示。
(d) connect(timer,SIGNAL(timeout()),this,SLOT(showTime())):连接定时器的timeout()信号与显示时间的槽函数showTime()。
(e) timer->start(1000):以1000毫秒(ms)为周期启动定时器。
槽函数showTime()完成电子钟的显示时间的功能。具体代码如下:
void DigiClock::showTime()
{
QTime time=QTime::currentTime(); //(a)
QString text=time.toString("hh:mm"); //(b)
if(showColon) //(c)
{
text[2]=':';
showColon=false;
}
else
{
text[2]=' ';
showColon=true;
}
display(text); //显示转换好的字符串时间
}
其中,
(a) QTime time=QTime::currentTime():获取当前的系统时间,保存在一个QTime对象中。
(b) QString text=time.toString("hh:mm"):把获取的当前时间转换为字符串类型。QTime类的详细介绍参照4.9.2节。
(c) showColon:控制电子时钟“时”与“分”之间表示秒的两个点的闪显功能。
(6)通过执行鼠标按下事件响应函数mousePressEvent(QMouseEvent*)和鼠标移动事件响应函数mouseMoveEvent(QMouseEvent*)的重定义,可以实现用鼠标在桌面上随意拖曳电子时钟。
在鼠标按下响应函数mousePressEvent(QMouseEvent*)中,首先判断按下的键是否为鼠标左键。若按下的键是鼠标左键,则保存当前鼠标点所在的位置相对于窗体左上角的偏移值dragPosition;若按下的键是鼠标右键,则退出窗体。
在鼠标移动响应函数mouseMoveEvent(QMouseEvent*)中,首先判断当前鼠标状态。调用event->buttons()返回鼠标的状态,若为左侧按键,则调用QWidget的move()函数将窗体移动至鼠标当前点。由于move()函数的参数指的是窗体的左上角的位置,所以要使用鼠标当前点的位置减去相对窗体左上角的偏移值dragPosition。
以上函数的具体代码如下:
void DigiClock::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
dragPosition=event->globalPos()-frameGeometry().topLeft();
event->accept();
}
if(event->button()==Qt::RightButton)
{
close();
}
}
void DigiClock::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons()&Qt::LeftButton)
{
move(event->globalPos()-dragPosition);
event->accept();
}
}
(7)在“main.cpp”文件中添加以下代码:
#include "dialog.h"
#include <QApplication>
#include "digiclock.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
DigiClock clock;
clock.show();
//Dialog w;
//w.show();
return a.exec();
}
五、可扩展对话框
可扩展对话框的基本实现方法是利用setSizeConstraint(QLayout::SetFixedSize)方法使对话框尺寸保持相对固定。其中,最关键的部分有以下两点。
在整个对话框的构造函数中调用。
layout->setSizeConstraint(QLayout::SetFixedSize);
这个设置保证了对话框的尺寸保持相对固定,始终保持各个控件组合的默认尺寸。在扩展部分显示时,对话框尺寸根据需要显示的控件被扩展;而在扩展部分隐藏时,对话框尺寸又恢复至初始状态。
切换按钮的实现。整个窗体可扩展的工作都是在此按钮所连接的槽函数中完成的。
【例】(难度一般)(CH406)简单地填写资料。通常情况下,只需填写姓名和性别。若有特殊需要,还需填写更多信息时,则切换至完整对话窗体,运行效果如图4.13所示。
如图4.13(b)所示是单击如图4.13(a)所示中的“详细”按钮后展开的对话框,再次单击“详细”按钮,扩展开的部分又重新隐藏。
实现步骤如下。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“ExtensionDlg”,基类选择“QDialog”,类名命名为“ExtensionDlg”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。
(2)ExtensionDlg类继承自QDialog,打开“extensiondlg.h”头文件,具体代码如下:
#ifndef EXTENSIONDLG_H
#define EXTENSIONDLG_H
#include <QDialog>
class ExtensionDlg : public QDialog
{
Q_OBJECT
public:
ExtensionDlg(QWidget *parent = 0);
~ExtensionDlg();
private slots:
void showDetailInfo();
private:
void createBaseInfo(); //实现基本对话窗体部分
void createDetailInfo(); //实现扩展窗体部分
QWidget *baseWidget; //基本对话窗体部分
QWidget *detailWidget; //扩展窗体部分
};
#endif // EXTENSIONDLG_H
(3)打开“extensiondlg.cpp”源文件,添加以下代码:
#include "extensiondlg.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QPushButton>
#include <QDialogButtonBox>
#include <QHBoxLayout>
ExtensionDlg::ExtensionDlg(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("Extension Dialog")); //设置对话框的标题栏信息
createBaseInfo();
createDetailInfo();
QVBoxLayout *layout =new QVBoxLayout(this); //布局
layout->addWidget(baseWidget);
layout->addWidget(detailWidget);
layout->setSizeConstraint(QLayout::SetFixedSize); //(a)
layout->setSpacing(10);
}
void ExtensionDlg::createBaseInfo()
{
baseWidget =new QWidget;
QLabel *nameLabel =new QLabel(tr("姓名:"));
QLineEdit *nameLineEdit =new QLineEdit;
QLabel *sexLabel =new QLabel(tr("性别:"));
QComboBox *sexComboBox =new QComboBox;
sexComboBox->insertItem(0,tr("女"));
sexComboBox->insertItem(1,tr("男"));
QGridLayout *LeftLayout =new QGridLayout;
LeftLayout->addWidget(nameLabel,0,0);
LeftLayout->addWidget(nameLineEdit,0,1);
LeftLayout->addWidget(sexLabel);
LeftLayout->addWidget(sexComboBox);
QPushButton *OKBtn =new QPushButton(tr("确定"));
QPushButton *DetailBtn =new QPushButton(tr("详细"));
QDialogButtonBox *btnBox =new QDialogButtonBox(Qt::Vertical);
btnBox->addButton(OKBtn,QDialogButtonBox::ActionRole);
btnBox->addButton(DetailBtn,QDialogButtonBox::ActionRole);
QHBoxLayout *mainLayout =new QHBoxLayout(baseWidget);
mainLayout->addLayout(LeftLayout);
mainLayout->addWidget(btnBox);
connect(DetailBtn,SIGNAL(clicked()),this,SLOT(showDetailInfo()));
}
void ExtensionDlg::createDetailInfo()
{
detailWidget =new QWidget;
QLabel *ageLabel =new QLabel(tr("年龄:"));
QLineEdit *ageLineEdit =new QLineEdit;
ageLineEdit->setText(tr("30"));
QLabel *departmentLabel =new QLabel(tr("部门:"));
QComboBox *departmentComBox =new QComboBox;
departmentComBox->addItem(tr("部门1"));
departmentComBox->addItem(tr("部门2"));
departmentComBox->addItem(tr("部门3"));
departmentComBox->addItem(tr("部门4"));
QLabel *emailLabel =new QLabel(tr("email:"));
QLineEdit *emailLineEdit =new QLineEdit;
QGridLayout *mainLayout =new QGridLayout(detailWidget);
mainLayout->addWidget(ageLabel,0,0);
mainLayout->addWidget(ageLineEdit,0,1);
mainLayout->addWidget(departmentLabel,1,0);
mainLayout->addWidget(departmentComBox,1,1);
mainLayout->addWidget(emailLabel,2,0);
mainLayout->addWidget(emailLineEdit,2,1);
detailWidget->hide();
}
void ExtensionDlg::showDetailInfo()
{
if(detailWidget->isHidden())
detailWidget->show();
else detailWidget->hide();
}
ExtensionDlg::~ExtensionDlg()
{
}
createBaseInfo()函数完成基本信息窗体部分的构建,其中,连接实现切换功能的“详细”按钮DetailBtn的clicked()信号与槽函数showDetailInfo()以实现对话框的可扩展
createDetailInfo()函数实现详细信息窗体部分detailWidget的构建,并在函数的最后调用hide()隐藏此部分窗体
showDetailInfo()函数完成窗体扩展切换工作,在用户单击DetailBtn时调用此函数,首先检测detailWidget窗体处于何种状态。若此时是隐藏状态,则应用show()函数显示detailWidget窗体,否则调用hide()函数隐藏detailWidget窗体。其具体实现代码如下:
六、不规则窗体
【例】(简单)(CH407)不规则窗体的实现方法。具体实现一个蝴蝶图形外沿形状的不规则形状对话框,也可以在不规则窗体上放置按钮等控件,可以通过鼠标左键拖曳窗体,单击鼠标右键关闭窗体。运行效果如图4.14所示。
实现步骤如下。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“ShapeWidget”,基类选择“QWidget”,类名命名为“ShapeWidget”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。
(2)不规则窗体类ShapeWidget继承自QWidget类,为了使不规则窗体能够通过鼠标随意拖曳,在该类中重定义了鼠标事件函数mousePressEvent()、mouseMoveEvent()及绘制函数paintEvent(),打开“shapewidget.h”头文件,添加如下代码:
#ifndef SHAPEWIDGET_H
#define SHAPEWIDGET_H
#include <QWidget>
class ShapeWidget : public QWidget
{
Q_OBJECT
public:
ShapeWidget(QWidget *parent = 0);
~ShapeWidget();
protected:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
private:
QPoint dragPosition;
};
#endif // SHAPEWIDGET_H
(3)打开“shapewidget.cpp”文件,ShapeWidget的构造函数部分是实现不规则窗体的关键,添加的具体代码如下:
#include "shapewidget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QPixmap>
#include <QBitmap>
ShapeWidget::ShapeWidget(QWidget *parent)
: QWidget(parent)
{
QPixmap pix; //新建一个QPixmap对象
pix.load("16.png",0,Qt::AvoidDither|Qt::ThresholdDither|Qt::ThresholdAlphaDither); //(a)
resize(pix.size()); //(b)
setMask(QBitmap(pix.mask())); //(c)
}
void ShapeWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
dragPosition =event->globalPos()-frameGeometry().topLeft();
event->accept();
}
if(event->button()==Qt::RightButton)
{
close();
}
}
void ShapeWidget::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons()&Qt::LeftButton)
{
move(event->globalPos()-dragPosition);
event->accept();
}
}
void ShapeWidget::paintEvent(QPaintEvent * event)
{
QPainter painter(this);
painter.drawPixmap(0,0,QPixmap("16.png"));
}
ShapeWidget::~ShapeWidget()
{
}
其中,
(a)pix.load("16.png",0,Qt::AvoidDither|Qt::ThresholdDither|Qt::ThresholdAlphaDither):调用QPixmap的load()函数为QPixmap对象填入图像值。 load()函数的原型如下:
bool QPixmap::load ( const QString & fileName, const char * format = 0, Qt:: ImageConversionFlags flags = Qt::AutoColor )
(b) resize(pix.size()):重设主窗体的尺寸为所读取的图片的大小。
(c) setMask(QBitmap(pix.mask())):为调用它的控件增加一个遮罩,遮住所选区域以外的部分使其看起来是透明的,它的参数可为一个QBitmap对象或一个QRegion对象,此处调用QPixmap的mask()函数用于获得图片自身的遮罩,为一个QBitmap对象,实例中使用的是PNG格式的图片,它的透明部分实际上是一个遮罩。
鼠标移动响应函数mouseMoveEvent(QMouseEvent*),首先判断当前鼠标状态,调用event-> buttons()返回鼠标的状态,若为左键则调用QWidget的move()函数将窗体移动至鼠标当前点。由于move()函数的参数指的是窗体的左上角的位置,因此要使用鼠标当前点的位置减去相对窗体左上角的偏移值dragPosition。具体的实现代码如下:
void ShapeWidget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton)
{
dragPosition =event->globalPos()-frameGeometry().topLeft();
event->accept();
}
if(event->button()==Qt::RightButton)
{
close();
}
}
void ShapeWidget::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons()&Qt::LeftButton)
{
move(event->globalPos()-dragPosition);
event->accept();
}
}
重画函数paintEvent()主要完成在窗体上绘制图片的工作。此处为方便显示在窗体上,所绘制的是用来确定窗体外形的PNG图片。具体实现代码如下:
void ShapeWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0,0,QPixmap("16.png"));
}
七、程序启动画面(QSplashScreen)
【例】(简单)(CH408)程序启动画面(QSplashScreen)的使用方法。当运行程序时,在显示屏的中央出现一个启动画面,经过一段时间,在应用程序完成初始化工作后,启动画面隐去,出现程序的主窗口界面。
实现方法如下。
(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“SplashSreen”,基类选择“QMainWindow”,类名命名为“MainWindow”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。
(2)主窗体MainWindow类继承自QMainWindow类,模拟一个程序的启动,打开“mainwindow.h”头文件,自动生成的代码如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QTextEdit>
#include <windows.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("Splash Example");
QTextEdit *edit=new QTextEdit;
edit->setText("Splash Example!");
setCentralWidget(edit);
resize(600,450);
Sleep(1000); //(a)
}
MainWindow::~MainWindow()
{
}
(4)启动画面主要在main()函数中实现,打开“main.cpp”文件,添加以下加黑代码:
#include "mainwindow.h"
#include <QApplication>
#include <QPixmap>
#include <QSplashScreen>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap("Qt.png"); //(a)
QSplashScreen splash(pixmap); //(b)
splash.show(); //显示此启动图片
a.processEvents(); //(c)
MainWindow w;
w.show();
splash.finish(&w); //(e)
return a.exec();
}
其中,
(a) QPixmap pixmap("Qt.png"):创建一个QPixmap对象,设置启动图片(这里设置为Qt的图标“Qt.png”)。
(b) QSplashScreen splash(pixmap):利用QPixmap对象创建一个QSplashScreen对象。
(c) a.processEvents():使程序在显示启动画面的同时仍能响应鼠标等其他事件。
(d) MainWindow w、w.show():正常创建主窗体对象,并调用show()函数显示。
(e) splash.finish(&w):表示在主窗体对象初始化完成后,结束启动画面。