QT学习笔记——06-Day16_C++_QT

在学习QT总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。windows

06-Day16_C++_QT网络

目录:
1、经常使用控件
一、自定义控件封装
2、Qt消息机制和事件
一、QLabel中鼠标经常使用事件
二、定时器第一种方式
三、定时器第二种方式
四、event事件
五、事件过滤器
3、绘图和绘图设备
一、QPainter基本绘图
二、绘图高级设置
三、手动调用绘图事件
四、绘图设备
4、文件
一、文件读写操做
二、文件信息
三、文本流和数据流
5、总结框架

 

1、经常使用控件ide

在搭建Qt窗口界面的时候,在一个项目中不少窗口,或者是窗口中的某个模块会被常常性的重复使用。通常遇到这种状况咱们都会将这个窗口或者模块拿出来作成一个独立的窗口类,以备之后重复使用。
在使用Qt的ui文件搭建界面的时候,工具栏栏中只为咱们提供了标准的窗口控件,若是咱们想使用自定义控件怎么办?svg


例如:能够从QWidget派生出一个类SmallWidget,实现了一个自定窗口,
函数

一、自定义控件封装工具

界面设置以下:布局

新建工程:选择“QWidget”,勾选“显示主界面”(默认勾选)post

1)在工程处右键“添加新文件”,选择“QT”—“设计师界面类”——>“choose”,选择界面模板“Widget”,选择类名,输入:SmallWidget。而后在smallwidget.ui中添加“Spin Box”和“Horizontal Slider”,并将其更改成合适大小。学习

2)在widget.ui中拖拽Widget,右键提高为——>类名写入(SmallWidget)—勾选:“全局包含”—点击:添加—提高

3)添加两个按钮“PushButton”,并更更名字

4)对外接口:setValue和getValue

在smallwidget.cpp中更改

 1 #include "smallwidget.h"
 2 #include "ui_smallwidget.h"
 3 
 4 SmallWidget::SmallWidget(QWidget *parent) :
 5     QWidget(parent),
 6     ui(new Ui::SmallWidget)
 7 {
 8     ui->setupUi(this);
 9 
10     //QSpinBox移动,Slider跟着移动 发生了重载,函数指向:返回值(做用域)参数类型
11     void(QSpinBox:: * signal)(int) = &QSpinBox::valueChanged;
12     connect(ui->spinBox, signal, ui->horizontalSlider,&QSlider::setValue);
13 
14     //Slider移动,SpinBox跟着移动
15     connect(ui->horizontalSlider, &QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
16 
17 
18 
19 }
20 
21 void SmallWidget::setValue(int v)
22 {
23     ui->spinBox->setValue(v);
24 }
25 
26 int SmallWidget::getValue()
27 {
28     return ui->spinBox->value();
29 }
30 
31 
32 SmallWidget::~SmallWidget()
33 {
34     delete ui;
35 }

在smallwidget.h中更改

 1 #ifndef SMALLWIDGET_H
 2 #define SMALLWIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class SmallWidget;
 8 }
 9 
10 class SmallWidget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit SmallWidget(QWidget *parent = 0);
16     ~SmallWidget();
17 
18     void setValue(int v);
19 
20     int getValue();
21 
22 
23 private:
24     Ui::SmallWidget *ui;
25 };
26 
27 #endif // SMALLWIDGET_H

在widget.cpp中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QDebug>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10 
11     //点击设置,设置到一半的位置
12     connect(ui->btnSet,&QPushButton::clicked,[=](){
13         ui->widget->setValue(50);
14     });
15 
16     //点击获取,拿到当前值
17     connect(ui->btnGet,&QPushButton::clicked,[=](){
18         qDebug() << "当前值为:" << ui->widget->getValue();
19     });
20 
21 }
22 
23 Widget::~Widget()
24 {
25     delete ui;
26 }

 

2、Qt消息机制和事件


事件
事件(event)是由系统或者 Qt 自己在不一样的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口须要从新绘制的时候,都会发出一个相应的事件。一些事件在对用户操做作出响应时发出,如键盘事件等;另外一些事件则是由系统自动发出,如计时器事件。
在前面咱们也曾经简单提到,Qt 程序须要在main()函数建立一个QApplication对象,而后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数以后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将建立一个事件对象。Qt 中全部事件类都继承于QEvent。在事件对象建立完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler),关于这一点,会在后边详细说明。
在全部组件的父类QWidget中,定义了不少事件处理的回调函数,如
》 keyPressEvent()
》 keyReleaseEvent()
》 mouseDoubleClickEvent()
》 mouseMoveEvent()
》 mousePressEvent()
》 mouseReleaseEvent() 等。
这些函数都是 protected virtual 的,也就是说,咱们能够在子类中从新实现这些函数。

》EventLabel继承了QLabel,覆盖了mousePressEvent()、mouseMoveEvent()和MouseReleaseEvent()三个函数。咱们并无添加什么功能,只是在鼠标按下(press)、鼠标移动(move)和鼠标释放(release)的时候,把当前鼠标的坐标值显示在这个Label上面。因为QLabel是支持 HTML 代码的,所以咱们直接使用了 HTML 代码来格式化文字。
》QString的arg()函数能够自动替换掉QString中出现的占位符。其占位符以 % 开始,后面是占位符的位置,例如 %1,%2 这种。
QString("[%1, %2]").arg(x).arg(y);
语句将会使用x替换 %1,y替换 %2,所以,生成的QString为[x, y]。
》在mouseReleaseEvent()函数中,咱们使用了另一种QString的构造方法。咱们使用相似 C 风格的格式化函数sprintf()来构造QString。
运行上面的代码,当咱们点击了一下鼠标以后,label 上将显示鼠标当前坐标值。

为何要点击鼠标以后才能在mouseMoveEvent()函数中显示鼠标坐标值?
这是由于QWidget中有一个mouseTracking属性,该属性用于设置是否追踪鼠标。只有鼠标被追踪时,mouseMoveEvent()才会发出。若是mouseTracking是 false(默认便是),组件在至少一次鼠标点击以后,才可以被追踪,也就是可以发出mouseMoveEvent()事件。若是mouseTracking为 true,则mouseMoveEvent()直接能够被发出。


一、QLabel中鼠标经常使用事件

新建工程:选择“QWidget”,勾选“显示主界面”(默认勾选)

1)而后在widget.ui中添加“Label”
2)在工程处右键“添加新文件”,选择“C++”—“C++ Class”——>“choose”,输入类名:MyLabel,选择继承于“QWidget”,。
3)更改3处QLabel,mylabel.h中(更改头文件#include <QLabel>和class MyLabel : public QLabel);在mylabel.cpp(更改MyLabel::MyLabel(QWidget *parent) : QLabel(parent))
4)在widget.ui,在“Label”右键提高为——>基类名称,选择“QLabel”;提高的类名称,写入:MyLabel—勾选:“全局包含”(选不选都行)—点击:添加—提高(右上角QLabel更改成MyLabel)

在mylabel.cpp中更改

