18、登录对话框示例分析
登录对话框是应用程序中常用部件。
思考:如何开发一个可以在不同项目间复用的登录对话框?
登录对话框需求分析:可复用软件部件。获取用户名和密码。附加需求:随机验证码。
如何获取用户输入的用户名和密码?
如何在两个不同的对话框间传递数据?
通过附加的成员变量和成员函数完成不同对话框间的数据传递。
检查用户名和密码是否为空:提示错误
随机验证码:当验证码输入错误时进行提示,验证码随机刷新。
小结:登录对话框作为可复用的软件部件进行开发。对话框之间通过成员变量和成员函数传递数据。
将用户数据保存在私有成员变量中,通过公有成员函数进行数据传递。
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton TestBtn;
private slots:
void TestBtn_Clicked();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include "QLoginDialog.h"
#include <QDebug>
Widget::Widget(QWidget *parent) : QWidget(parent), TestBtn(this)
{
TestBtn.setText("Test Login Dialog");
setFixedSize(200, 50);
connect(&TestBtn, SIGNAL(clicked()), this, SLOT(TestBtn_Clicked()));
}
void Widget::TestBtn_Clicked()
{
QLoginDialog dlg;
if( dlg.exec() == QDialog::Accepted )
{
qDebug() << "User: " + dlg.getUser();
qDebug() << "Pwd: " + dlg.getPwd();
}
}
Widget::~Widget()
{
}
#ifndef _QLOGINDIALOG_H_
#define _QLOGINDIALOG_H_
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
class QLoginDialog : public QDialog
{
Q_OBJECT
private:
QLabel UserLabel;
QLabel PwdLabel;
QLineEdit UserEdit;
QLineEdit PwdEdit;
QPushButton LoginBtn;
QPushButton CancelBtn;
QString m_user; //保存用户名和密码
QString m_pwd;
private slots:
void LoginBtn_Clicked();
void CancelBtn_Clicked();
public:
QLoginDialog(QWidget *parent = 0);
QString getUser();
QString getPwd();
~QLoginDialog();
};
#endif
#include "QLoginDialog.h"
#include <QDebug>
QLoginDialog::QLoginDialog(QWidget* parent) : QDialog(parent, Qt::WindowCloseButtonHint),
UserLabel(this), PwdLabel(this), UserEdit(this), PwdEdit(this), LoginBtn(this), CancelBtn(this)
{
UserLabel.setText("User ID:");
UserLabel.move(20, 30);
UserLabel.resize(60, 25);
UserEdit.move(85, 30);
UserEdit.resize(180, 25);
PwdLabel.setText("Password:");
PwdLabel.move(20, 65);
PwdLabel.resize(60,25);
PwdEdit.move(85, 65);
PwdEdit.resize(180, 25);
PwdEdit.setEchoMode(QLineEdit::Password); //设置不显示
CancelBtn.setText("Cancel");
CancelBtn.move(85, 110);
CancelBtn.resize(85, 30);
LoginBtn.setText("Login");
LoginBtn.move(180, 110);
LoginBtn.resize(85, 30);
setWindowTitle("Login");
setFixedSize(285, 170); //固定大小
connect(&LoginBtn, SIGNAL(clicked()), this, SLOT(LoginBtn_Clicked()));
connect(&CancelBtn, SIGNAL(clicked()), this, SLOT(CancelBtn_Clicked()));
}
void QLoginDialog::LoginBtn_Clicked()
{
qDebug() << "LoginBtn_Clicked() Begin";
m_user = UserEdit.text().trimmed(); //取得用户输入
m_pwd = PwdEdit.text();
done(Accepted); //点击登录,返回
qDebug() << "LoginBtn_Clicked() End";
}
void QLoginDialog::CancelBtn_Clicked()
{
qDebug() << "CancelBtn_Clicked() Begin";
done(Rejected); //点击取消,返回
qDebug() << "CancelBtn_Clicked() End";
}
QString QLoginDialog::getUser()
{
return m_user;
}
QString QLoginDialog::getPwd()
{
return m_pwd;
}
QLoginDialog::~QLoginDialog()
{
}
19、qt中的标准对话框
qt为开发者提供了一些可复用的对话框类型。
qt提供的可复用对话框全部继承自QDialog类。
qt中的标准对话框遵循相同的使用方式:
定义对话框对象
DialogType dlg(this);
设置对话框属性
dlg.setPropertyxxx(value);
if(dlg.exec())==DialogTyupe::value)
{ //获取对话框数据
Type v=dlg.getDialogValue();
//处理对话框数据 }
1消息对话框:消息对话框是应用程序中最常见的界面元素:
消息对话框主要用于:为用户提示重要信息,强制用户进行操作选择。
消息对话框的使用方式:
//构造消息对话框对象
QMessageBox msg(this);
//设置消息对话框的相关属性。
msg.setText("this is a "); //标题
msg.setWindowTitle("title"); //提示消息
msg.setIcon(QMessageBox::Information): //设置图标
msg.setStandardBuuttons( QMessageBox::OK|QMessageBox::Cancel |QMessageBox::YesToALL); ); //设置按钮
if( msg.exec()==QMwssageBox::Ok) { qDebug()<<"ok button is clicked!"; }
QMessageBox中的实用函数:
QMessageBox::qustion
QMessageBox::information
QMessageBox::warning
QMessageBox::critical
QMessageBox::about
练习。
2文件对话框:常用于以下情形
Open Mode:应用程序中需要用户打开一个外部的文件
Save Mode:应用程序中需要将当前内容存储于用户指定的外部文件中。
使用方式:
QFileDialog fd(this);
// save mode:QFileDialog::AcceptSave //保存模式
fd.setAcceptMode(QFileDialog::AcceptOpen); //设置属性,打开模式
fd.setFileMode(QFileDialog::ExistingFile); //一次只打开一个存在的文件。多个文件,多个加s
//fd.setFileMode(QFileDialog::ExistingFiles); //打开多个文件,多加个s
if( fd.exec()==QFileDialog::Accepted ) //调用exec,文件对话框在屏幕上显示
{ QStringList fs=fd.selectedFiles(); } //得到用户选择的文件
文件类型过滤器:setFilter("Text(*.*)")
在文件对话框中可以通过文件后缀定义过滤器
过滤器定义规则:显示名(*.后缀1 *.后缀2...*.后缀N)
例:“Image(*.png *.xpm *.jpg)”//显示 .png *.xpm *.jpg三个,空格隔开
"Text(*.txt)" //仅仅是txt文本文件,Text代表了这些文件
“All(*.*)”
小结:
Qt中提供了多个可复用的对话框类型:继承于QDialog类型,遵循相同的使用方式。QMessageBox用于提示重要的程序信息,QFileDialog用于获取系统中的文件路径。
//dlg.setFilter( "Text(*.txt)" );
QFileDialog中的实用函数:
QFileDialog::getOpenFileName
QFileDialog::getOpenFileNames
QFileDialog::getSaveFileName
20、标准对话框(中)
qt中提供了预定义的颜色对话框QColorDialog类
QColorDialog类用于提供指定颜色的对话框部件。
颜色对话框的使用方式:
//构造颜色对话框对象
QColorDialog dlg(this);
//设置颜色对话框的相关属性
dlg.setWindowTetle("Color Editor");
dlg.setCurrentColor(Qt::red);//初始颜色
if(dlg.exec()==QColorDialog::Accepted)
{
qDebug()<<dlg.selectedColor();
}
Qt中的QColor类用于在程序中表示颜色的概念,QColor类同时支持多种颜色表示方式:
RGB:以红、绿、蓝为基准的三色模型。
HSV:以色调,饱和度、明度为基准的六角椎体模型。
CMYK:以天蓝,品红,黄色,黑为基准的全彩印刷色彩模型。
QColorDialog中的实用函数:
QColorDialog::getColor
输入对话框:qt中提供了预定义的输入对话框QInputDialog类
QInputDialog类用于需要临时进行数据输入的场合。使用方式:
//构造输入对话框对象
QInputDialog dlg(this);
//设置输入对话框的相关属性
dlg.setWindowTitle("Input...")'
dlg.setLabelTest("please enter a interger:");
dlg.setInputMode(QInputDialog::IntInput);//输入的是什么,这里输入整型数
if(dlg.exec()==QInputDialog::Accepted)
{ qDebug<<dlg.intValue(); }
输入对话框的输入模式:
QInputDialog::TextInput -输入文本字符串
QInputDialog::IntInput-输入整型数
QInputDialog::Double Inout-输入浮点数
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton ColorDialogBtn;
QPushButton InputDialogBtn;
private slots:
void ColorDialogBtn_Clicked();
void InputDialogBtn_Clicked();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include <QDebug>
#include <QColorDialog>
#include <QInputDialog>
Widget::Widget(QWidget *parent) : QWidget(parent),
ColorDialogBtn(this), InputDialogBtn(this)
{
ColorDialogBtn.setText("Color Dialog");
ColorDialogBtn.move(20, 20);
ColorDialogBtn.resize(160, 30);
InputDialogBtn.setText("Input Dialog");
InputDialogBtn.move(20, 70);
InputDialogBtn.resize(160, 30);
resize(200, 120);
setFixedSize(200, 120);
connect(&ColorDialogBtn, SIGNAL(clicked()), this, SLOT(ColorDialogBtn_Clicked()));
connect(&InputDialogBtn, SIGNAL(clicked()), this, SLOT(InputDialogBtn_Clicked()));
}
void Widget::ColorDialogBtn_Clicked()
{
QColorDialog dlg(this);
dlg.setWindowTitle("Color Editor");
dlg.setCurrentColor(QColor(100, 111, 222));//直接调用构造函数生成临时对象
if( dlg.exec() == QColorDialog::Accepted )
{
QColor color = dlg.selectedColor();
qDebug() << color;
qDebug() << color.red();
qDebug() << color.green();
qDebug() << color.blue();
qDebug() << color.hue();
qDebug() << color.saturation();
qDebug() << color.value();
}
}
void Widget::InputDialogBtn_Clicked()
{
QInputDialog dlg(this);
dlg.setWindowTitle("Input Test");
dlg.setLabelText("Please input an integer:");
dlg.setInputMode(QInputDialog::TextInput);
//dlg.setIntMinimum(0); //最小最大
//dlg.setIntMaximum(255);
if( dlg.exec() == QInputDialog::Accepted )
{
qDebug() << dlg.textValue();//intValue
}
}
Widget::~Widget()
{
}
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QInputDialog中的实用函数:
QInputDialog::getDouble //输入浮点
QInputDialog::getInt
QInputDialog::getItem //自己练习
QInputDialog::getText //输入字符串
小结:
QColorDialog类用于提供指定颜色的对话框部件。
QColor类用来在程序中表示颜色的概念。
QInputDialog类用于需要临时进行数据输入的场合。
21、标准对话框(下)
qt中提供了预定义的字体对话框QFontDialog类。
QFontDialog类用于提供选择字体的对话框部件。
字体对话框的使用方式:
//构造字体对话框对象
QFontDialog dlg(this);
//设置字体对话框的相关属性
dlg.setWindowTitle("Font Editor");
dlg.setCurrentFont(QFont("Coutier New",10,QFont::Bold));//初始字体
if(dlg.exec()==QFontDialog::Accepted)
{ qDebug()<<dlg.selectedFont(); }
QFontDialog中的实用函数:
QFontDialog::getFont
2进度对话框
Qt中提供了预定义的进度对话框QProgressDialog类
QProgressDialog类用于显示进度信息
QProgressDialog类用于需要用户等待的场合。使用方式:
//构造进度对话框对象
QProgressDialog dlg(this);
//设置进度对话框的相关属性
dlg.setWindowTitle("Updating...");
dlg.setLabelText("Downloading from server..");
dlg.setMinimum(0);//设置最小进度值
dlg.setMaximum(1000);//设置最大进度值
dlg.exec(); //这里是差异,需要用户等待,用户不能操作
3打印对话框:
Qt中提供了预定义的打印对话框QPringtDialog类,QPrintDialog类用于设置打印相关的参数信息。
使用方式:
//构造打印对话框对象
QPrintDialog dlg(this);
//设置打印对话框的相关属性
dlg.setWindowTitle("print Dialog");
if(dlg.exec()==QprintDialog::Accepted)
{ Qprinter* p=dlg.printer();
//use printer object to print data }
打印对话框会产生一个数据对象,数据对象的类型是QPrinter:
qt中的QPrinter类是打印设备及其参数的封装,QPrinter类封装了系统中打印设备的驱动接口,QPrinter以相同方式使用系统中的不同打印设备。
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton FontDialogBtn;
QPushButton ProgressDialogBtn;
QPushButton PrintDialogBtn;
private slots:
void FontDialogBtn_Clicked();
void PrintDialogBtn_Clicked();
void ProgressDialogBtn_Clicked();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include <QDebug>
#include <QPrinter>
#include <QTextDocument>
#include <QPrintDialog>
#include <QProgressDialog>
#include <QFontDialog>
Widget::Widget(QWidget *parent) : QWidget(parent),
FontDialogBtn(this), ProgressDialogBtn(this), PrintDialogBtn(this)
{
FontDialogBtn.setText("Font Dialog");
FontDialogBtn.move(20, 20);
FontDialogBtn.resize(160, 30);
ProgressDialogBtn.setText("Progress Dialog");
ProgressDialogBtn.move(20, 70);
ProgressDialogBtn.resize(160, 30);
PrintDialogBtn.setText("Print Dialog");
PrintDialogBtn.move(20, 120);
PrintDialogBtn.resize(160, 30);
resize(200, 170);
setFixedSize(200, 170);
connect(&FontDialogBtn, SIGNAL(clicked()), this, SLOT(FontDialogBtn_Clicked()));
connect(&ProgressDialogBtn, SIGNAL(clicked()), this, SLOT(ProgressDialogBtn_Clicked()));
connect(&PrintDialogBtn, SIGNAL(clicked()), this, SLOT(PrintDialogBtn_Clicked()));
}
void Widget::FontDialogBtn_Clicked()
{
QFontDialog dlg(this);
dlg.setWindowTitle("Font Dialog Test");
dlg.setCurrentFont(QFont("Courier New", 10, QFont::Bold));
if( dlg.exec() == QFontDialog::Accepted )
{
qDebug() << dlg.selectedFont();
}
}
void Widget::ProgressDialogBtn_Clicked()
{
QProgressDialog dlg(this);
dlg.setWindowTitle("Updating...");
dlg.setLabelText("Downloading update from server...");
dlg.setMinimum(0);
dlg.setMaximum(100);
dlg.setValue(35);//进度
// create a new thread //启动后台工作线程,从服务器下载更新,下载就调用上一个函数
dlg.exec();
}
void Widget::PrintDialogBtn_Clicked()
{
QPrintDialog dlg(this);
dlg.setWindowTitle("Print Dialog Test");
if( dlg.exec() == QPrintDialog::Accepted )
{
QPrinter* p = dlg.printer();//封装了打印机及打印参数
QTextDocument td;//定义被打印对象
//td.setPlainText("Printer object test!");
td.setHtml("<h1>Print html object test</hl>");
p->setOutputFileName("D:\\test.xps"); //打印到d盘
td.print(p);
}
}
Widget::~Widget()
{
}
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
小结:qt中标准对话框的设计模式:
GUI界面部件产生数据对象,
业务逻辑中的其他对象使用数据对象,
GUI界面与业务逻辑通过数据对象连接。
用户->操作标准对话框对象->产生数据对象 <- 其他qt对象使用(真实业务逻辑)
22、布局管理器计时器:
目前的GUI开发方式:绝对定位
直接在像素级指定各个组件的位置和大小。
void QWidget::move(int x,int y)
void QWidget::resize(int w,int h)
问题:组件的位置和大小无法自适应父窗口的变化
解决方案:布局管理器
提供相关的类对界面组件进行布局管理:
能够自动排列窗口中的界面组件,窗口变化后自动更新界面组件的大小。
QLayout是Qt中布局管理器的抽象基类,通过继承QLayout实现功能各异且互补的布局管理器,qt中可以根据需要自定义布局管理器,布局管理器不是界面部件,而是界面部件的定位策略。
QLayout <----QBoxLayout, QGridLayout , QformLayout, QStackedLayout
QBoxLayout布局管理器:以水平或者垂直的方式管理界面组件(一个格子格子的)。
子类:QVBoxLayout, QHBoxLayout
布局管理器可以相互嵌套,形成更加复杂的布局方式:
布局嵌套几乎可以完成所有常用的界面布局。
自定义布局类可以达到个性化界面布局的效果。不推荐
嵌套实例:
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton TestBtn1;
QPushButton TestBtn2;
QPushButton TestBtn3;
QPushButton TestBtn4;
void initControl();
void testVBoxLayout();
void testHBoxLayout();
void testVHBoxLayout();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include <QVBoxLayout>
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
//initControl();
//testVBoxLayout();
//testHBoxLayout();
//testVHBoxLayout();
}
void Widget::testVHBoxLayout()
{
QHBoxLayout* hLayout1 = new QHBoxLayout();
QHBoxLayout* hLayout2 = new QHBoxLayout();
QVBoxLayout* vLayout = new QVBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
hLayout1->setSpacing(10);
hLayout1->addWidget(&TestBtn1);
hLayout1->addWidget(&TestBtn2);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
hLayout2->setSpacing(10);
hLayout2->addWidget(&TestBtn3);
hLayout2->addWidget(&TestBtn4);
vLayout->setSpacing(10);
vLayout->addLayout(hLayout1);
vLayout->addLayout(hLayout2);
setLayout(vLayout);//窗口直接是垂直管理器
}
void Widget::testHBoxLayout()
{
QHBoxLayout* layout = new QHBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(30);
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
setLayout(layout);
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout = new QVBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);//能变宽变长
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(30);//设置按钮距离
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
setLayout(layout);
}
void Widget::initControl()
{
TestBtn1.setText("Test Button 1");
TestBtn1.move(20, 20);
TestBtn1.resize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.move(20, 70);
TestBtn2.resize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.move(20, 120);
TestBtn3.resize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.move(20, 170);
TestBtn4.resize(160, 30);
}
Widget::~Widget()
{
}
小结:绝对定位的布局方位无法自适应窗口的变化,qt提供了相关的类对界面组件进行布局管理,qt预定义了功能各异且互补的布局管理器,布局管理器能够相互嵌套形成复杂的布局。
23、布局管理器2
布局管理器中的比例系数:
默认情况下以等比例的方式更新组件的大小。
可以自定义组件大小更新时的比例系数。
QBoxLayout中的比例系数设置
void setStretch(int index,int stretch) //格子下标,比例系数
bool setStretchFactor(QWidget* widget, int stretch) //某个具体组件的比例系数
bool set Stretch Factor(QLayout* layout, int stretch) //嵌套的布局管理器的比例系数
组件的初始大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置。
一开始运行是手工设置的,在变化的过程中逐渐符合我们设置的比例。所以一开始的比例是初始设置的。
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton TestBtn1;
QPushButton TestBtn2;
QPushButton TestBtn3;
QPushButton TestBtn4;
void initControl();
void testVBoxLayout();
void testHBoxLayout();
void testVHBoxLayout();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include <QVBoxLayout>
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
//initControl();
//testVBoxLayout();
//testHBoxLayout();
//testVHBoxLayout();
}
void Widget::testVHBoxLayout()
{
QHBoxLayout* hLayout1 = new QHBoxLayout();
QHBoxLayout* hLayout2 = new QHBoxLayout();
QVBoxLayout* vLayout = new QVBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
hLayout1->setSpacing(10);
hLayout1->addWidget(&TestBtn1);
hLayout1->addWidget(&TestBtn2);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
hLayout2->setSpacing(10);
hLayout2->addWidget(&TestBtn3);
hLayout2->addWidget(&TestBtn4);
vLayout->setSpacing(10);
vLayout->addLayout(hLayout1);
vLayout->addLayout(hLayout2);
vLayout->setStretchFactor(hLayout1, 1);
vLayout->setStretchFactor(hLayout2, 3);
setLayout(vLayout);
}
void Widget::testHBoxLayout()
{
QHBoxLayout* layout = new QHBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(30);
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
layout->setStretchFactor(&TestBtn1, 1);
layout->setStretchFactor(&TestBtn2, 2);
layout->setStretchFactor(&TestBtn3, 1);
layout->setStretchFactor(&TestBtn4, 3);//比例系数
setLayout(layout);
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout = new QVBoxLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(30);
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
layout->setStretch(0, 1);
layout->setStretch(1, 1);
layout->setStretch(2, 2);
layout->setStretch(3, 2);
setLayout(layout);
}
void Widget::initControl()
{
TestBtn1.setText("Test Button 1");
TestBtn1.move(20, 20);
TestBtn1.resize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.move(20, 70);
TestBtn2.resize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.move(20, 120);
TestBtn3.resize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.move(20, 170);
TestBtn4.resize(160, 30);
}
Widget::~Widget()
{
}
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
QGridLayout布局管理器
以网格(二维)的方式管理界面组件。
QGridLayout中的比例系数设置:
void setColumnStretch(int column,int stretch)
void setRowStretch(int row,int stretch)
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton TestBtn1;
QPushButton TestBtn2;
QPushButton TestBtn3;
QPushButton TestBtn4;
void testGridLayout1();
void testGridLayout2();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include <QGridLayout>
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
//testGridLayout1();
//testGridLayout2();
}
void Widget::testGridLayout1()
{
QGridLayout* layout = new QGridLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(10);
layout->addWidget(&TestBtn1, 0, 0);//放在00位置
layout->addWidget(&TestBtn2, 0, 1);
layout->addWidget(&TestBtn3, 1, 0);
layout->addWidget(&TestBtn4, 1, 1);
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 3);
layout->setColumnStretch(0, 1);
layout->setColumnStretch(1, 3);
setLayout(layout);
}
void Widget::testGridLayout2()
{
QGridLayout* layout = new QGridLayout();
TestBtn1.setText("Test Button 1");
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160, 30);
TestBtn2.setText("Test Button 2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160, 30);
TestBtn3.setText("Test Button 3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160, 30);
TestBtn4.setText("Test Button 4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160, 30);
layout->setSpacing(10);
layout->addWidget(&TestBtn1, 0, 0, 2, 1);//在00位置占用2行一列
layout->addWidget(&TestBtn2, 0, 1, 2, 1);
layout->addWidget(&TestBtn3, 2, 0, 1, 2);
layout->addWidget(&TestBtn4, 3, 0, 1, 2);
setLayout(layout);
}
Widget::~Widget()
{
}
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
布局管理器的嵌套:
QGridLayout支持嵌套其他布局管理器成为其管理对象。
小结: QGridLayout以网格的方式对组件 进行管理,QGridLayout中的组件可以根据需要跨越多个网络,QBoxLayout和QGridLayout支持比例系数的概念。比例系数决定了组件大小的相对变化。
24、布局管理器3
绝对定位组件的坐标和大小
嵌套QBoxLayout 线性布局管理器
创建3*2的QGridLayout 网格布局管理器
为了美观,提出表单管理器:
layout->Widget(nameedit,0,0);
QFormLayout布局管理器:
以表单(Form)的方式管理界面组件。
表单布局中的标签和组件是相互对应的关系。
标签:组件
用法:
void addRow(QWidget* label,QWidget*field) //以行的方式管理
void addRow(QWidget* label,QLayout* field)
void addRow(const QString& labelText,QWidget* field)
void addRow(const QString& labelTest,QLayout* field)
表单布局支持嵌套,其他布局管理器可以作为子布局被其管理。
QFormLayout的样式函数:
void setRowWrapPolicy(RowWrapPolicy policy)//设置每一行排布,一行标示一行组件
void setLabelAlignment(Qt::Alignment alignment)//对齐
小结:
QFormLayout以表单的方式管理界面组件
QFormLayout的样式设置简洁明了
QFormLayout支持布局管理器的嵌套
QFormLayout是嵌入式产品中最常用的布局方式。
QLineEdit* nameEdit = new QLineEdit();
QLineEdit* mailEdit = new QLineEdit();
QLineEdit* addrEdit = new QLineEdit();
QFormLayout* layout = new QFormLayout();
layout->addRow("Name:", nameEdit);
layout->addRow("Email:", mailEdit);
layout->addRow("Address:", addrEdit);
layout->setRowWrapPolicy(QFormLayout::WrapLongRows);
//标识,组件如果在同一行放不下,组件会自动到下一行,其它的标识,组件还是在同一行
//layout->setLabelAlignment(Qt::AlignRight);
//标签向右对齐
layout->setSpacing(10);
setLayout(layout);
//将layout设置到窗口中,告诉主窗口现在由布局管理器管理上面组件
setWindowTitle("FTP");
25、布局管理器4
栈式布局管理器(QStackedLayout)
所有组件再垂直于频幕的方向上被管理
每次只有一个组件会显示再频幕上,
只有最顶层的组件会被最终显示
特点:组件大小一致且充满父组件的显示区,不能直接嵌套其他布局管理器,能够自由切换需要显示的组件,每次能且仅能显示一个组件。
用法概要:
int addWidget(QWidget* widget) //加入需要管理的组件,不能addlayout
QWidget* currentWidget() //得到当前显示在屏幕的组件,得到最顶层的组件
void setCurrentIndex(int index) //通过编号即下标来设置当前显示
int currentIndex()
间接布局管理器的嵌套。
计时器:
计时器是工程开发中非常重要的角色。
计时器用于每隔一定的时间触发一个消息。
计时器消息最终会被转化为函数调用。
宏观上:计时器再每个间隔会调用指定的函数。
计时器(QTimer)使用方法:
1编写计时器消息处理函数
2再程序中创建计时器对象
3连接计时器消息和消息处理函数
4设置计时器时间间隔并启动计时
应用:上一步下一步,左划右划
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton TestBtn1;
QPushButton TestBtn2;
QPushButton TestBtn3;
QPushButton TestBtn4;
void initControl();
private slots:
void timerTimeout();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif
#include "Widget.h"
#include "Widget.h"
#include <QStackedLayout>
#include <QHBoxLayout> //水平布局管理器
#include <QtCore>
#include <QDebug>
#include <QtCore>
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
initControl();
}
void Widget::initControl()
{
QStackedLayout* sayout=new QStackedLayout();
QHBoxLayout* hlayout=new QHBoxLayout();
QWidget* widget=new QWidget();
QTimer* timer=new QTimer(this); //创建Qttimer对象,计时器对象
TestBtn1.setText("1st Button");
TestBtn2.setText("2rd Button");
TestBtn3.setText("3th Button");
TestBtn4.setText("Test Button 4: D.T.Software");
TestBtn2.setParent(widget); //父组件为widget对象
TestBtn3.setParent(widget);
hlayout->addWidget(&TestBtn2);//水平布局管理器管理两个
hlayout->addWidget(&TestBtn3);
widget->setLayout(hlayout); //将水平布局管理器设置到刚刚创建出来的widget对象上面去
sayout->addWidget(&TestBtn1);
//sayout->addWidget(&TestBtn2);
//sayout->addWidget(&TestBtn3);
sayout->addWidget(widget); //完成嵌套
sayout->addWidget(&TestBtn4);
sayout->setCurrentIndex(1); //初始显示哪个组件
setLayout(sayout);//将栈式管理布局器显示到当前窗口
connect(timer,SIGNAL(timeout()),this,SLOT(timerTimeout()));//timer对象的timeout信号,链接计时器消息,和消息处理函数(槽)
timer->start(2000); //每隔2秒启动一次
}
void Widget::timerTimeout()
{
QStackedLayout* slayout=dynamic_cast<QStackedLayout*>(layout()); //直接按F1,帮助文档会调用出来,得到QLayout指针类型,所以要强制类型转换
//获取栈布局管理器对象,调用layout成员函数将当前组件拥有的布局管理器直接返回
if(slayout != NULL)
{
int index=((slayout->currentIndex()+1) % slayout->count());
//currentIndex()当前显示的组件下标,下一个--+1,可能溢出--取余,循环得到下标,count函数获取当前这个对象所管理的组件数目
slayout->setCurrentIndex(index); //重新设置要显示的组件下标
qDebug()<<index;
}
}
Widget::~Widget()
{
}
小结:
QStackedLayout以栈的方式管理界面组件。
QStackedLayout中的组件最多只有一个显示。
QStackedLayout可以自由切换需要显示的组件。
QTimer是Qt中的计时器组件。
QTimer能够在指定的之间间隔触发消息。