二阶构造
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons() // 第一阶段构造函数
{
}
bool construct() // 第二阶段构造函数
{
return true;
}
public:
static TwoPhaseCons* NewInstance(); // 对象创建函数
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
// 若第二阶段构造失败,返回 NULL
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
delete obj;
return 0;
}
实战
IntArray.h
#ifndef _INTARRAY_H_
#define _INTARRAY_H_
class IntArray
{
private:
int m_length;
int* m_pointer;
IntArray(int len);
bool construct();
public:
static IntArray* NewInstance(int length);
int length();
int get(int index, int& value);
bool set(int index ,int value);
~IntArray();
};
#endif
main.cpp
#include <stdio.h>
#include "IntArray.h"
int main()
{
IntArray* a = IntArray::NewInstance(5);
printf("a.length = %d\n", a->length());
a->set(0, 1);
for (int i = 0; i < a->length(); i++)
{
int v = 0;
printf("a[%d] = %d\n", i, a->get(i, v));
}
delete a;
return 0;
}
intarray.cpp
#include "IntArray.h"
IntArray::IntArray(int len)
{
m_length = len;
}
bool IntArray::construct()
{
bool ret = true;
m_pointer = new int[m_length];
if (m_pointer)
{
for (int i = 0; i < m_length; i++)
{
m_pointer[i] = 0;
}
}
else
{
ret = false;
}
return ret;
}
IntArray* IntArray::NewInstance(int length)
{
IntArray* ret = new IntArray(length);
if (!(ret && ret->construct()))
{
delete ret;
ret = 0;
}
return ret;
}
int IntArray::length()
{
return m_length;
}
int IntArray::get(int index, int& value)
{
bool ret = (0 <= index) && (index < length());
if (ret)
{
value = m_pointer[index];
}
return value;
}
bool IntArray::set(int index, int value)
{
bool ret = (0 <= index) && (index < length());
if (ret)
{
m_pointer[index] = value;
}
return ret;
}
IntArray::~IntArray()
{
delete[]m_pointer;
}
窗口部件和窗口类型
坐标系统
#include <QtGui/QApplication>
#include <QPushButton>
#include <QDebug>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QPushButton b(&w); // 生成QPushButton对象,其父组件为QWideget
QPushButton b1(&w);
b.setText("Button"); //
b.move(10, 10); //
b.resize(100, 50); //
b1.setText("Button"); //
b1.move(120, 10); //
b1.resize(100, 50); //
w.resize(100, 100);
w.move(120, 120);
w.show();
qDebug()<<"QWidget:";
qDebug()<<w.x();
qDebug()<<w.y();
qDebug()<<w.width();
qDebug()<<w.height();
qDebug()<<"QWidget::geometry()";
qDebug()<<w.geometry().x();
qDebug()<<w.geometry().y();
qDebug()<<w.geometry().width();
qDebug()<<w.geometry().height();
qDebug()<<"QWidget::frameGeometry()";
qDebug()<<w.frameGeometry().x();
qDebug()<<w.frameGeometry().y();
qDebug()<<w.frameGeometry().width();
qDebug()<<w.frameGeometry().height();
return a.exec();
}
Qt对象间的父子关系
布局管理器
1.布局管理器提供相关的类对界面组件进行布局管理
- 能够自动排列窗口中的界面组件
- 窗口变化后自动更新界面组件的大小
2.
- QLayout是Qt中布局管理器的抽象基类
- 通过继承QLayout实现了功能各异且互补的布局管理器
- Qt中可以根据需要自定义布局管理器
- 布局管理器不是界面组件,而是界面部件的定位策略
3.QBoxLayout布局管理器
——以水平或垂直的方式管理界面组件
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void testVBoxLayout();
private:
Ui::Widget *ui;
QPushButton *button1;
QPushButton *button2;
QPushButton *button3;
QPushButton *button4;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button2 = new QPushButton("Button 2");
button3 = new QPushButton("Button 3");
button4 = new QPushButton("Button 4");
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button3);
setLayout(layout);
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
手动拖大拖小时,里面的按钮默认情况下变化时仅仅是宽度变化,高度不会变,如何让高度也变化?
另外,调整初始按钮大小以及设置按钮间距
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout->setSpacing(30);
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button3);
setLayout(layout);
}
布局管理器的嵌套
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QHBoxLayout* layout1=new QHBoxLayout();
QHBoxLayout* layout2=new QHBoxLayout();
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout1->addWidget(button1);
layout1->addWidget(button2);
layout1->setSpacing(10);
layout2->addWidget(button3);
layout2->addWidget(button4);
layout2->setSpacing(10);
layout->addLayout(layout1);
layout->addLayout(layout2);
layout->setSpacing(10);
setLayout(layout);
}
手动拉伸时窗口时,里面的窗口默认情况下是等比例变化的,
如何改变变化的比例
QBoxLayout中的比例系数设置
void setStretch(int index,int stretch)
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout->setSpacing(30);
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->setStretch(0,1);
layout->setStretch(1,1);
layout->setStretch(2,2);
layout->setStretch(3,2);
setLayout(layout);
}
bool setStretchFactor(QWidegt* widget,int stretch)
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout->setSpacing(30);
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->setStretchFactor(button1,1);
layout->setStretchFactor(button2,1);
layout->setStretchFactor(button3,2);
layout->setStretchFactor(button4,2);
setLayout(layout);
}
bool setStretchFactor(QLayout* layout,int stretch)
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QHBoxLayout* layout1=new QHBoxLayout();
QHBoxLayout* layout2=new QHBoxLayout();
QVBoxLayout* layout=new QVBoxLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout1->addWidget(button1);
layout1->addWidget(button2);
layout1->setSpacing(10);
layout2->addWidget(button3);
layout2->addWidget(button4);
layout2->setSpacing(10);
layout->addLayout(layout1);
layout->addLayout(layout2);
layout->setSpacing(10);
layout->setStretchFactor(layout1,1);
layout->setStretchFactor(layout2,2);
setLayout(layout);
}
组件的初始大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置
QGridlayout布局管理器
以网格(二维)的方式管理界面组件
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QGridLayout* layout=new QGridLayout();
button1 = new QPushButton("Button 1");
button1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button1->setMinimumSize(160,30);
button2 = new QPushButton("Button 2");
button2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button2->setMinimumSize(160,30);
button3 = new QPushButton("Button 3");
button3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button3->setMinimumSize(160,30);
button4 = new QPushButton("Button 4");
button4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
button4->setMinimumSize(160,30);
layout->setSpacing(10);
layout->addWidget(button1,0,0,2,1);//后面两个参数是指占用两行一列
layout->addWidget(button2,0,1,2,1);//设置第1行的比例因子为3
layout->addWidget(button3,2,0,1,2);//前两个按钮都占用两行,所以button3只能从第三行放
layout->addWidget(button4,3,0,1,2);
//设置比例因子
layout->setRowStretch(0,1);
layout->setRowStretch(1,3);
layout->setColumnStretch(0,1);
layout->setColumnStretch(0,1);
setLayout(layout);
}
网格布局管理器也支持嵌套
QFormLayout布局管理器
- 以表单的方式管理界面组件
- 表单布局中的标签和组件是相互对应的关系
QFormLayout的用法概要
- void addRow(QWidget* label,QWidget* field)
- void addRow(QWidget* label,QLayout* field)
- void addRow(const QString& labelText,QWidget* field)
- void addRow(const QString& labelText,QLayout* field)
表单布局管理器也支持嵌套,其他布局管理器可以作为子布局被其管理
#include "widget.h"
#include "ui_widget.h"
#include <QLineEdit>
#include <QFormLayout>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QLineEdit* p1=new QLineEdit();
QLineEdit* p2=new QLineEdit();
QLineEdit* p3=new QLineEdit();
QFormLayout* layout=new QFormLayout();
layout->addRow("Name:",p1);
layout->addRow("Age:",p2);
layout->addRow("Address",p3);
setLayout(layout);
setWindowTitle("信息");
}
QFormLayout的样式函数
void setRowWrapPolicy(RowWrapPolicy policy):设置每一行该如何排列,默认设置是左右排布void setLabelAlignment(Qt::Alignment alignment);设置对齐方式
#include "widget.h"
#include "ui_widget.h"
#include <QLineEdit>
#include <QFormLayout>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QLineEdit* p1=new QLineEdit();
QLineEdit* p2=new QLineEdit();
QLineEdit* p3=new QLineEdit();
QFormLayout* layout=new QFormLayout();
layout->addRow("Name:",p1);
layout->addRow("Age:",p2);
layout->addRow("Addresssssssssssssssssssssssssssssssssssssssssss:",p3);
//一行标识,一行组件
//layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
//如果整行的水平空间不足以显示,则允许对整行进行换行,将小部件移到下一行
//layout->setRowWrapPolicy(QFormLayout::WrapLongRows);
//右对齐
layout->setLabelAlignment(Qt::AlignRight);
setLayout(layout);
setWindowTitle("信息");
}
栈式布局管理器(QStackedLayout)
- 所有组件在垂直于屏幕的方向上被管理
- 每次只有一个组件会显示在屏幕上
- 只有最顶层的组件会被最终显示
栈式布局管理器的特点
- 组件大小一致且充满父组件的显示区
- 不能直接嵌套其他布局管理器
- 能够自由切换需要显示的组件
- 每次能且仅能显示一个组件
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QStackedLayout>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QStackedLayout* layout=new QStackedLayout();
button1 = new QPushButton("Button 1");
button2 = new QPushButton("Button 2");
button3 = new QPushButton("Button 3");
button4 = new QPushButton("Button 4");
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button3);
//设置最初始要显示的组件
layout->setCurrentIndex(1);//显示button2
setLayout(layout);
}
间接嵌套布局管理器
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QStackedLayout>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QStackedLayout* layout=new QStackedLayout();
QHBoxLayout* hlayout=new QHBoxLayout();
QWidget* widget=new QWidget();
button1 = new QPushButton("Button 1");
button2 = new QPushButton("Button 2");
button3 = new QPushButton("Button 3");
button4 = new QPushButton("Button 4");
button2->setParent(widget);
button3->setParent(widget);
hlayout->addWidget(button2);
hlayout->addWidget(button3);
widget->setLayout(hlayout);
layout->addWidget(button1);
layout->addWidget(widget);
layout->addWidget(button4);
layout->setCurrentIndex(1);
setLayout(layout);
}
计时器
计时器是工程开发中非常重要的角色
计时器用于每隔一定的时间触发一个消息
计时器消息最终会转化为函数调用
宏观上,计时器在每个时间间隔会调用指定的函数
计时器的使用方法
- 编写计时器消息处理函数
- 在程序中创建计时器对象
- 连接计时器消息和消息处理函数
- 设置计时器时间间隔并启动计时
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void testVBoxLayout();
private:
Ui::Widget *ui;
QPushButton *button1;
QPushButton *button2;
QPushButton *button3;
QPushButton *button4;
private slots:
void timerTimeout();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QStackedLayout>
#include <QDebug>
#include <QtCore>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
testVBoxLayout();
}
Widget::~Widget()
{
delete ui;
}
void Widget::testVBoxLayout()
{
QStackedLayout* layout=new QStackedLayout();
QHBoxLayout* hlayout=new QHBoxLayout();
QWidget* widget=new QWidget();
QTimer* timer=new QTimer(this);//在程序中创建计时器对象
button1 = new QPushButton("Button 1");
button2 = new QPushButton("Button 2");
button3 = new QPushButton("Button 3");
button4 = new QPushButton("Button 4");
button2->setParent(widget);
button3->setParent(widget);
hlayout->addWidget(button2);
hlayout->addWidget(button3);
widget->setLayout(hlayout);
layout->addWidget(button1);
layout->addWidget(widget);
layout->addWidget(button4);
layout->setCurrentIndex(0);
setLayout(layout);
//连接计时器消息和消息处理函数
connect(timer,SIGNAL(timeout()),this,SLOT(timerTimeout()));
//设置计时器时间间隔并启动计时
timer->start(2000);//每隔两秒触发一次消息
}
//编写计时器消息处理函数
void Widget::timerTimeout()
{
QStackedLayout* sLayout=dynamic_cast<QStackedLayout*>(layout());
if(sLayout!=NULL)
{
int index=(sLayout->currentIndex()+1)%sLayout->count();
sLayout->setCurrentIndex(index);
}
}
对话框
- 对话框是与用户进行简短交互的顶层窗口
- QDialog是Qt中所有对话框窗口的基类
- QDialog继承于QWidget是一种容器类型的组件
QDialog的意义
- QDialog作为一种专用的交互窗口而存在
- QDialog不能作为子部件嵌入其它容器中
- QDialog是定制了窗口式样的特殊的QWidget
main.cpp
#include "widget.h"
#include <QApplication>
#include <QDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QDialog dialog(&w);
w.setWindowTitle("widget");
dialog.setWindowTitle("dialog");
dialog.show();
w.show();
return a.exec();
}
运行结果可以看出,dialog并没有被嵌入到父组件里面去,而且dialog始终位于widget这个父组件的上层,所以,对话框是与用户进行简短交互的顶层窗口,QDialog不能作为子部件嵌入其它容器中
main.cpp
#include "widget.h"
#include <QApplication>
#include <QDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog dialog;
Widget w(&dialog);
w.setWindowTitle("widget");
dialog.setWindowTitle("dialog");
dialog.show();
w.show();
return a.exec();
}
此时widget被嵌入dialog中
对话框的类型
1.模态对话框(QDialog::exec())
- 显示后无法与父窗口进行交互
- 是一种阻塞式的对话框调用方式
2.非模态对话框(QDialog::show())
- 显示后独立存在可以同时与父窗口进行交互
- 是一种非阻塞式的对话框调用方式
一般情况下,模态对话框用于必须依赖用户选择的场合(80%)
如消息提示,文件选择,打印设置等,非模态对话框用于特殊功能设置的场合(20%),如查找操作,属性设置等
小技巧
- 在栈上创建模态对话框是最简单常用的方式
- 一般情况下非模态对话框需要在堆上创建
- 通过QDialog::setModal函数可以创建混合特性的对话框
- 非模态对话框需要指定Qt::WA_DeleteOnClose属性
void Dialog::button1_clicked()
{
qDebug()<<"1";
QDialog dialog;
dialog.exec();
qDebug()<<"2";
}
只会输出"1",因为该对话框是模态,在完成该对话框的交互之前,后面的不会被运行
当把对话框关闭之后,就可以接着输出下面的代码
非模态对话框需要在堆上创建
模态对话框指定或者不指定父组件,效果都是一样的,非模态对话框如果不指定父组件,对话框会位于主窗口的下面,指定父组件后,会始终位于主窗口的上面,无论是模态对话框还是非模态对话框,建议都指定父组件
非模态对话框是在堆上创建的,如何关闭对话框的时候释放堆资源呢,指定Qt::WA_DeleteOnClose属性
void Dialog::button2_clicked()
{
qDebug()<<"1";
QDialog* dialog=new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
qDebug()<<"2";
}
混合属性的对话框,在运行机理上是非模态对话框的特性,在表现形式上是模态对话框的特性,在对话框弹出的时候,无法与主窗口进行交互
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton button1;
QPushButton button2;
QPushButton button3;
private slots:
void button1_clicked();
void button2_clicked();
void button3_clicked();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <QGridLayout>
#include <QDebug>
Dialog::Dialog(QWidget *parent)
: QDialog(parent),button1(this),button2(this),button3(this)
{
button1.setText("button1");
button1.move(20,20);
button1.resize(100,30);
button2.setText("button2");
button2.move(20,70);
button2.resize(100,30);
button3.setText("button3");
button3.move(20,120);
button3.resize(100,30);
connect(&button1,SIGNAL(clicked()),this,SLOT(button1_clicked()));
connect(&button2,SIGNAL(clicked()),this,SLOT(button2_clicked()));
connect(&button3,SIGNAL(clicked()),this,SLOT(button3_clicked()));
}
Dialog::~Dialog()
{
qDebug()<<"输出";
}
void Dialog::button1_clicked()
{
qDebug()<<"1";
QDialog dialog(this);
dialog.exec();
qDebug()<<"2";
}
void Dialog::button2_clicked()
{
qDebug()<<"1";
QDialog* dialog=new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
qDebug()<<"2";
}
void Dialog::button3_clicked()
{
qDebug()<<"1";
QDialog* dialog=new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModal(this);
dialog->show();
qDebug()<<"2";
}
main.cpp
#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
对话框的返回值
- 只有模态对话框才有返回值的概念
- 模态对话框的返回值用于表示交互结果
- QDialog::exec()的返回值为交互结果
——void QDialog::done(int i)关闭对话框并将参数作为交互结果
——QDialog::Accepeted 用户操作成功
——QDialog::Rejected 用户操作失败
案例:设计登录对话框
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
QString getUser();
QString getPwd();
~Dialog();
private:
QPushButton button1;
QPushButton button2;
QLineEdit lineedit1;
QLineEdit lineedit2;
QLabel label1;
QLabel label2;
QString m_pwd;
QString m_user;
private slots:
void button1_clicked();
void button2_clicked();
};
#endif // DIALOG_H
widget.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
QString getUser();
QString getPwd();
~Dialog();
private:
QPushButton button1;
QPushButton button2;
QLineEdit lineedit1;
QLineEdit lineedit2;
QLabel label1;
QLabel label2;
QString m_pwd;
QString m_user;
private slots:
void button1_clicked();
void button2_clicked();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <QGridLayout>
#include <QDebug>
Dialog::Dialog(QWidget *parent)
: QDialog(parent),button1(this),button2(this),lineedit1(this),lineedit2(this),
label1(this),label2(this)
{
label1.setText("User ID");
label1.move(20,30);
label1.resize(65,25);
lineedit1.move(85,30);
lineedit1.resize(180,25);
label2.setText("Password");
label2.move(20,65);
label2.resize(65,25);
lineedit2.move(85,65);
lineedit2.resize(180,25);
lineedit2.setEchoMode(QLineEdit::Password);//密码不直接显示出来,用黑色圆点表示
button1.setText("Cancel");
button1.move(85,110);
button1.resize(85,30);
button2.setText("Login");
button2.move(180,110);
button2.resize(85,30);
setWindowTitle("Login");
setFixedSize(285,170);//固定大小
connect(&button1,SIGNAL(clicked()),this,SLOT(button1_clicked()));
connect(&button2,SIGNAL(clicked()),this,SLOT(button2_clicked()));
}
QString Dialog::getUser()
{
return m_user;
}
QString Dialog::getPwd()
{
return m_pwd;
}
Dialog::~Dialog()
{
qDebug()<<"输出";
}
void Dialog::button1_clicked()
{
done(Rejected);
}
void Dialog::button2_clicked()
{
m_user=lineedit1.text();
m_pwd=lineedit2.text();
done(Accepted);
}
main,cpp
#include "dialog.h"
#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "dialog.h"
#include <QDebug>
widget::widget(QWidget *parent) :
QWidget(parent),TextBton(this)
{
TextBton.setText("Test Login Dialog");
setFixedSize(200,50);
connect(&TextBton,SIGNAL(clicked()),this,SLOT(TextBton_Clicked()));
}
void widget::TextBton_Clicked()
{
Dialog dlg;
if(dlg.exec()==QDialog::Accepted)
{
qDebug()<<"User: "<<dlg.getUser();
qDebug()<<"Pwd: "<<dlg.getPwd();
}
}
widget::~widget()
{
}
标准对话框
Qt为开发者提供了一些可复用的对话框类型
Qt提供的可复用对话框全部继承自QDialog类
如QMessageBox,QFileDialog,QPrintDialog,QColorDialog,QInputDialog,QProgressDialog
Qt中的标准对话框遵循相同的使用方式
DialogType dig(this);//定义对话框对象
dig.setPropertyXXX(value);
if(dig.exec()==DialogType::Value)
{
Type v=dig.getDialogValue();//获取对话框数据
//处理对话框数据
//...
}
消息对话框
消息对话框是应用程序中最常见的界面元素
消息对话框主要用于:为用户提示重要信息,强制用户进行操作选择
QMessageBox msg(this);
msg.setWindowTitle("Message title");//标题
msg.setText("This is message content");//提示消息
msg.setIcon(QMessageBox::Information);//设置图标
msg.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel);//设置按钮
if(msg.exec()==QMessageBox::ok)
{
qDebug()<<"ok button is clicked";
}
QMessageBox中的实用函数
- QMessageBox::question
- QMessageBox::information
- QMessageBox::warning
- QMessageBox::critical
- QMessageBox::about
文件对话框
文件对话框常用于以下情形
——Open Mode
应用程序中需要用户打开一个外部的文件
——Save Mode
应用程序中需要将当前内容存储与用户指定的外部文件中
QFileDialog fd(this);
fd.setAcceptMode(QFileDialog::AcceptOpen);//打开模式
//QFileDialog::AcceptSave 保存模式
fd.setFileMode(QFileDialog::ExistingFile);//打开存在的一个文件
//QFileDialog::ExistingFiles打开多个文件
if(fd.exec()==QFileDialog::Accepted)
{
QStringList fs=fd.selectedFiles();
}
文件类型过滤器
在文件对话框中可以通过文件后缀定义过滤器
过滤器定义规则:显示名(*.后缀1 *.后缀2 *.后缀3...)
例如:”Image(*.png *.xpm *.jpg)"
"Text(*.txt)" "All(*.*)"
QFileDialog中的实用函数
- QFileDialog::getOpenFileName
- QFileDialog::getOpenFileNames
- QFileDialog::getSaveFileName
颜色对话框
Qt中提供了预定义的颜色对话框QColorDialog类
QColorDialog类用于提供指定颜色的对话框部件
颜色对话框的使用方式
//构造颜色对话框对象
QColorDialog dig(this);
//设置颜色对话框的相关属性
dig.setWindowTitle("Color Editor");
dig.setCurrentColor(Qt::red);//初始颜色
if(dig.exec()==QColorDialog::Accepted)
{
qDebug()<<dig.selectedColor();
}
Qt中的QColor类用来在程序中表示颜色的概念
QColor类同时支持多种颜色表示方式,如RGB,HSV,CMYK
QColorDialog中的实用函数
——QColorDialog::getColor
输入对话框
Qt中提供了预定义的输入对话框QInputDialog类
QInputDialog类用于需要临时进行数据输入的场合
//构造输入对话框对象
QInputDialog dlg(this);
//设置输入对话框的相关属性
dlg.setWindowTitle("Input..");
dlg.setLabelText("Please enter a integer:");
dlg.setInputMode(QInputDialog::IntInput);
if(dlg.exec()==QInputDialog::Accepted)
{
qDebug()<<dlg.intValue();
}
输入对话框的输入模式
QInputDialog::TextInput输入文本字符串
QInputDialog::IntInput输入整形数
QInputDialog::DoubleInput输入浮点数
输入对话框的实用函数
QInputDialog::getDouble
QInputDialog::getInt
QInputDialog::getItem
QInputDialog::getText
字体对话框
Qt中提供了预定义的字体对话框QFontDialog类
QFontDialog类用于提供选择字体的对话框部件
//构造字体对话框对象
QFontDialog dig(this);
//设置字体对话框的相关属性
dig.setWindowTitle("Font Editor");
//初始字体
dig.setCurrentFont(QFont("Courier New",10,QFont::Bold));
if(dig.exec()==QFontDialog::Accepted)
{
qDebug()<<dig.selectedFont();
}
QFontDialog中的实用函数
QFontDialog::getFont
进度对话框
QtQt中提供了预定义的进度对话框QProgressDialog类
QProgressDialog类用于显示进度信息
QProgressDialog类用于需要用户等待的场合
//构造进度对话框对象
QProgressDialog dlg(this);
//设置进度对话框的相关属性
dlg.setWindowTitle("Updating..");
dlg.setLabelText("Downloading from server:..");
dlg.setMinimum(0);//设置最小进度值
dlg.setMaximum(1000);//设置最大进度值
dlg.exec();
打印对话框
Qt中提供了预定义的打印对话框QPrintDialog类
QPrintDialog类用于设置打印相关的参数信息
//构造打印对话框对象
QPrintDialog dlg(this);
//设置打印对话框的相关属性
dlg.setWindowTitle("Print Dialog");
if(dlg.exec()==QFontDialog::Accepted)
{
QPrinter* p=dlg.printer();
//user printer object to print data
}
- Qt中的QPrinter类是打印设备及其参数的封装
- QPrinter类封装了系统中打印设备的驱动接口
- QPrinter以相同方式使用系统中的不同打印设备
标准对话框最终案例
字体,进度,打印对话框省略
#ifndef WIDGET_H
#define WIDGET_H
#include <QPushButton>
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
QPushButton button1;
QPushButton button2;
QPushButton button3;
QPushButton button4;
QPushButton button5;
QPushButton button6;
private slots:
void button1_clicked();
void button2_clicked();
void button3_clicked();
void button4_clicked();
void button5_clicked();
void button6_clicked();
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QColorDialog>
#include <QInputDialog>
Widget::Widget(QWidget *parent)
: QWidget(parent),button1(this),button2(this),button3(this),button4(this),button5(this)
{
button1.setText("button1");
button1.move(20,20);
button1.resize(100,30);
button2.setText("button2");
button2.move(20,70);
button2.resize(100,30);
button3.setText("button3");
button3.move(20,120);
button3.resize(100,30);
button4.setText("button4");
button4.move(20,170);
button4.resize(100,30);
button5.setText("button5");
button5.move(20,220);
button5.resize(100,30);
connect(&button1,SIGNAL(clicked()),this,SLOT(button1_clicked()));
connect(&button2,SIGNAL(clicked()),this,SLOT(button2_clicked()));
connect(&button3,SIGNAL(clicked()),this,SLOT(button3_clicked()));
connect(&button4,SIGNAL(clicked()),this,SLOT(button4_clicked()));
connect(&button5,SIGNAL(clicked()),this,SLOT(button5_clicked()));
}
Widget::~Widget()
{
}
void Widget::button1_clicked()
{
QMessageBox msg(this);
msg.setWindowTitle("window title");
msg.setText("This is a detail message dialog");
msg.setIcon(QMessageBox::Information);
msg.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel);
if(msg.exec()==QMessageBox::Ok)
{
qDebug()<<"Ok button is clicked";
}
}
void Widget::button2_clicked()
{
QFileDialog flg(this);
flg.setAcceptMode(QFileDialog::AcceptOpen);
flg.setNameFilter(QString("Text(*.txt)"));
flg.setFileMode(QFileDialog::ExistingFiles);
if(flg.exec()==QFileDialog::Accepted)
{
QStringList fs=flg.selectedFiles();
for(int i=0;i<fs.count();i++)
{
qDebug()<<fs[i];
}
}
}
void Widget::button3_clicked()
{
QFileDialog flg(this);
flg.setAcceptMode(QFileDialog::AcceptSave);
flg.setNameFilter(QString("Text files (*.txt)"));
if(flg.exec()==QFileDialog::Accepted)
{
QStringList fs=flg.selectedFiles();
for(int i=0;i<fs.count();i++)
{
qDebug()<<fs[i];
}
}
}
void Widget::button4_clicked()
{
QColorDialog dlg(this);
dlg.setWindowTitle("Color Editor");
dlg.setCurrentColor(Qt::blue);//或者 dlg.setCurrentColor(QColor(100,111,233));
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::button5_clicked()
{
QInputDialog dlg(this);
dlg.setWindowTitle("input test");
dlg.setLabelText("please input an integer");
dlg.setInputMode(QInputDialog::IntInput);
dlg.setIntMaximum(255);
dlg.setIntMinimum(0);
if(dlg.exec()==QInputDialog::Accepted)
{
qDebug()<<dlg.intValue();
}
}
void Widget::button6_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::button7_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();
}
}
应用程序中的主窗口
main.cpp
#include <QtGui/QApplication>
#include "MainWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow* w = MainWindow::NewInstance();
int ret = -1;
if( w != NULL )
{
w->show();
ret = a.exec();
}
return ret;
}
MainWindow.cpp
#include "MainWindow.h"
#include <QMenu>
MainWindow::MainWindow()
{
}
MainWindow* MainWindow::NewInstance()
{
MainWindow* ret = new MainWindow();
if( (ret == NULL) || !ret->construct() )
{
delete ret;
ret = NULL;
}
return ret;
}
bool MainWindow::construct()
{
bool ret = true;
ret = ret && initMenuBar();
return ret;
}
bool MainWindow::initMenuBar()
{
bool ret = true;
QMenuBar* mb = menuBar();
ret = ret && initFileMenu(mb);
return ret;
}
bool MainWindow::initFileMenu(QMenuBar* mb)
{
QMenu* menu = new QMenu("File(&F)");
bool ret = (menu != NULL);
if( ret )
{
QAction* action = NULL;
ret = ret && makeAction(action, "New(N)", Qt::CTRL + Qt::Key_N);
if( ret )
{
menu->addAction(action); // add Action item to Menu
}
menu->addSeparator();
ret = ret && makeAction(action, "Exit(X)", Qt::CTRL + Qt::Key_X);
if( ret )
{
menu->addAction(action); // add Action item to Menu
}
}
if( ret )
{
mb->addMenu(menu); // add Menu add to application Menu Bar
}
else
{
delete menu;
}
return ret;
}
bool MainWindow::makeAction(QAction*& action, QString text, int key)
{
bool ret = true;
action = new QAction(text, NULL);
if( action != NULL )
{
action->setShortcut(QKeySequence(key));
}
else
{
ret = false;
}
return ret;
}
MainWindow::~MainWindow()
{
}
MainWindow.h
#ifndef _MAINWINDOW_H_
#define _MAINWINDOW_H_
#include <QtGui/QMainWindow>
#include <QKeySequence>
#include <QMenuBar>
#include <QAction>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
MainWindow();
MainWindow(const MainWindow&);
MainWindow& operator= (const MainWindow&);
bool construct();
bool initMenuBar();
bool initFileMenu(QMenuBar* mb);
bool makeAction(QAction*& action, QString text, int key);
public:
static MainWindow* NewInstance();
~MainWindow();
};
#endif // _MAINWINDOW_H_
主窗口中的工具栏
工具栏的概念和意义
- 应用程序中集成各种功能实现快捷使用的一个区域
- 工具栏并不是应用程序中必须存在的组件
- 工具栏中的元素可以是各种窗口组件
- 工具栏中的元素通常以图标按钮的方式存在
在Qt中提供与工具栏相关的类组件
1.工具栏(QToolBar)
2.快捷项(QAction)
QToolBar的关键成员函数
-
setFloatable(bool floatable)
:设置工具栏是否可浮动。如果设置为true,则工具栏可以拖动到主窗口之外成为独立的浮动窗口。 -
setMovable(bool movable)
:设置工具栏是否可移动。如果设置为true,则工具栏可以从一个位置拖动到另一个位置。 -
setIconSize(const QSize &size)
:设置工具栏上工具按钮的图标大小。
QToolBar中可以加入任意的QWidegt组件
QToolBar* tb=addToolBar("Tool Bar");
QPushButton* b=new QPushButton("Button");
QLabel* l=new QLabel("Label");
QLineEdit* e=new QLineEdit();
tb->addWidget(b);
tb->addWidget(l);
tb->addWidget(e);
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include <QPushButton>
#include <QToolBar>
#include <QLabel>
#include <QLineEdit>
#include <QAction>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QToolBar* tb=addToolBar("Tool Bar");
tb->setFloatable(false);
tb->setMovable(false);
QAction* action=new QAction("",NULL);
action->setToolTip("Open");//设置提示标签
//action->setIcon();//设置图标
tb->addAction(action);
QPushButton* b=new QPushButton("Button");
QLabel* l=new QLabel("Label");
QLineEdit* e=new QLineEdit();
tb->addWidget(b);
tb->addWidget(l);
tb->addWidget(e);
}
MainWindow::~MainWindow()
{
}
27课第二节,28课第二节暂时放过
文本编辑组件
Qt提供了多种文本编辑组件,以下是其中三种常用的文本编辑组件:
-
QPlainTextEdit: QPlainTextEdit是一个用于多行纯文本编辑的组件。它提供了基本的文本编辑功能,可以显示和编辑大量文本数据。使用QPlainTextEdit,您可以进行文本的输入、编辑、复制、粘贴等操作。它支持自动换行、滚动条、文本格式化等特性。
-
QTextEdit: QTextEdit是一个富文本编辑组件,可以用于显示和编辑带有格式的富文本内容,例如文字、图像、超链接、表格等。QTextEdit支持多种文本格式和样式,可以进行精细的排版和格式化设置。它还支持撤销/重做、剪切/复制/粘贴等编辑操作,并且可以连接自定义的信号槽处理编辑内容的变化。
-
QLineEdit: QLineEdit是一个用于单行文本输入的组件。它通常用于接收用户的简短输入,例如用户名、密码、搜索关键词等。QLineEdit提供了基本的文本输入验证、清除按钮、输入提示等功能。它还支持捕获和处理特定的键盘事件和焦点事件,以及连接信号槽来响应文本变化和完成输入操作。
Qt常用文本编辑组件的内置功能
- 右键弹出式菜单
- 快捷键功能
- 复制,粘贴,剪切等
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
QLineEdit lineEdit;
QPlainTextEdit plainEdit;
QTextEdit textEdit;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
主窗口中的状态栏
状态栏的概念和意义
- 状态栏是应用程序中输出简要信息的区域
- 状态栏一般位于主窗口最底部
- 状态栏中的消息类型
- 实时消息,如:当前程序状态
- 永久消息,如:程序版本号,机构名称
- 进度消息,如:进度条提示,百分比提示
在Qt中提供与状态栏相关的类组件
- 状态栏(QStatusBar)
- 任意组件(QWidget)
Qt状态栏的设计原则
- 左边的区域用于输出实时消息
- 右边的区域用于设置永久消息
- addWidget在状态栏左半部分添加组件
- addPerManentWidget在状态栏右半部分添加组件
mainwindow.cpp
#include "mainwindow.h"
#include <QPushButton>
#include <QToolBar>
#include <QLabel>
#include <QLineEdit>
#include <QAction>
#include <QStatusBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QStatusBar* sb=statusBar();
QPushButton* button=new QPushButton("button");
QLineEdit* e=new QLineEdit();
QLabel* l=new QLabel("lable");
sb->addPermanentWidget(button);
sb->addPermanentWidget(l);
sb->addPermanentWidget(e);
sb->showMessage("D.T.SoftWare");//输出一条实时消息
}
MainWindow::~MainWindow()
{
}
进程和线程的概念