Qt5.5乱码问题?qDebug() << str更改成qDebug() << str.toUtf8().data(); QString转char*:先转成QByteArray类型,再转char*)

 1 #ifndef MYLABEL_H
 2 #define MYLABEL_H
 3 
 4 #include <QLabel>
 5 
 6 class MyLabel : public QLabel
 7 {
 8     Q_OBJECT
 9 public:
10     explicit MyLabel(QWidget *parent = 0);
11 
12    //捕获事件
13     //鼠标进入
14     void enterEvent(QEvent *);
15 
16     //鼠标离开
17     void leaveEvent(QEvent *);
18 
19 
20     //鼠标按下
21      void mousePressEvent(QMouseEvent * ev);
22      //鼠标释放
23      void mouseReleaseEvent(QMouseEvent * ev);
24      //鼠标移动
25      void mouseMoveEvent(QMouseEvent * ev);
26 };
27 
28 #endif // MYLABEL_H

在mylabel.h中更改

 1 #include "mylabel.h"
 2 #include<QDebug>
 3 #include<QMouseEvent>
 4 
 5 MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
 6 {
 7     //设置鼠标追踪
 8     this->setMouseTracking(true);
 9 }
10 
11 //鼠标进入
12 void MyLabel::enterEvent(QEvent *)
13 {
14     //qDebug() << "鼠标进入了!!!";
15 }
16 //鼠标离开
17 void MyLabel::leaveEvent(QEvent *)
18 {
19      //qDebug() << "鼠标离开了!!!";
20 }
21 
22 //鼠标按下
23  void MyLabel::mousePressEvent(QMouseEvent * ev)
24  {
25      //若是鼠标案子啊的是左键,而后提示内容
26      //找按下的位置
27      if(ev->button() == Qt::LeftButton)
28      {
29         QString str = QString("鼠标按下了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
30 
31 
32         qDebug() << str.toUtf8().data();
33      }
34  }
35  //鼠标释放
36  void MyLabel::mouseReleaseEvent(QMouseEvent * ev)
37  {
38      if(ev->button() == Qt::LeftButton)
39      {  
      //QString拼接字符串 40 QString str = QString("鼠标释放了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y()); 41 42 qDebug() << str.toUtf8().data(); 43 } 44 } 45 //鼠标移动 46 void MyLabel::mouseMoveEvent(QMouseEvent * ev) 47 { 48 //持续状态,须要用buttons,用&与操做符进行判断 49 // if(ev->buttons() & Qt::LeftButton) 50 // { 51 QString str = QString("鼠标移动了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y()); 52 53 qDebug() << str.toUtf8().data(); 54 // } 55 56 }

 

二、定时器第一种方式

1)timerEvent事件

2)启动定时器,startTimer(毫秒),返回值就是Id号

3)区分定时器 timerId

在widget.ui中添加两个“Label”,

在widget.h中更改

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 
21     //定时器事件
22     void timerEvent(QTimerEvent *);
23 
24     //定时器标识号
25     int id1;
26     int id2;
27 
28 };
29 
30 #endif // WIDGET_H

在widget.cpp中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QTimerEvent>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10 
11     //启动定时器
12     id1 = startTimer(1000);//每1000毫秒调用一次timeEvent
13     id2 = startTimer(2000);
14 }
15 
16 void Widget::timerEvent(QTimerEvent * e)
17 {
18     if(e->timerId() == id1)
19     {
20         static int num = 0;
21         ui->label_2->setText(QString::number(num++));
22     }
23     if(e->timerId() == id2)
24     {
25         static int num2 = 0;
26         ui->label_3->setText(QString::number(num2++));
27     }
28 
29 }
30 
31 Widget::~Widget()
32 {
33     delete ui;
34 }

三、定时器第二种方式

1)QTimer头文件

2)建立 QTimer* timer

3)启动定时器 timer->start(毫秒)

4)发送信号:timeout

5)暂停stop

在widget.ui中添加1个“Label”,一个“Push Button”

在widget.cpp中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QTimerEvent>
 4 #include<QTimer>
 5 
 6 Widget::Widget(QWidget *parent) :
 7     QWidget(parent),
 8     ui(new Ui::Widget)
 9 {
10     ui->setupUi(this);
11 
12     //启动定时器
13     id1 = startTimer(1000);//每1000毫秒调用一次timeEvent
14     id2 = startTimer(2000);
15 
16     //定时器第二种方式
17     QTimer* timer1 = new QTimer(this);
18     //启动定时器对象
19     timer1->start(500);//毫秒作单位
20     //每隔0.5秒发送信号
21     connect(timer1, &QTimer::timeout,[=](){
22         static int num = 0;
23         ui->label_4->setText(QString::number(num++));
24     });
25 
26     //点击按钮,暂停定时器
27     connect(ui->pushButton,&QPushButton::clicked,[=](){
28         timer1->stop();
29     });
30 
31 }
32 
33 void Widget::timerEvent(QTimerEvent * e)
34 {
35     if(e->timerId() == id1)
36     {
37         static int num = 0;
38         ui->label_2->setText(QString::number(num++));
39     }
40     if(e->timerId() == id2)
41     {
42         static int num2 = 0;
43         ui->label_3->setText(QString::number(num2++));
44     }
45 
46 }
47 
48 Widget::~Widget()
49 {
50     delete ui;
51 }

四、event事件


事件对象建立完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不一样的类型,分发给不一样的事件处理器(event handler)。

如上所述,event()函数主要用于事件的分发。因此,若是你但愿在事件分发以前作一些操做,就能够重写这个event()函数了。例如,咱们但愿在一个QWidget组件中监听 tab 键的按下,那么就能够继承QWidget,并重写它的event()函数,来达到这个目的。

 

也就是说,event()函数中实际是经过事件处理器来响应一个具体的事件。这至关于event()函数将具体事件的处理“委托”给具体的事件处理器。而这些事件处理器是 protected virtual 的,所以,咱们重写了某一个事件处理器,便可让 Qt 调用咱们本身实现的版本。

由此能够见,event()是一个集中处理不一样类型的事件的地方。若是你不想重写一大堆事件处理器,就能够重写这个event()函数,经过QEvent::type()判断不一样的事件。鉴于重写event()函数须要十分当心注意父类的同名函数的调用,一不留神就可能出现问题,因此通常仍是建议只重写事件处理器(固然,也必须记得是否是应该调用父类的同名处理器)。这其实暗示了event()函数的另一个做用:屏蔽掉某些不须要的事件处理器。


1)主要功能:事件的分发

2)bool event(QEvent * e)

3)返回值若是是true,表明用户本身处理

4)false系统处理,最好抛给父类去处理

5)static_cast<转换类型>(原对象)

6)e-type 具体事件

在mylabel.h中更改

 1 #ifndef MYLABEL_H
 2 #define MYLABEL_H
 3 
 4 #include <QLabel>
 5 
 6 class MyLabel : public QLabel
 7 {
 8     Q_OBJECT
 9 public:
10     explicit MyLabel(QWidget *parent = 0);
11 
12    //捕获事件
13     //鼠标进入
14     void enterEvent(QEvent *);
15 
16     //鼠标离开
17     void leaveEvent(QEvent *);
18 
19 
20     //鼠标按下
21      void mousePressEvent(QMouseEvent * ev);
22      //鼠标释放
23      void mouseReleaseEvent(QMouseEvent * ev);
24      //鼠标移动
25      void mouseMoveEvent(QMouseEvent * ev);
26 
27      //事件分发,Event事件
28      bool event(QEvent *e);
29 
30 };
31 
32 #endif // MYLABEL_H

