QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
一、编码问题
在计算机编程中,流(Stream)是一种抽象的概念,用于表示数据的输入或输出。根据处理数据的不同方式,流可以分为字节流(Byte Stream)和字符流(Character Stream)两大类。
1. 字节流(Byte Stream)
字节流是处理数据的基本单位是字节(8位二进制数据)的流。它不考虑数据的具体内容,只是简单地将数据视为字节序列进行读取或写入。字节流主要用于处理二进制数据,例如图片、视频、音频文件等,或者当你不确定数据的内容时(比如,当你正在读取一个可能是文本也可能是其他格式的文件时)。
Qt通过QByteArray为我们提供了一个字节数组容器(它是可变长的)。主要用来存储原始的字节流。
QByteArray仍可以表示字符串,类似与unsigned char buf[ ],但是QT中多用QString来表示字符串。
QByteArray一般结合其它类使用,比如QIODevice类的QByteArray QIODevice::readAll()
QByteArray(const char *data, int size = -1) //构造
char at(int i) const //返回第i个元素
void clear() //清空
bool contains(const char * str) const //是否包含字符串 ==strstr
bool contains(char ch) const //是否包含字符
char *data() //从QByteArray类型转化为char *//查找从from开始第一次匹配str的位置
int indexOf(const char *str, int from = 0)
QByteArray & append(char ch) //尾部增加
QByteArray & prepend(char ch) //头部增加
int length() const //返回长度
QByteArray &remove(int pos, int len) //删除
2.字符流(Character Stream)
1) 概念
字符流则是处理数据的基本单位是字符。字符流主要用于处理文本数据。QT通过QString类为我们提供了字符串类。
2) QString相关方法
//数字转字符串, QString静态方法
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"
//字符串转为数字
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 转化到 QByteArray
QByteArray toLocal8Bit() const //转成本地编码的字节流
QByteArray toUtf8() const//转成utf8编码的字节流
例:把一个QString转为char *(QString没有直接转换为char *的方法,需要中间经过一层QByteArray的过渡)
QString str1 = "hello";
char *s = str1.toLocal8Bit().data();
总结:字符流一定是字节流, 而字节流不一定是字符流。
问题:有时候数据写入文件,打开文件会出现乱码的情况,这是为什么,如何解决呢?
答:这个是涉及到编码的问题, 如果字节流的编码是UTF8, 而文件中按照GBK编码解析,可能就是乱码。
二、字符集
字符编码的集合
三、字符编码
1. 概念
我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。
因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111 = 十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。
由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
注意:QT界面的编码是UTF8的
2. QString转为字节流相关的方法
QByteArray toLocal8Bit() //把QString按照本地编码转换成QByteArray
QByteArray toUtf8() //把QString按照utf-8编码转换成QByteArrayQString fromLocal8Bit(const QByteArray & str) //将QByteArray按照本地编码转换为QString
QString fromUtf8(const QByteArray & str) //将QByteArray按照utf-8编码转换为QString
四、其他容器
QList
QVector
QMap
... ...
五、定时器
QTime: 时间类
QTimer: 定时器类
QDateTime: 日期时间类
1. 常用方法
//parent可以传界面的指针,但是没有父子窗体关系,作用仅剩内存管理
QTimer(QObject * parent = 0)
void start(int msec) //参数为ms 定时一次,永久生效
void stop() //停止定时器
Signal:
Void timeout();//一次定时
void QTimer::singleShot(int msec, const QObject * receiver, const char * member) [static]receiver:接收者member:执行函数 1s=1000ms 1ms=1000us 1us=1000ns
每次时间到达后会发出 timeout() 信号
2. 编程步骤
QTimer *timer = new QTimer(this); //实例化
connect(timer, SIGNAL(timeout()), this, SLOT(update())); //绑定超时处理函数
timer->start(1000);
...
timer->stop(); //停止定时器
实例需求:做一个时间显示Label,增加“开始”和“结束”按钮,点击开始,lab每1s记录一次时间。(或者通过数码管显示)
QTime:可以获取到系统当前时间
QDateTime:获取系统时间和日期
提示:时间处理用QDateTime
QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");//设置系统时间显示格式
代码:
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; // 不能指定父对象ui->lcdNumber->setDigitCount(8);time->moveToThread(thread); // 移动到thread线程中connect(thread,&QThread::started,time,&MyTime::thread_time);connect(this,&Widget::destroyed,this,&Widget::on_pushButton_2_clicked); // 直接点击 X 也能销毁线程connect(time,&MyTime::my_signal,this,[=](QString datatime){ // 只能在主线程对界面进行操作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();
}
输出:
六、事件
由窗口系统或QT自身以及外部外设产生的动作,称为事件。
比如当按下鼠标或释放鼠标时,会产生鼠标事件,按下键盘时,出现按键事件。
当某个事件发生时,某个控件要做出响应实现具体业务逻辑,这个操作可以在对应的事件处理函数中实现。
捕捉并处理一个事件的步骤
总目标:所有的事件处理都是通过重写某个事件方法来实现的,可按照如下步骤实现
1. 从逻辑角度判断事件类型,比如你要处理鼠标动作,那肯定是鼠标事件
2. 查找QEvent类的帮助文档,找到enum QEvent::Type中对应的事件,比如QEvent::KeyPress
3. 根据帮助文档,找到相应的事件属于的类,比如QKeyEvent
4. 通过帮助文档的详细介绍部分,找到应该重写的方法,比如QWidget::keyPressEvent()
5. 分析是否可以直接重写事件方法(看能不能修改类的源代码),如果不能,自定义一个类,继承于某个控件类,然后在自定义类中重写其事件方法。
6. void QWidget::keyPressEvent(QKeyEvent * event),根据具体的需求,通过参数event所属的类,具体分析需要获取的数据,然后进行业务逻辑处理
7. 不需要的事件,交由父类做默认处理(如调用父类的keyPressEvent()方法
案例需求:
1、完善原登录模块。要求用户输入完后按回车键触发登录事件,ESC键退出登录界面
2、界面中添加一个单行输入框,当输入字符为某些特殊字符时候,提示用户并禁止输入。
提示小技巧: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();
}
输出:
起始页面
输入特殊字符时
七、绘图事件
void QWidget::paintEvent(QPaintEvent *event);
注意:绘图事件不能直接调用, 当窗口发生变化时,QT内部会自动调用绘图事件,或者调用update方法,也会间接调用。
绘图相关的类
//构造方法, 设置绘制设备
QPainter(QPaintDevice *device)
//设置画笔
void setPen(const QPen &pen)
//设置画刷
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相对绘制设备的原点, 一般直接传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)//画笔构造方法
QPen(const QColor &color)
QPen(Qt::PenStyle style)
void setWidth(int width)//设置画刷的宽度//画刷构造方法
QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern)
QBrush(Qt::BrushStyle style)
相关文章:

QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
一、编码问题 在计算机编程中,流(Stream)是一种抽象的概念,用于表示数据的输入或输出。根据处理数据的不同方式,流可以分为字节流(Byte Stream)和字符流(Character Stream࿰…...
学习electron
一、开发环境 1、先行安装 node.js 和 npm 2、检查 Node.js 是否正确安装,请在您的终端输入以下命令:检测安装的版本 node -v npm -v 注意 因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运…...
《C++智能合约与区块链底层交互全解析:构建坚实的去中心化应用桥梁》
在区块链技术的广阔天地里,C智能合约扮演着极为关键的角色,而其与区块链底层的交互则是实现各种去中心化应用功能的核心环节。深入理解并掌握这种交互机制,对于区块链开发者来说至关重要,它犹如一座桥梁,将智能合约的业…...

MySQL:事务
什么是事务 事务就是把SQL语句打包成一个整体,在这组SQL执行的时候,要么同时成功,要么同时失败。 事务的ACID特性 事务的ACID特性指的是 Atomicity (原⼦性), Consistency (⼀致性), Isolation (隔离 性)和 Durabi…...

Linux——进程间通信之管道
进程间通信之管道 文章目录 进程间通信之管道1. 进程间通信1.1 为什么要进行进程间的通信1.2 如何进行进程间的通信1.3 进程间通信的方式 2. 管道2.1 匿名管道2.1.1 系统调用pipe()2.1.2 使用匿名管道进行通信2.1.1 匿名管道四种情况2.1.2 匿名管道的五大特性2.1.3 进程池 2.2 …...

java-排序算法汇总
排序算法: 冒泡排序(Bubble Sort) 选择排序(Selection Sort) 插入排序(Insertion Sort) 快速排序(Quick Sort) 归并排序(Merge Sort) 堆排序&…...

Vscode进行Java开发环境搭建
Vscode进行Java开发环境搭建 搭建Java开发环境(Windows)1.Jdk安装2.VsCode安装3.Java插件4.安装 Spring 插件5.安装 Mybatis 插件5.安装Maven环境6.Jrebel插件7.IntelliJ IDEA Keybindings8. 收尾 VS Code(Visual Studio Code)是由微软开发的一款免费、开…...

算法学习笔记(五):二叉树一遍历、DFS
一.遍历二叉树 二叉树TreeNode类 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, Tree…...
#Verilog HDL# Verilog中的generate用法集锦
生成块允许复制模块实例或有条件地实例化任何模块。它提供了基于Verilog参数构建设计的能力。当相同的操作或模块实例需要重复多次,或者当某些代码需要根据给定的Verilog参数有条件地包含时,这些语句特别方便。 生成块不能包含端口、参数、specparam声明或指定块。但是,允许…...

简述C++map容器
pair键值对 std::pair在很多关联容器(如std::map、std::multimap、std::set、std:multiset等)中被广泛应用。以std::map为例,std::map是一个键值对的容器,其中每个元素都是一个std::pair,键用于唯一标识元…...
Vue 学习随笔系列十七 -- 表格样式修改
表格样式修改 文章目录 表格样式修改一、表格背景颜色修改1、方法一2、方法二 二、多级表头颜色修改 一、表格背景颜色修改 1、方法一 表格外套一个 div ,修改div的背景色,并将表格背景色设置为透明 参考代码: <template><div cl…...

08 —— Webpack打包图片
【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件:发送一个单独的文件并导出URL地址 小于8KB的文件:导出一…...

01.Django快速入门
一、Django 快速入门 使用最新版本 Django4.2LTS 版本,3 年内不需要更换版本由浅入深讲解,浅显易懂课程大纲全面包含 Django 框架知识点,内容丰富全面细致知识点结合项目实战实现全栈项目应用 Django 官网(文档): https://docs.djangoproject.com/zh-h…...

【大数据学习 | Spark-Core】spark-shell开发
spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码,会在driver端进行解析,然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...
Modern Effective C++ Item 14 如果函数不抛出异常请使用noexcept
C11 noexcept关键字用于指定函数不会抛出异常,有助于提高程序的异常安全性,还能够使编译器生成更加高效的代码。 noexcept 是函数接口的一部分 函数是否声明为 noexcept 是接口设计的一部分,客户端代码可能会依赖这一点。如果一个函数被声明…...
cudatoolkit安装(nvcc -V错误版本解决)
CudaToolKit安装(nvcc) cudatoolkit 是 CUDA 开发工具包(CUDA Toolkit) 的核心部分,包含了一系列用于开发和运行 CUDA 应用程序的软件组件。nvcc 是 NVIDIA CUDA 编译器驱动,用于将 CUDA C/C 代码编译成可…...
DTO和VO的区别及使用场景详解
随着互联网的发展,前后端分离的开发模式越来越流行。在前后端数据交互过程中,为了保证数据的安全性和效率,通常会采用 DTO 和 VO 来封装数据。本篇博客将详细介绍 DTO 和 VO 的区别以及使用场景。 大家可能会有个疑问,既然DTO是展…...

百度在下一盘大棋
这两天世界互联网大会在乌镇又召开了。 我看到一条新闻,今年世界互联网大会乌镇峰会发布“2024 年度中国互联网企业创新发展十大典型案例”,百度文心智能体平台入选。 这个智能体平台我最近也有所关注,接下来我就来讲讲它。 百度在下一盘大棋…...
第十六届蓝桥杯模拟赛第二期题解—Java
第十六届蓝桥杯模拟赛/校赛第二期个人题解,有错误的地方欢迎各位大佬指正 问题一(填空题) 【问题描述】 如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。 请问, 2024 的最大的质因数是多少? …...
驱动开发笔记:关于3588GPIO
1.概要 2.内容 1.3588GPIO 关于RK3588的GPIO(General-Purpose Input/Output,通用输入输出引脚),以下是一些关键信息和操作指南: 一、GPIO基本概念 定义:GPIO是嵌入式系统中常见的通信接口,…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...