英文版網(wǎng)站建設(shè)方案廈門seo公司
一、編碼問題
????????在計(jì)算機(jī)編程中,流(Stream)是一種抽象的概念,用于表示數(shù)據(jù)的輸入或輸出。根據(jù)處理數(shù)據(jù)的不同方式,流可以分為字節(jié)流(Byte Stream)和字符流(Character Stream)兩大類。
1. 字節(jié)流(Byte Stream)
????????字節(jié)流是處理數(shù)據(jù)的基本單位是字節(jié)(8位二進(jìn)制數(shù)據(jù))的流。它不考慮數(shù)據(jù)的具體內(nèi)容,只是簡(jiǎn)單地將數(shù)據(jù)視為字節(jié)序列進(jìn)行讀取或?qū)懭?。字?jié)流主要用于處理二進(jìn)制數(shù)據(jù),例如圖片、視頻、音頻文件等,或者當(dāng)你不確定數(shù)據(jù)的內(nèi)容時(shí)(比如,當(dāng)你正在讀取一個(gè)可能是文本也可能是其他格式的文件時(shí))。
????????Qt通過QByteArray為我們提供了一個(gè)字節(jié)數(shù)組容器(它是可變長(zhǎng)的)。主要用來存儲(chǔ)原始的字節(jié)流。
QByteArray仍可以表示字符串,類似與unsigned char buf[ ],但是QT中多用QString來表示字符串。
QByteArray一般結(jié)合其它類使用,比如QIODevice類的QByteArray QIODevice::readAll()
QByteArray(const char *data, int size = -1)? //構(gòu)造
char?? at(int i) const //返回第i個(gè)元素
void?? clear()? //清空
bool?? contains(const char * str) const? //是否包含字符串 ?==strstr
bool?? contains(char ch) const //是否包含字符
char ? *data()? //從QByteArray類型轉(zhuǎn)化為char *//查找從from開始第一次匹配str的位置
int indexOf(const char *str, int from = 0)
QByteArray & append(char ch)? //尾部增加
QByteArray & prepend(char ch) //頭部增加
int length() const //返回長(zhǎng)度
QByteArray &remove(int pos, int len)? //刪除
2.字符流(Character Stream)
1) 概念
????????字符流則是處理數(shù)據(jù)的基本單位是字符。字符流主要用于處理文本數(shù)據(jù)。QT通過QString類為我們提供了字符串類。
2) QString相關(guān)方法
//數(shù)字轉(zhuǎn)字符串, QString靜態(tài)方法
QString?? number(long n, int base = 10) [static]
QString?? number(double n, char format = 'g', int precision = 6) [static]
例:
long a = 63;
QString s = QString::number(a, 10);???????????? // s == "63"
QString t = QString::number(a, 16).toUpper();???? // t == "3F"
//字符串轉(zhuǎn)為數(shù)字
short toShort(bool * ok = 0, int base = 10) const
float toFloat(bool * ok = 0) const
long toLong(bool * ok = 0, int base = 10) const
例:
QString str1 = "1234.56";
str1.toFloat(); // returns 1234.56
//從 QString 轉(zhuǎn)化到 QByteArray
QByteArray toLocal8Bit() const //轉(zhuǎn)成本地編碼的字節(jié)流
QByteArray toUtf8() const//轉(zhuǎn)成utf8編碼的字節(jié)流
例:把一個(gè)QString轉(zhuǎn)為char *(QString沒有直接轉(zhuǎn)換為char *的方法,需要中間經(jīng)過一層QByteArray的過渡)
QString str1 = "hello";
char *s = str1.toLocal8Bit().data();
總結(jié):字符流一定是字節(jié)流, 而字節(jié)流不一定是字符流。
問題:有時(shí)候數(shù)據(jù)寫入文件,打開文件會(huì)出現(xiàn)亂碼的情況,這是為什么,如何解決呢?
答:這個(gè)是涉及到編碼的問題, 如果字節(jié)流的編碼是UTF8, 而文件中按照GBK編碼解析,可能就是亂碼。
二、字符集
字符編碼的集合
三、字符編碼
1. 概念
????????我們已經(jīng)講過了,字符串也是一種數(shù)據(jù)類型,但是,字符串比較特殊的是還有一個(gè)編碼問題。
????????因?yàn)橛?jì)算機(jī)只能處理數(shù)字,如果要處理文本,就必須先把文本轉(zhuǎn)換為數(shù)字才能處理。最早的計(jì)算機(jī)在設(shè)計(jì)時(shí)采用8個(gè)比特(bit)作為一個(gè)字節(jié)(byte),所以,一個(gè)字節(jié)能表示的最大的整數(shù)就是255(二進(jìn)制11111111?= 十進(jìn)制255),如果要表示更大的整數(shù),就必須用更多的字節(jié)。比如兩個(gè)字節(jié)可以表示的最大整數(shù)是65535,4個(gè)字節(jié)可以表示的最大整數(shù)是4294967295。
????????由于計(jì)算機(jī)是美國(guó)人發(fā)明的,因此,最早只有127個(gè)字符被編碼到計(jì)算機(jī)里,也就是大小寫英文字母、數(shù)字和一些符號(hào),這個(gè)編碼表被稱為ASCII編碼,比如大寫字母A的編碼是65,小寫字母z的編碼是122。
????????但是要處理中文顯然一個(gè)字節(jié)是不夠的,至少需要兩個(gè)字節(jié),而且還不能和ASCII編碼沖突,所以,中國(guó)制定了GB2312編碼,用來把中文編進(jìn)去。
????????你可以想得到的是,全世界有上百種語言,日本把日文編到Shift_JIS里,韓國(guó)把韓文編到Euc-kr里,各國(guó)有各國(guó)的標(biāo)準(zhǔn),就會(huì)不可避免地出現(xiàn)沖突,結(jié)果就是,在多語言混合的文本中,顯示出來會(huì)有亂碼。
????????因此,Unicode應(yīng)運(yùn)而生。Unicode把所有語言都統(tǒng)一到一套編碼里,這樣就不會(huì)再有亂碼問題了。本著節(jié)約的精神,又出現(xiàn)了把Unicode編碼轉(zhuǎn)化為“可變長(zhǎng)編碼”的UTF-8編碼。UTF-8編碼把一個(gè)Unicode字符根據(jù)不同的數(shù)字大小編碼成1-6個(gè)字節(jié),常用的英文字母被編碼成1個(gè)字節(jié),漢字通常是3個(gè)字節(jié),只有很生僻的字符才會(huì)被編碼成4-6個(gè)字節(jié)。如果你要傳輸?shù)奈谋景罅坑⑽淖址?#xff0c;用UTF-8編碼就能節(jié)省空間。
注意:QT界面的編碼是UTF8的
2. QString轉(zhuǎn)為字節(jié)流相關(guān)的方法
QByteArray?? toLocal8Bit() //把QString按照本地編碼轉(zhuǎn)換成QByteArray
QByteArray?? toUtf8() //把QString按照utf-8編碼轉(zhuǎn)換成QByteArrayQString?? fromLocal8Bit(const QByteArray & str)? //將QByteArray按照本地編碼轉(zhuǎn)換為QString
QString??? fromUtf8(const QByteArray & str) //將QByteArray按照utf-8編碼轉(zhuǎn)換為QString
四、其他容器
QList
QVector
QMap
... ...
五、定時(shí)器
QTime: 時(shí)間類
QTimer: 定時(shí)器類
QDateTime: 日期時(shí)間類
1. 常用方法
//parent可以傳界面的指針,但是沒有父子窗體關(guān)系,作用僅剩內(nèi)存管理
QTimer(QObject * parent = 0)?
void?? start(int msec)? //參數(shù)為ms? 定時(shí)一次,永久生效
void?? stop()? //停止定時(shí)器
Signal:
Void? timeout();//一次定時(shí)
void QTimer::singleShot(int msec, const QObject * receiver, const char * member) [static]receiver:接收者member:執(zhí)行函數(shù)?????1s=1000ms 1ms=1000us? 1us=1000ns
每次時(shí)間到達(dá)后會(huì)發(fā)出 timeout() 信號(hào)
2. 編程步驟
QTimer *timer = new QTimer(this);? //實(shí)例化
connect(timer, SIGNAL(timeout()), this, SLOT(update()));? //綁定超時(shí)處理函數(shù)
timer->start(1000);
...
timer->stop();? //停止定時(shí)器
實(shí)例需求:做一個(gè)時(shí)間顯示Label,增加“開始”和“結(jié)束”按鈕,點(diǎn)擊開始,lab每1s記錄一次時(shí)間。(或者通過數(shù)碼管顯示)
QTime:可以獲取到系統(tǒng)當(dāng)前時(shí)間
QDateTime:獲取系統(tǒng)時(shí)間和日期
提示:時(shí)間處理用QDateTime
QDateTime time = QDateTime::currentDateTime();//獲取系統(tǒng)現(xiàn)在的時(shí)間
QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");//設(shè)置系統(tǒng)時(shí)間顯示格式??
代碼:
mytime.h
#ifndef MYTIME_H
#define MYTIME_H#include <QObject>
#include <QDebug>
#include <QThread>
#include <QDateTime>
class MyTime : public QObject
{Q_OBJECT
public:explicit MyTime(QObject *parent = nullptr);void thread_time();void set_flag(int flag);
signals:void my_signal(QString datatime);
public slots:private:int flag = 1;
};#endif // MYTIME_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QDebug>
#include <QThread>
#include "mytime.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::Widget *ui;QThread *thread;MyTime *time;
};#endif // WIDGET_H
mytime.cpp
#include "mytime.h"MyTime::MyTime(QObject *parent) : QObject(parent)
{}void MyTime::thread_time()
{while(flag){QDateTime currentTime = QDateTime::currentDateTime();QString formattedTime = currentTime.toString("hh:mm:ss");qDebug() << formattedTime;emit my_signal(formattedTime);QThread::sleep(1);}
}void MyTime::set_flag(int flag)
{this->flag = flag;
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);thread = new QThread(this);time = new MyTime; // 不能指定父對(duì)象ui->lcdNumber->setDigitCount(8);time->moveToThread(thread); // 移動(dòng)到thread線程中connect(thread,&QThread::started,time,&MyTime::thread_time);connect(this,&Widget::destroyed,this,&Widget::on_pushButton_2_clicked); // 直接點(diǎn)擊 X 也能銷毀線程connect(time,&MyTime::my_signal,this,[=](QString datatime){ // 只能在主線程對(duì)界面進(jìn)行操作this->ui->lcdNumber->display(datatime);});
}
Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{thread->start();
}void Widget::on_pushButton_2_clicked()
{thread->quit();time->set_flag(0);thread->wait();
}
輸出:
六、事件
????????由窗口系統(tǒng)或QT自身以及外部外設(shè)產(chǎn)生的動(dòng)作,稱為事件。
????????比如當(dāng)按下鼠標(biāo)或釋放鼠標(biāo)時(shí),會(huì)產(chǎn)生鼠標(biāo)事件,按下鍵盤時(shí),出現(xiàn)按鍵事件。
????????當(dāng)某個(gè)事件發(fā)生時(shí),某個(gè)控件要做出響應(yīng)實(shí)現(xiàn)具體業(yè)務(wù)邏輯,這個(gè)操作可以在對(duì)應(yīng)的事件處理函數(shù)中實(shí)現(xiàn)。
捕捉并處理一個(gè)事件的步驟
總目標(biāo):所有的事件處理都是通過重寫某個(gè)事件方法來實(shí)現(xiàn)的,可按照如下步驟實(shí)現(xiàn)
1. 從邏輯角度判斷事件類型,比如你要處理鼠標(biāo)動(dòng)作,那肯定是鼠標(biāo)事件
2. 查找QEvent類的幫助文檔,找到enum QEvent::Type中對(duì)應(yīng)的事件,比如QEvent::KeyPress
3. 根據(jù)幫助文檔,找到相應(yīng)的事件屬于的類,比如QKeyEvent
4. 通過幫助文檔的詳細(xì)介紹部分,找到應(yīng)該重寫的方法,比如QWidget::keyPressEvent()
5. 分析是否可以直接重寫事件方法(看能不能修改類的源代碼),如果不能,自定義一個(gè)類,繼承于某個(gè)控件類,然后在自定義類中重寫其事件方法。
6. void QWidget::?keyPressEvent(QKeyEvent * event),根據(jù)具體的需求,通過參數(shù)event所屬的類,具體分析需要獲取的數(shù)據(jù),然后進(jìn)行業(yè)務(wù)邏輯處理
7. 不需要的事件,交由父類做默認(rèn)處理(如調(diào)用父類的keyPressEvent()方法
案例需求:
1、完善原登錄模塊。要求用戶輸入完后按回車鍵觸發(fā)登錄事件,ESC鍵退出登錄界面
2、界面中添加一個(gè)單行輸入框,當(dāng)輸入字符為某些特殊字符時(shí)候,提示用戶并禁止輸入。
提示小技巧:QToolTip::showText(this->mapToGlobal(this->pos()), "不能使用特殊字符", this);
代碼:
myline.h
#ifndef MYLINE_H
#define MYLINE_H#include <QWidget>
#include <QtWidgets>class myline : public QLineEdit
{Q_OBJECT
public:explicit myline(QWidget *parent = nullptr);void keyPressEvent(QKeyEvent *event);
signals:public slots:
};#endif // MYLINE_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QtWidgets>
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();private slots:void on_exit_button_clicked();private:Ui::Widget *ui;void keyPressEvent(QKeyEvent *event);
};#endif // WIDGET_H
myline.cpp
#include "myline.h"myline::myline(QWidget *parent) : QLineEdit (parent)
{}void myline::keyPressEvent(QKeyEvent *event)
{qDebug("mylineedit: %x",event->key());if(event->key() == Qt::Key_Slash)QToolTip::showText(this->mapToGlobal(this->pos()), "不能使用特殊字符", this);else{QLineEdit::keyPressEvent(event);}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "myline.h"
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::keyPressEvent(QKeyEvent *event)
{qDebug("%x",event->key());if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter){ // <CR>QString name = ui->name_edit->text();QString passwd = ui->passwd_edit->text();if(name == "wanghan" && passwd == "123456"){qDebug()<<"ok"<<endl;}}if(event->key() == Qt::Key_Escape){ // escthis->close();}
}void Widget::on_exit_button_clicked()
{this->close();
}
輸出:
起始頁(yè)面
輸入特殊字符時(shí)
七、繪圖事件
void QWidget::paintEvent(QPaintEvent *event);
注意:繪圖事件不能直接調(diào)用, 當(dāng)窗口發(fā)生變化時(shí),QT內(nèi)部會(huì)自動(dòng)調(diào)用繪圖事件,或者調(diào)用update方法,也會(huì)間接調(diào)用。
繪圖相關(guān)的類
//構(gòu)造方法, 設(shè)置繪制設(shè)備
QPainter(QPaintDevice *device)
//設(shè)置畫筆
void setPen(const QPen &pen)
//設(shè)置畫刷
void setBrush(const QBrush &brush)
//繪制直線
void drawLine(int x1, int y1, int x2, int y2)
//繪制矩形
void drawRect(const QRectF &rectangle)
void drawRect(int x, int y, int width, int height)
//繪制圖片 x,y相對(duì)繪制設(shè)備的原點(diǎn), 一般直接傳0, 0
void drawPixmap(int x, int y, const QPixmap &pixmap)
void drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
void drawPixmap(int x, int y, int width, int height, const QPixmap &pixmap)
//繪制圓形 或者橢圓
void drawEllipse(int x, int y, int width, int height)
//繪制文本
void drawText(int x, int y, const QString &text)//畫筆構(gòu)造方法
QPen(const QColor &color)
QPen(Qt::PenStyle style)
void setWidth(int width)//設(shè)置畫刷的寬度//畫刷構(gòu)造方法
QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern)
QBrush(Qt::BrushStyle style)