在mylabel.cpp中更改

 1 #include "mylabel.h"
 2 #include<QDebug>
 3 #include<QMouseEvent>
 4 
 5 MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
 6 {
 7     //设置鼠标追踪
 8     //this->setMouseTracking(true);
 9 }
10 
11 //鼠标进入
12 void MyLabel::enterEvent(QEvent *)
13 {
14     //qDebug() << "鼠标进入了!!!";
15 }
16 //鼠标离开
17 void MyLabel::leaveEvent(QEvent *)
18 {
19      //qDebug() << "鼠标离开了!!!";
20 }
21 
22 //鼠标按下
23  void MyLabel::mousePressEvent(QMouseEvent * ev)
24  {
25      //若是鼠标案子啊的是左键,而后提示内容
26      //找按下的位置
27 //     if(ev->button() == Qt::LeftButton)
28 //     {
   
   
   
   
29         QString str = QString("鼠标按下了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
30 
31 
32         qDebug() << str.toUtf8().data();
33 //     }
34  }
35  //鼠标释放
36  void MyLabel::mouseReleaseEvent(QMouseEvent * ev)
37  {
38 //     if(ev->button() == Qt::LeftButton)
39 //     {
   
   
   
   
40         QString str = QString("鼠标释放了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
41 
42         qDebug() << str.toUtf8().data();
43 //     }
44  }
45  //鼠标移动
46  void MyLabel::mouseMoveEvent(QMouseEvent * ev)
47  {
48      //持续状态,须要用buttons,用&与操做符进行判断
49 //     if(ev->buttons() & Qt::LeftButton)
50 //     {
   
   
   
   
51         QString str = QString("鼠标移动了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
52 
53         qDebug() << str.toUtf8().data();
54 //     }
55 
56  }
57 
58  bool MyLabel::event(QEvent *e)
59  {
60      //一般不会作拦截,event只要分发事件就能够了
61      if(e->type() == QEvent::MouseButtonPress)
62      {
63         QMouseEvent* ev = static_cast<QMouseEvent*>(e);
64 
65          QString str = QString("Event:::鼠标按下了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
66 
67          qDebug() << str.toUtf8().data();
68 
69          //只有鼠标按下,本身处理,返回true
70          return true;
71      }
72 
73      //其余事件,让父亲作默认处理
74 
75      return QLabel::event(e);
76 
77  }

 

五、事件过滤器


有时候,对象须要查看、甚至要拦截发送到另外对象的事件。例如,对话框可能想要拦截按键事件,不让别的组件接收到;或者要修改回车键的默认处理。

 

经过前面的章节,咱们已经知道,Qt 建立了QEvent事件对象以后,会调用QObject的event()函数处理事件的分发。显然,咱们能够在event()函数中实现拦截的操做。因为event()函数是 protected 的,所以,须要继承已有类。若是组件不少,就须要重写不少个event()函数。这固然至关麻烦,更不用说重写event()函数还得当心一堆问题。好在 Qt 提供了另一种机制来达到这一目的:事件过滤器。

 

QObject有一个eventFilter()函数,用于创建事件过滤器。函数原型以下:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

这个函数正如其名字显示的那样,是一个“事件过滤器”。所谓事件过滤器,能够理解成一种过滤代码。事件过滤器会检查接收到的事件。若是这个事件是咱们感兴趣的类型,就进行咱们本身的处理;若是不是,就继续转发。这个函数返回一个 bool 类型,若是你想将参数 event 过滤出来,好比,不想让它继续转发,就返回 true,不然返回 false。事件过滤器的调用时间是目标对象(也就是参数里面的watched对象)接收到事件对象以前。也就是说,若是你在事件过滤器中中止了某个事件,那么,watched对象以及之后全部的事件过滤器根本不会知道这么一个事件。

 

注意,

事件过滤器和被安装过滤器的组件必须在同一线程,不然,过滤器将不起做用。另外,若是在安装过滤器以后,这两个组件到了不一样的线程,那么,只有等到两者从新回到同一线程的时候过滤器才会有效。


event事件解析图

1)哪一个控件须要过滤事件,就给哪一个控件安装过滤器

2)步骤1:安装过滤器

3)ui->label->installEventFilter(this);

4)步骤2:重写事件

在“widget.h”中更改

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 
21     //定时器事件
22     void timerEvent(QTimerEvent *);
23 
24     //定时器标识号
25     int id1;
26     int id2;
27 
28     //事件过滤器的事件
29     bool eventFilter(QObject *, QEvent *);
30 
31 };
32 
33 #endif // WIDGET_H

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QTimerEvent>
 4 #include<QTimer>
 5 #include<QMouseEvent>
 6 #include<QDebug>
 7 
 8 Widget::Widget(QWidget *parent) :
 9     QWidget(parent),
10     ui(new Ui::Widget)
11 {
12     ui->setupUi(this);
13 
14     //启动定时器
15     id1 = startTimer(1000);//每1000毫秒调用一次timeEvent
16     id2 = startTimer(2000);
17 
18     //定时器第二种方式
19     QTimer* timer1 = new QTimer(this);
20     //启动定时器对象
21     timer1->start(500);//毫秒作单位
22     //每隔0.5秒发送信号
23     connect(timer1, &QTimer::timeout,[=](){
24         static int num = 0;
25         ui->label_4->setText(QString::number(num++));
26     });
27 
28     //点击按钮,暂停定时器
29     connect(ui->pushButton,&QPushButton::clicked,[=](){
30         timer1->stop();
31     });
32 
33 
34     //给ui->label作事件过滤器,拦截
35     //步骤1:给控件安装过滤器
36     //参数this经过父窗口给label安装过滤器
37     ui->label->installEventFilter(this);
38     //步骤2:重写eventFilter事件
39 
40 }
41 
42 bool Widget::eventFilter(QObject * obj, QEvent *e)
43 {
44     if(obj == ui->label)
45     {
46         if(e->type() == QEvent::MouseButtonPress)
47         {
48            QMouseEvent* ev = static_cast<QMouseEvent*>(e);
49 
50             QString str = QString("事件过滤器:::鼠标按下了!!! x = %1 y = %2").arg(ev->x()).arg(ev->y());
51 
52             qDebug() << str.toUtf8().data();
53 
54             //只有鼠标按下,本身处理,返回true
55             return true;
56         }
57 
58 
59     }
60     //其余让父类处理
61     return QWidget::eventFilter(obj, e);
62 
63 }
64 
65 void Widget::timerEvent(QTimerEvent * e)
66 {
67     if(e->timerId() == id1)
68     {
69         static int num = 0;
70         ui->label_2->setText(QString::number(num++));
71     }
72     if(e->timerId() == id2)
73     {
74         static int num2 = 0;
75         ui->label_3->setText(QString::number(num2++));
76     }
77 
78 }
79 
80 Widget::~Widget()
81 {
82     delete ui;
83 }

 


总结

Qt 的事件是整个 Qt 框架的核心机制之一,也比较复杂。说它复杂,更可能是由于它涉及到的函数众多,而处理方法也不少,有时候让人难以选择。如今咱们简单总结一下 Qt 中的事件机制。

Qt 中有不少种事件:鼠标事件、键盘事件、大小改变的事件、位置移动的事件等等。如何处理这些事件,实际有两种选择:

》全部事件对应一个事件处理函数,在这个事件处理函数中用一个很大的分支语句进行选择,其表明做就是 win32 API 的WndProc()函数:

LRESULT CALLBACK WndProc(HWND hWnd,

                         UINT message,

                         WPARAM wParam,

                         LPARAM lParam)

在这个函数中,咱们须要使用switch语句,选择message参数的类型进行处理,典型代码是:

switch(message)

{

    case WM_PAINT:

        // ...

        break;

    case WM_DESTROY:

        // ...

        break;

    ...

}

》每一种事件对应一个事件处理函数。Qt 就是使用的这么一种机制:

  mouseEvent()

  keyPressEvent()

  …

Qt 具备这么多种事件处理函数,确定有一个地方对其进行分发,不然,Qt 怎么知道哪种事件调用哪个事件处理函数呢?这个分发的函数,就是event()。显然,当QMouseEvent产生以后,event()函数将其分发给mouseEvent()事件处理器进行处理。

event()函数会有两个问题:

》event()函数是一个 protected 的函数,这意味着咱们要想重写event(),必须继承一个已有的类。试想,个人程序根本不想要鼠标事件,程序中全部组件都不容许处理鼠标事件,是否是我得继承全部组件,一一重写其event()函数?protected 函数带来的另一个问题是,若是我基于第三方库进行开发,而对方没有提供源代码,只有一个连接库,其它都是封装好的。我怎么去继承这种库中的组件呢?

》event()函数的确有必定的控制,不过有时候个人需求更严格一些:我但愿那些组件根本看不到这种事件。event()函数虽然能够拦截,但其实也是接收到了QMouseEvent对象。我连让它收都收不到。这样作的好处是,模拟一种系统根本没有那个事件的效果,因此其它组件根本不会收到这个事件,也就无需修改本身的事件处理函数。这种需求怎么办呢?

这两个问题是event()函数没法处理的。因而,Qt 提供了另一种解决方案:事件过滤器。事件过滤器给咱们一种能力,让咱们可以彻底移除某种事件。事件过滤器能够安装到任意QObject类型上面,而且能够安装多个。若是要实现全局的事件过滤器,则能够安装到QApplication或者QCoreApplication上面。这里须要注意的是,若是使用installEventFilter()函数给一个对象安装事件过滤器,那么该事件过滤器只对该对象有效,只有这个对象的事件须要先传递给事件过滤器的eventFilter()函数进行过滤,其它对象不受影响。若是给QApplication对象安装事件过滤器,那么该过滤器对程序中的每个对象都有效,任何对象的事件都是先传给eventFilter()函数。

事件过滤器能够解决刚刚咱们提出的event()函数的两点不足:

》首先,事件过滤器不是 protected 的,所以咱们能够向任何QObject子类安装事件过滤器;

》其次,事件过滤器在目标对象接收到事件以前进行处理,若是咱们将事件过滤掉,目标对象根本不会见到这个事件。

事实上,还有一种方法,咱们没有介绍。Qt 事件的调用最终都会追溯到QCoreApplication::notify()函数,所以,最大的控制权其实是重写QCoreApplication::notify()。这个函数的声明是:

virtual bool QCoreApplication::notify ( QObject * receiver,

                                        QEvent * event );

该函数会将event发送给receiver,也就是调用receiver->event(event),其返回值就是来自receiver的事件处理器。注意,这个函数为任意线程的任意对象的任意事件调用,所以,它不存在事件过滤器的线程的问题。不过咱们并不推荐这么作,由于notify()函数只有一个,而事件过滤器要灵活得多。

 

如今咱们能够总结一下 Qt 的事件处理,其实是有五个层次:

》重写paintEvent()、mousePressEvent()等事件处理函数。这是最普通、最简单的形式,同时功能也最简单。

》重写event()函数。event()函数是全部对象的事件入口,QObject和QWidget中的实现,默认是把事件传递给特定的事件处理函数。

》在特定对象上面安装事件过滤器。该过滤器仅过滤该对象接收到的事件。

》在QCoreApplication::instance()上面安装事件过滤器。该过滤器将过滤全部对象的全部事件,所以和notify()函数同样强大,可是它更灵活,由于能够安装多个过滤器。全局的事件过滤器能够看到 disabled 组件上面发出的鼠标事件。全局过滤器有一个问题:只能用在主线程。

重写QCoreApplication::notify()函数。这是最强大的,和全局事件过滤器同样提供彻底控制,而且不受线程的限制。可是全局范围内只能有一个被使用(由于QCoreApplication是单例的)。


 

3、绘图和绘图设备


QPainter

Qt 的绘图系统容许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。

QPainter用来执行绘制的操做;QPaintDevice是一个二维空间的抽象,这个二维空间容许QPainter在其上面进行绘制,也就是QPainter工做的空间;QPaintEngine提供了画笔(QPainter)在不一样的设备上进行绘制的统一的接口。QPaintEngine类应用于QPainter和QPaintDevice之间,一般对开发人员是透明的。除非你须要自定义一个设备,不然你是不须要关心QPaintEngine这个类的。咱们能够把QPainter理解成画笔;把QPaintDevice理解成使用画笔的地方,好比纸张、屏幕等;而对于纸张、屏幕而言,确定要使用不一样的画笔绘制,为了统一使用一种画笔,咱们设计了QPaintEngine类,这个类让不一样的纸张、屏幕都能使用一种画笔。

下图给出了这三个类之间的层次结构:

上面的示意图告诉咱们,Qt 的绘图系统其实是,使用QPainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通信(也就是翻译QPainter的指令)。


一、QPainter基本绘图

1)绘图事件paintEvent

2)QPainter painter(绘图设备this)

3)draw 线 圆 矩形 文字

4)QPen 设置笔宽度、样式、让画家用 笔

5)QBrush 设置画刷样式,让画家用画刷

新建工程:选择“QWidget”,勾选“显示主界面”(默认勾选)

在“widget.h”中更改

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 
21 public:
22     //绘图事件
23     void paintEvent(QPaintEvent*);
24 
25 };
26 
27 #endif // WIDGET_H

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QPainter>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10 }
11 
12 void Widget::paintEvent(QPaintEvent*)
13 {
14     //建立画家
15     QPainter painter(this);
16 
17     //设置画笔颜色
18     QPen pen(QColor(255,0,0));
19     //设置笔宽度
20     pen.setWidth(3);
21     //设置笔的风格
22     pen.setStyle(Qt::DotLine);
23     //画家用这只笔
24     painter.setPen(pen);
25 
26 
27     //画刷填充颜色
28     QBrush brush(Qt::cyan);
29     //让画家使用画刷
30     brush.setStyle(Qt::Dense4Pattern);
31     painter.setBrush(brush);
32 
33     //利用画家画画
34     //画线
35     painter.drawLine(QPoint(0,0),QPoint(100,100));
36 
37     //画圆(椭圆)
38     painter.drawEllipse(QPoint(100,100),100,50);
39 
40     //画矩形
41     painter.drawRect(QRect(10,10,50,50));
42 
43     //画字体
44     painter.drawText(QRect(10,200,150,50),"好好学习,每天向上");
45 
46 }
47 
48 
49 Widget::~Widget()
50 {
51     delete ui;
52 }

二、绘图高级设置

1)抗锯齿 painter.setRenderHint(QPainter::Antialiasing);

2)画家移动 painter.translate(QPoint(100,0));

3)画家状态 painter.save();  painter.restore();

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QPainter>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10 }
11 
12 void Widget::paintEvent(QPaintEvent*)
13 {
14     //建立画家
15     QPainter painter(this);
16 
17     //高级设置
18 //    painter.drawEllipse(QPoint(100,100),50,50);
19 //    //设置抗锯齿,效率低
20 //    painter.setRenderHint(QPainter::Antialiasing);
21 //    painter.drawEllipse(QPoint(200,100),50,50);
22 
23 
24     painter.drawRect(QRect(20,20,50,50));
25 
26     //移动画家
27     painter.translate(QPoint(100,0));
28 
29     //保存状态
30     painter.save();
31 
32     painter.drawRect(QRect(20,20,50,50));
33 
34     painter.translate(QPoint(100,0));
35 
36     //取出状态
37     painter.restore();
38 
39     painter.drawRect(QRect(20,20,50,50));
40 
41 
42 //    //设置画笔颜色
43 //    QPen pen(QColor(255,0,0));
44 //    //设置笔宽度
45 //    pen.setWidth(3);
46 //    //设置笔的风格
47 //    pen.setStyle(Qt::DotLine);
48 //    //画家用这只笔
49 //    painter.setPen(pen);
50 
51 
52 //    //画刷填充颜色
53 //    QBrush brush(Qt::cyan);
54 //    //让画家使用画刷
55 //    brush.setStyle(Qt::Dense4Pattern);
56 //    painter.setBrush(brush);
57 
58 //    //利用画家画画
59 //    //画线
60 //    painter.drawLine(QPoint(0,0),QPoint(100,100));
61 
62 //    //画圆(椭圆)
63 //    painter.drawEllipse(QPoint(100,100),100,50);
64 
65 //    //画矩形
66 //    painter.drawRect(QRect(10,10,50,50));
67 
68 //    //画字体
69 //    painter.drawText(QRect(10,200,150,50),"好好学习,每天向上");
70 
71 }
72 
73 
74 Widget::~Widget()
75 {
76     delete ui;
77 }

三、手动调用绘图事件

1)update

2)画家能够画图片

3)drawPixmap(x,y,文件路径)

在“widget.h”中更改

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 
21 public:
22     //绘图事件
23     void paintEvent(QPaintEvent*);
24 
25     int posX;
26 
27 };
28 
29 #endif // WIDGET_H

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QPainter>
 4 
 5 Widget::Widget(QWidget *parent) :
 6     QWidget(parent),
 7     ui(new Ui::Widget)
 8 {
 9     ui->setupUi(this);
10 
11     //点击按钮,移动图片
12     posX = 10;
13 
14     connect(ui->pushButton,&QPushButton::clicked,[=](){
15         posX += 10;
16         //手动调用绘图事件
17         update();
18     });
19 
20 }
21 
22 void Widget::paintEvent(QPaintEvent*)
23 {
24     //建立画家
25     QPainter painter(this);
26 
27     //画图片
28     painter.drawPixmap(posX,100,QPixmap(":/Image/OnePiece.png"));
29 
30     //若是出屏幕,强制变回10
31     if(posX > this->width())
32     {
33         posX = 10;
34     }
35 
36     //高级设置
37 //    painter.drawEllipse(QPoint(100,100),50,50);
38 //    //设置抗锯齿,效率低
39 //    painter.setRenderHint(QPainter::Antialiasing);
40 //    painter.drawEllipse(QPoint(200,100),50,50);
41 
42 
43 //    painter.drawRect(QRect(20,20,50,50));
44 
45 //    //移动画家
46 //    painter.translate(QPoint(100,0));
47 
48 //    //保存状态
49 //    painter.save();
50 
51 //    painter.drawRect(QRect(20,20,50,50));
52 
53 //    painter.translate(QPoint(100,0));
54 
55 //    //取出状态
56 //    painter.restore();
57 
58 //    painter.drawRect(QRect(20,20,50,50));
59 
60 
61 //    //设置画笔颜色
62 //    QPen pen(QColor(255,0,0));
63 //    //设置笔宽度
64 //    pen.setWidth(3);
65 //    //设置笔的风格
66 //    pen.setStyle(Qt::DotLine);
67 //    //画家用这只笔
68 //    painter.setPen(pen);
69 
70 
71 //    //画刷填充颜色
72 //    QBrush brush(Qt::cyan);
73 //    //让画家使用画刷
74 //    brush.setStyle(Qt::Dense4Pattern);
75 //    painter.setBrush(brush);
76 
77 //    //利用画家画画
78 //    //画线
79 //    painter.drawLine(QPoint(0,0),QPoint(100,100));
80 
81 //    //画圆(椭圆)
82 //    painter.drawEllipse(QPoint(100,100),100,50);
83 
84 //    //画矩形
85 //    painter.drawRect(QRect(10,10,50,50));
86 
87 //    //画字体
88 //    painter.drawText(QRect(10,200,150,50),"好好学习,每天向上");
89 
90 }
91 
92 
93 Widget::~Widget()
94 {
95     delete ui;
96 }

 

四、绘图设备


绘图设备

绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类,分别是QPixmap、QBitmap、QImage和 QPicture。其中,

》QPixmap专门为图像在屏幕上的显示作了优化

》QBitmap是QPixmap的一个子类,它的色深限定为1,可使用 QPixmap的isQBitmap()函数来肯定这个QPixmap是否是一个QBitmap。

》QImage专门为图像的像素级访问作了优化。

》QPicture则能够记录和重现QPainter的各条命令。

 

QPixmap、QBitmap、QImage

QPixmap继承了QPaintDevice,所以,你可使用QPainter直接在上面绘制图形。QPixmap也能够接受一个字符串做为一个文件的路径来显示这个文件,好比你想在程序之中打开png、jpeg之类的文件,就可使用 QPixmap。使用QPainter的drawPixmap()函数能够把这个文件绘制到一个QLabel、QPushButton或者其余的设备上面。QPixmap是针对屏幕进行特殊优化的,所以,它与实际的底层显示设备息息相关。注意,这里说的显示设备并非硬件,而是操做系统提供的原生的绘图引擎。因此,在不一样的操做系统平台下,QPixmap的显示可能会有所差异。

QBitmap继承自QPixmap,所以具备QPixmap的全部特性,提供单色图像。QBitmap的色深始终为1. 色深这个概念来自计算机图形学,是指用于表现颜色的二进制的位数。咱们知道,计算机里面的数据都是使用二进制表示的。为了表示一种颜色,咱们也会使用二进制。好比咱们要表示8种颜色,须要用3个二进制位,这时咱们就说色深是3. 所以,所谓色深为1,也就是使用1个二进制位表示颜色。1个位只有两种状态:0和1,所以它所表示的颜色就有两种,黑和白。因此说,QBitmap其实是只有黑白两色的图像数据。

因为QBitmap色深小,所以只占用不多的存储空间,因此适合作光标文件和笔刷。

 

QPixmap使用底层平台的绘制系统进行绘制,没法提供像素级别的操做,而QImage则是使用独立于硬件的绘制系统,其实是本身绘制本身,所以提供了像素级别的操做,而且可以在不一样系统之上提供一个一致的显示形式。

 

QImage与QPixmap的区别

》QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的

》QPixmap依赖于所在的平台的绘图引擎,故例如反锯齿等一些效果在不一样的平台上可能会有不一样的显示效果,QImage使用Qt自身的绘图引擎,可在不一样平台上具备相同的显示效果

》因为QImage是独立于硬件的,也是一种QPaintDevice,所以咱们能够在另外一个线程中对其进行绘制,而不须要在GUI线程中处理,使用这一方式能够很大幅度提升UI响应速度。

》QImage可经过setPixpel()和pixel()等方法直接存取指定的像素。

QImage与QPixmap之间的转换:

》QImage转QPixmap

使用QPixmap的静态成员函数: fromImage()

QPixmap    fromImage(const QImage & image,

Qt::ImageConversionFlags flags = Qt::AutoColor)

》QPixmap转QImage:

使用QPixmap类的成员函数: toImage()

QImage toImage() const

 

QPicture

最后一个须要说明的是QPicture。这是一个能够记录和重现QPainter命令的绘图设备。 QPicture将QPainter的命令序列化到一个IO设备,保存为一个平台独立的文件格式。这种格式有时候会是“元文件(meta- files)”。Qt的这种格式是二进制的,不一样于某些本地的元文件,Qt的pictures文件没有内容上的限制,只要是可以被QPainter绘制的元素,不管是字体仍是pixmap,或者是变换,均可以保存进一个picture中。

QPicture是平台无关的,所以它可使用在多种设备之上,好比svg、pdf、ps、打印机或者屏幕。回忆下咱们这里所说的QPaintDevice,其实是说能够有QPainter绘制的对象。QPicture使用系统的分辨率,而且能够调整 QPainter来消除不一样设备之间的显示差别。

若是咱们要记录下QPainter的命令,首先要使用QPainter::begin()函数,将QPicture实例做为参数传递进去,以便告诉系统开始记录,记录完毕后使用QPainter::end()命令终止。


1)QPixmap、QBitMap(黑白色)、QImage、QPicture、QWidget

2)QPixmap:建立对象——QPixmap pix(w,h);fill填充色;保存save

3)QImage(w,h,format) 设置像素setPixel

4)QPicture重现记录,绘图指令,后缀名无要求

新建工程:选择“QWidget”,勾选“显示主界面”(默认勾选)

在“widget.h”中更改

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 private:
19     Ui::Widget *ui;
20 
21 public:
22     //绘图
23     void paintEvent(QPaintEvent *);
24 
25 };
26 
27 #endif // WIDGET_H

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QPainter>
 4 #include<QPicture>
 5 
 6 Widget::Widget(QWidget *parent) :
 7     QWidget(parent),
 8     ui(new Ui::Widget)
 9 {
10     ui->setupUi(this);
11 
12     //QPixmap绘图设备,对不一样平台显示作了优化
13 //    QPixmap pix(300, 300);
14 //    //设置默认填充色
15 //    pix.fill(Qt::white);
16 //    QPainter painter(&pix);
17 
18 //    painter.setPen(QPen(Qt::green));
19 //    painter.drawEllipse(QPoint(150, 150), 100, 100);
20 
21 //    //保存
22 //    pix.save("E:/pix.png");
23 
24     //QImage作绘图设备,对像素级访问进行了优化
25 //    QImage img(300,300,QImage::Format_RGB32);
26 //    img.fill(Qt::white);
27 //    QPainter painter(&img);
28 //    painter.setPen(QPen(Qt::blue));
29 //    painter.drawEllipse(QPoint(150, 150), 100, 100);
30 //    img.save("E:/img.png");
31 
32     
33     //QPicture绘图设备
34     QPicture pic;
35     QPainter painter;
36     painter.begin(&pic);
37     
38     painter.setPen(QPen(Qt::cyan));
39     painter.drawEllipse(QPoint(150, 150), 100, 100);
40     
41     painter.end();
42     
43     //保存
44     pic.save("E:/pic.wp");
45 
46 }
47 
48 void Widget::paintEvent(QPaintEvent *)
49 {
50     //QImage可修改像素
51 //    QImage img;
52 //    img.load(":/Image/Luffy.png");
53 
54 //    for(int i = 50; i < 150; i++)
55 //    {
56 //        for(int j = 50; j < 150; j++)
57 //        {
58 //            QRgb value = qRgb(255, 0, 0);
59 //            img.setPixel(i,j,value);
60 //        }
61 //    }
62 
63 //    QPainter painter(this);
64 //    painter.drawImage(QPoint(0,0), img);
65     
66     //重现绘图指令QPicture
67     QPicture pic;
68     pic.load("E:/pic.wp");
69     QPainter painter(this);
70     painter.drawPicture(0,0,pic);
71     
72 }
73 
74 
75 Widget::~Widget()
76 {
77     delete ui;
78 }

 

4、文件


文件操做是应用程序必不可少的部分。Qt 做为一个通用开发库,提供了跨平台的文件操做能力。Qt 经过QIODevice提供了对 I/O 设备的抽象,这些设备具备读写字节块的能力。下面是 I/O 设备的类图(Qt5):

》QIODevice:全部 I/O 设备类的父类,提供了字节块读写的通用操做以及基本接口;

》QFileDevice:Qt5新增长的类,提供了有关文件操做的通用实现。

》QFlie:访问本地文件或者嵌入资源;

》QTemporaryFile:建立和访问本地文件系统的临时文件;

》QBuffer:读写QbyteArray, 内存文件;

》QProcess:运行外部程序,处理进程间通信;

》QAbstractSocket:全部套接字类的父类;

》QTcpSocket:TCP协议网络数据传输;

》QUdpSocket:传输 UDP 报文;

》QSslSocket:使用 SSL/TLS 传输数据;

文件系统分类:

》顺序访问设备:

是指它们的数据只能访问一遍:从头走到尾,从第一个字节开始访问,直到最后一个字节,中途不能返回去读取上一个字节,这其中,QProcess、QTcpSocket、QUdpSoctet和QSslSocket是顺序访问设备。

》随机访问设备:

能够访问任意位置任意次数,还可使用QIODevice::seek()函数来从新定位文件访问位置指针,QFile、QTemporaryFile和QBuffer是随机访问设备,

 

基本文件操做

文件操做是应用程序必不可少的部分。Qt 做为一个通用开发库,提供了跨平台的文件操做能力。在全部的 I/O 设备中,文件 I/O 是最重要的部分之一。由于咱们大多数的程序依旧须要首先访问本地文件(固然,在云计算大行其道的未来,这一观点可能改变)。QFile提供了从文件中读取和写入数据的能力。

咱们一般会将文件路径做为参数传给QFile的构造函数。不过也能够在建立好对象最后,使用setFileName()来修改。QFile须要使用 / 做为文件分隔符,不过,它会自动将其转换成操做系统所须要的形式。例如 C:/windows 这样的路径在 Windows 平台下一样是能够的。

QFile主要提供了有关文件的各类操做,好比打开文件、关闭文件、刷新文件等。咱们可使用QDataStream或QTextStream类来读写文件,也可使用QIODevice类提供的read()、readLine()、readAll()以及write()这样的函数。值得注意的是,有关文件自己的信息,好比文件名、文件所在目录的名字等,则是经过QFileInfo获取,而不是本身分析文件路径字符串。

 

二进制文件读写

QDataStream提供了基于QIODevice的二进制数据的序列化。数据流是一种二进制流,这种流彻底不依赖于底层操做系统、CPU 或者字节顺序(大端或小端)。例如,在安装了 Windows 平台的 PC 上面写入的一个数据流,能够不通过任何处理,直接拿到运行了 Solaris 的 SPARC 机器上读取。因为数据流就是二进制流,所以咱们也能够直接读写没有编码的二进制数据,例如图像、视频、音频等。

QDataStream既可以存取 C++ 基本类型,如 int、char、short 等,也能够存取复杂的数据类型,例如自定义的类。实际上,QDataStream对于类的存储,是将复杂的类分割为不少基本单元实现的。

惟一须要注意的是,你必须按照写入的顺序,将数据读取出来。顺序颠倒的话,程序行为是不肯定的,严重时会直接形成程序崩溃。

 

文本文件读写

上一节咱们介绍了有关二进制文件的读写。二进制文件比较小巧,却不是人可读的格式。而文本文件是一种人可读的文件。为了操做这种文件,咱们须要使用QTextStream类。QTextStream和QDataStream的使用相似,只不过它是操做纯文本文件的。

QTextStream会自动将 Unicode 编码同操做系统的编码进行转换,这一操做对开发人员是透明的。它也会将换行符进行转换,一样不须要本身处理。QTextStream使用 16 位的QChar做为基础的数据存储单位,一样,它也支持 C++ 标准类型,如 int 等。实际上,这是将这种标准类型与字符串进行了相互转换。


一、文件读写操做

1)QFile file(路径)

2)file.open 打开方式 QIODevice::ReadOnly

3)file.readAll、readLine(file.atEnd判断是否到文件尾)

4)写QIODevice::WriteOnly

5)file.write(“....”);QFileDevice::Append追加

新建工程:选择“QWidget”,勾选“显示主界面”(默认勾选)

在“widget.ui”中添加“Widget”,在“Widget”中添加“Line Edit”和“Push Button”(水平布局),而后添加“Text Edit”(总体垂直布局)

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QFileDialog>
 4 #include<QMessageBox>
 5 #include<QFile>
 6 #include<QTextCodec>
 7 
 8 Widget::Widget(QWidget *parent) :
 9     QWidget(parent),
10     ui(new Ui::Widget)
11 {
12     ui->setupUi(this);
13 
14     //点击按钮,选取文件
15     connect(ui->pushButton,&QPushButton::clicked,[=](){
16 
17         QString path = QFileDialog::getOpenFileName(this,"打开文件","D:/WorkSpace/QT/day01/05_QFile");
18         if(path.isEmpty())
19         {
20             QMessageBox::warning(this,"警告", "打开失败");
21         }
22         else
23         {
24             //将路径放入到lineEdit
25             ui->lineEdit->setText(path);
26             //读取文件
27             //QFile默认支持UTF-8格式
28 
29 
30             //QTextCodec* codec = QTextCodec::codecForName("gbk");
31 
32             QFile file(path);//参数路径名称
33             //指定打开方式(只读)
34             //file.open(QIODevice::ReadOnly);//下边的也行
35             file.open(QFileDevice::ReadOnly);
36 
37             QByteArray array;
38             array = file.readAll();
39 
40 //            while(!file.atEnd())
41 //            {
42 //                array += file.readLine();
43 //            }
44 
45 
46             //设置到文本编辑框中
47             ui->textEdit->setText(array);
48             file.close();
49 
50 
51             //读gbk
52             //ui->textEdit->setText(codec->toUnicode(array));
53 
54 
55             //写文件
56             //从新指定打开方式
57             file.open(QFileDevice::Append);
58             file.write("哦哦哦哦哦");
59             file.close();
60 
61         }
62 
63 
64     });
65 
66 }
67 
68 Widget::~Widget()
69 {
70     delete ui;
71 }

 

二、文件信息

1)QFileInfo info

2)info读取到文件信息

3)路径、名称、后缀名、大小

4)建立日期、修改日期 QDateTime

在“widget.cpp”中更改

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include<QFileDialog>
 4 #include<QMessageBox>
 5 #include<QFile>
 6 #include<QTextCodec>
 7 #include<QFileInfo>
 8 #include<QDebug>
 9 #include<QDateTime>
10 
11 Widget::Widget(QWidget *parent) :
12     QWidget(parent),
13     ui(new Ui::Widget)
14 {
15     ui->setupUi(this);
16 
17     //点击按钮,选取文件
18     connect(ui->pushButton,&QPushButton::clicked,[=](){
19 
20         QString path = QFileDialog::getOpenFileName(this,"打开文件","D:/WorkSpace/QT/day01/05_QFile");
21         if(path.isEmpty())
22         {
23             QMessageBox::warning(this,"警告", "打开失败");
24         }
25         else
26         {
27             //将路径放入到lineEdit
28             ui->lineEdit->setText(path);
29             //读取文件
30             //QFile默认支持UTF-8格式
31 
32 
33             //QTextCodec* codec = QTextCodec::codecForName("gbk");
34 
35             QFile file(path);//参数路径名称
36             //指定打开方式(只读)
37             //file.open(QIODevice::ReadOnly);
38             file.open(QFileDevice::ReadOnly);
39 
40             QByteArray array;
41             array = file.readAll();
42 
43 //            while(!file.atEnd())
44 //            {
45 //                array += file.readLine();
46 //            }
47 
48 
49             //设置到文本编辑框中
50             ui->textEdit->setText(array);
51             file.close();
52 
53 
54             //读gbk
55             //ui->textEdit->setText(codec->toUnicode(array));
56 
57 
58             //写文件
59             //从新指定打开方式
60 //            file.open(QFileDevice::Append);
61 //            file.write("哦哦哦哦哦");
62 //            file.close();
63 
64             //经过QFileInfo读取文件信息
65             QFileInfo info(path);
66             qDebug() << "路径:" << info.filePath().toUtf8().data()
67                      << "名称:" << info.fileName().toUtf8().data()
68                      << "文件大小:" << info.size()
69                      << "后缀名:" << info.suffix();
70 
71             qDebug() << "建立日期:" << info.created().toString("yyyy-MM-dd hh:mm:ss");
72             qDebug() << "修改日期:" << info.lastModified().toString("yyyy/MM/dd hh:mm:ss");
73 
74 
75         }
76 
77 
78     });
79 
80 }
81 
82 Widget::~Widget()
83 {
84     delete ui;
85 }

 

三、文本流和数据流

(1)文本流

1)QFile file(path)

2)QTextStream(&file)

3)stream << 写

4)stream.readAll;左移遇到空格结束

(2) 数据流

1)QDataStream stream(&file)

2)stream << 写数据

3)stream >> 读数据;数据块读取

在“widget.cpp”中更改

  1 #include "widget.h"
  2 #include "ui_widget.h"
  3 #include<QFileDialog>
  4 #include<QMessageBox>
  5 #include<QFile>
  6 #include<QTextCodec>
  7 #include<QFileInfo>
  8 #include<QDebug>
  9 #include<QDateTime>
 10 #
 11 
 12 Widget::Widget(QWidget *parent) :
 13     QWidget(parent),
 14     ui(new Ui::Widget)
 15 {
 16     ui->setupUi(this);
 17 
 18     //点击按钮,选取文件
 19     connect(ui->pushButton,&QPushButton::clicked,[=](){
 20 
 21         QString path = QFileDialog::getOpenFileName(this,"打开文件","D:/WorkSpace/QT/day01/05_QFile");
 22         if(path.isEmpty())
 23         {
 24             QMessageBox::warning(this,"警告", "打开失败");
 25         }
 26         else
 27         {
 28             //将路径放入到lineEdit
 29             ui->lineEdit->setText(path);
 30             //读取文件
 31             //QFile默认支持UTF-8格式
 32 
 33 
 34             //QTextCodec* codec = QTextCodec::codecForName("gbk");
 35 
 36             QFile file(path);//参数路径名称
 37             //指定打开方式(只读)
 38             //file.open(QIODevice::ReadOnly);
 39             file.open(QFileDevice::ReadOnly);
 40 
 41             QByteArray array;
 42             array = file.readAll();
 43 
 44 //            while(!file.atEnd())
 45 //            {
 46 //                array += file.readLine();
 47 //            }
 48 
 49 
 50             //设置到文本编辑框中
 51             ui->textEdit->setText(array);
 52             file.close();
 53 
 54 
 55             //读gbk
 56             //ui->textEdit->setText(codec->toUnicode(array));
 57 
 58 
 59             //写文件
 60             //从新指定打开方式
 61 //            file.open(QFileDevice::Append);
 62 //            file.write("哦哦哦哦哦");
 63 //            file.close();
 64 
 65             //经过QFileInfo读取文件信息
 66             QFileInfo info(path);
 67             qDebug() << "路径:" << info.filePath().toUtf8().data()
 68                      << "名称:" << info.fileName().toUtf8().data()
 69                      << "文件大小:" << info.size()
 70                      << "后缀名:" << info.suffix();
 71 
 72             qDebug() << "建立日期:" << info.created().toString("yyyy-MM-dd hh:mm:ss");
 73             qDebug() << "修改日期:" << info.lastModified().toString("yyyy/MM/dd hh:mm:ss");
 74 
 75 
 76         }
 77 
 78 
 79     });
 80 
 81     //文件流读写文件
 82 
 83     //分类:文本流(基础数据类型)和数据流(大型QImage)
 84 
 85     //文本流
 86 //    QFile file("aaa.txt");
 87 //    file.open(QFileDevice::WriteOnly);
 88 //    QTextStream stream(&file);
 89 //    stream << QString("hello world") << 123456;
 90 //    file.close();
 91 
 92 //    //读取
 93 //    file.open(QFileDevice::ReadOnly);
 94 //    QString str;
 95 //    //stream >> str;//读取空格 结束
 96 //    str = stream.readAll();//推荐这种
 97 
 98 //    qDebug() << str;
 99 
100     //数据流 二进制
101     QFile file("bbb.txt");
102     file.open(QFileDevice::WriteOnly);
103     QDataStream stream(&file);
104     stream << QString("hello world") << 123456;
105 
106     file.close();
107 
108     //读数据
109     file.open(QFileDevice::ReadOnly);
110     QString str;
111     int num;
112     stream >> str >> num;//数据块
113 
114     qDebug() << str << num;
115 
116 }
117 
118 Widget::~Widget()
119 {
120     delete ui;
121 }

 

5、总结

1    QLabel
1.1    显示图片
1.1.1    setPixmap(QPixmap(“:/…”))
1.2    显示gif
1.2.1    setMovie()
1.2.2    new movie
1.2.3    movie->start();
2    Combox
2.1    setCurrentIndex(索引)
2.2    setCurrentText(“拖拉机”)
3    自定义控件
3.1    smallWidget 设计师界面类
3.2    提高完了 使用
3.3    信号和槽
3.3.1    valueChanged
3.3.2    setValue
4    事件
4.1    鼠标进入  参数要加入
4.2    鼠标离开
4.3    鼠标按下
4.3.1    位置信息  ev->x()  ev->y()
4.3.2    判断按键  ev->button()  Qt::LeftButton
4.4    鼠标释放
4.5    鼠标移动
4.5.1    判断按键 ev->buttons() & Qt::LeftBtton
5    定时器
5.1    timerEvent
5.2    启动 startTimer
5.3    timerId
5.4    第二种 QTimer
5.5    启动 start
5.6    timeout 信号
5.7    stop 暂停
6    event
6.1    做用  事件的分发
6.2    返回值 bool
6.2.1    做用 true 用户本身处理 ,不向下分发
7    事件过滤器  上层拦截
7.1    安装事件过滤器
7.2    重写eventfilter
8    QPainter    
8.1    QPainter painter(绘图设备 this)
8.2    painter.draw…
8.3    QPen pen(Qt::red); painter.setPen(pen); 画笔
8.4    QBrush brush   painter.setBrush()画刷
8.5    高级绘图
8.5.1    抗锯齿
8.5.2    painter.setRenderHint(QPainter::Antialiasing);
8.5.3    移动画家
8.5.4    painter.translate(QPoint(100,0))
8.5.5    保存画家状态
8.5.6    painter.save
8.5.7    取出状态
8.5.8    painter.restore
8.6    画图片
8.6.1    drawPixmap( QPixmap( “ …png ”) );
8.7    手动调用paintEvent
8.7.1    update()
9    绘图设备
9.1    QPixmap pix(300,300)
9.2    利用画家画图
9.3    保存 save
9.4    fill 填充颜色
9.5    QImage img(300,300, …RGB32)
9.6    画图
9.7    保存 save
9.8    对像素进行访问
9.8.1    setPixel
9.9    QBitmap
9.9.1    色深 1 黑白色
9.10    Qpicture
9.10.1    绘图指令
9.10.2    save 格式没有限定
9.10.3    画图  进行加载 load
9.10.4    painter.drawPicture(0,0,pic)
10    QFile
10.1    读 readAll 读取全部内容
10.2    write 写
10.3    默认编码  utf8
11    QFileInfo
11.1    文件信息
11.2    // 大小   后缀名 文件名 文件路径
11.3    qDebug() << info.size() <<info.suffix()<<info.fileName() << info.filePath();
11.4    QDateTime  toString
12    文件流
12.1    文本流
12.1.1    写 file.open(QIODevice::WriteOnly | QIODevice::Text)
12.1.2     readAll
12.2    数据流
12.2.1    dataStrema << QString("hello world")<<123456 数据块写入
12.2.2    dataStrema >> str >> num 读时候也按照数据类型读取

 

在学习QT总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。