Qt基础学习笔记

2023-05-16

Qt中的常用快捷键

注释:ctrl + /
运行:ctrl + r
编译:ctrl + b
帮助文档:F1
自动对齐:ctrl + i
同名之间.h文件与.cpp文件的切换:F4

QPushButton按钮

需要引入<QPushButton>头文件,QPushButton继承于QWidget类

创建一个按钮

// 默认构造
QPushButton * btn = new QPushButton();

// 构造创建按钮 弊端:默认以控件的大小创建窗口
QPushButton* btn2 = new QPushButton("第二个按钮", this); // 通过构造指定父类和文本

显示按钮

btn->show(); // 默认顶层方式弹出,独立的窗口

要想按钮显示在指定窗口中,需要指定父类

btn->setParent(this); // 将按钮的父类设置为myWidget,使其显示在myWidget窗口中
btn->setText("第一个按钮"); // 按钮的文本

设置按钮位置
坐标是以左上角为(0,0)

// 移动按钮至指定坐标处
btn2->move(100, 100);

窗口和按钮大小

// 重置窗口大小
resize(600, 400);

// 按钮重置大小
btn2->resize(50,50);

// 设置固定的窗口大小
setFixedSize(600, 400); // 不能通过鼠标拖拽来改变窗口的大小

设置窗口标题

// 设置窗口标题
setWindowTitle("第一个窗口");

对象树

1、当创建的对象在堆区时,如果指定的对象是QObject或者其子类派生下来的类,可以不用管理释放的操作,将对象放入到对象树中。
2、对象树的构造是现有父类再有子类的,析构顺序是先析构子类再析构父类。
3、当析构函数中有输出语句时,先打印父类的析构语句,但这并不意味着析构顺序。西沟的顺序依然是先子类后父类。
4、对象树一定程度上简化了内存回收机制。

信号和槽

信号槽的优点:松散耦合。
什么是松散耦合:信号的发送端 和 接收端本身是没有关联的,通过connect连接将两端耦合在一起。
connect(发送者, 发送的信号, 接收者, 信号的处理(槽));

  1. 参数1:信号的发送者
  2. 参数2:发送的信号(存放函数的地址)(clicked点击,pressed按下,released弹起,toggled切换)
  3. 参数3:信号的接收者
  4. 参数4:处理的槽函数(函数地址)
connect(myBtn, &PushButton::clicked, this, &Widget::close);

// 断开信号, 传参与connect一致
disconnect(btn, &QPushButton::clicked, this, &Widget::classIsOver);

// Qt4版本信号槽的连接
connect(zt, SIGNAL(hungry()), st, SLOT(treat()));

Qt4版本的优点,直观。缺点,类型不做检测

自定义信号
自定义信号使用signals关键字修饰
规定:
1、没有返回值;
2、只需要声明不需要实现;
3、可以有参数;
4、可以重载;

signals:
    // 自定义信号写在这里
    void hungry();
    void hungry(QString foodName); // 信号的重载

自定义槽函数
规定:
1、无返回值;
2、需要声明也需要实现;
3、可以有参数;
4、可以发生重载;

public slots:
    // 槽函数写在这里,早期版本必须写在这里,Qt5之后可以不使用slots关键字
    void treat();
    void treat(QString foodName); 

重载后的槽函数连接时需要指明函数类型

// 创建一个老师对象
this->zt = new Teacher(this);

// 创建一个学生对象
this->st = new Student(this);

// 有参信号的连接
void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
void (Student:: *studentSlots)(QString) = &Student::treat;
connect(zt, teacherSignal, st, studentSlots);

// 无参信号的连接
void (Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
void (Student:: *studentSlots2)(void) = &Student::treat;
connect(zt, teacherSignal2, st, studentSlots2);

槽函数必须有对应的实现。
使用时用connect将信号与槽函数连接在一起即可。

信号的发送
使用emit

emit zt->hungry(); // 使用emit发送信号
emit zt->hungry("有参的信号");

信号和槽的连接
1、信号连接多个槽函数
2、多个信号连接同一个槽函数
3、信号连接信号
注意: 信号的参数可以多于槽,但是必须一一对应

Lambda表达式

    // []标识一个Lambda的开始不能省略
    [=](){ // 值传递
        btn->setText("下课111");
    }();
    [&](){ // 引用传递
        btn2->setText("下课222");
    }();
    [btn](){ // 锁定值传递,只有btn生效
        btn->setText("下课222");
        //btn2->setText("下课222"); // 看不到,报错
    }();
    [=]()mutable{ // 加上mutable关键字,可以修改值传递的拷贝,注意只能修改拷贝,而不是传入值的本身
        btn->setText("下课111");
    }();
    int ret = []()->int{return 1000;}(); // ->代表Lambda的返回值类型
    qDebug() << ret << endl;

菜单栏

一个程序中菜单栏 只能最多有一个

	// 菜单栏的创建
	QMenuBar *bar = menuBar();
	// 将菜单栏放入窗口中
	setMenuBar(bar);
	
	// 新增菜单
    QMenu * fileMenu = bar->addMenu("文件");
    QMenu * editMenu = bar->addMenu("编辑");

    // 创建菜单项
    QAction* newAction = fileMenu->addAction("新建");
    fileMenu->addSeparator(); // 添加分割线
    QAction* openAction = fileMenu->addAction("打开");

工具栏

工具栏可以有多个

    QToolBar* toolBar = new QToolBar(this);
    //addToolBar(toolBar); // 将工具栏加载到窗口中,默认位置在上面,可以拖拽
    addToolBar(Qt::LeftToolBarArea, toolBar); // 指定左边

    // 只允许工具栏左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

    // 设置工具栏浮动
    toolBar->setFloatable(false); // 默认值为 true 可以浮动。设置false不允许浮动

    // 设置不可拖拽,默认可拖拽
    toolBar->setMovable(false);

    // 在工具栏中设置选项
    toolBar->addAction(newAction); // 跟上面fileMenu公用一个
    toolBar->addAction(openAction);
    toolBar->addSeparator(); // 添加分割线
    toolBar->addAction("自己"); // 也可以自己设置一个选项

    // 工具栏中添加控件
    QPushButton * btn = new QPushButton("aa", this);
    toolBar->addWidget(btn); // 将按钮放入工具栏中

状态栏

可以有多个

    QStatusBar* stBar = statusBar();
    // 将状态栏设置在窗口中
    setStatusBar(stBar);
    // 往状态栏中放标签控件
    QLabel* label = new QLabel("提示", this);
    stBar->addWidget(label); // 将标签放入状态栏

    QLabel* label2 = new QLabel("右侧提示", this);
    stBar->addPermanentWidget(label2);

铆接部件

    // 铆接部件(浮动窗口)  可以有多个  可拖拽
    QDockWidget* dockWidget = new QDockWidget("浮动",this);
    addDockWidget(Qt::BottomDockWidgetArea, dockWidget); // 围绕核心,根据核心确定位置

    // 设置后期停靠只能上下
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);

核心部件

只能有一个

	// 设置中心部件, 只能有一个
    QTextEdit* edit = new QTextEdit(this);
    setCentralWidget(edit); // 设置中心部件到窗口

各个栏的布局情况
在这里插入图片描述

添加资源文件

第一步:先将资源复制到项目所在文件夹
第二步:在Qt中右键项目—>添加新文件(Add New…),出现如下界面
在这里插入图片描述
第三步:名称自己起,添加成功后Qt列表会多出资源的文件夹
在这里插入图片描述
第四步:右键.qrc资源文件
在这里插入图片描述
第五步:添加前缀可以自定义,先添加前缀再添加文件
在这里插入图片描述
然后保存编译一下,就能看到项目列表中的资源文件了。

资源文件的使用
路径前必须写 ( “:” + “前缀”)

ui->actionnew->setIcon(QIcon(":/img/1.jpg")); // 这样就算代码移到别的电脑也可以使用这个图片

对话框

Qt都提供了哪些标准对话框:

  1. QColorDialog:选择颜色对话框。
  2. QFileDialog:选择文件对话框。
  3. QFontDialog:选择字体对话框。
  4. QInputDialog:允许用户输入一个值,并将其值返回。
  5. QMessageBox:消息(模态)对话框,用于显示信息,或询问等。
  6. QPageSetupDialog:为打印机提供纸张相关选项。
  7. QPrintDialog:打印机配置。
  8. QPrintPreviewDialog:打印预览。
  9. QProgressDialog:显示操作过程。

1、模态对话框:该对话框弹出后必须响应,否则不能点其他的窗口

// 点击按钮,弹出对话框
connect(ui->actionnew, &QAction::triggered, [=](){
	// 模态对话框(不可以对其他窗口进行操作)
	QDialog dlg(this);
	dlg.resize(200, 100); // 对话框太小有警告,系统提示对话框太小可能显示不了有效信息,所以警告
	dlg.exec(); // 阻塞  必须对对话框操作完毕才放开阻塞,向下执行
	qDebug() << "模态对话框操作完毕!";});

2、非模态对话框:该对话框弹出后可以不响应,依然可以点击其他窗口

// 点击按钮弹出对话框
connect(ui->actionnew, &QAction::triggered, [=](){
	// 非模态对话框(可以对其他窗口进行操作)
	QDialog *dlg2 = new QDialog(this); // 交给对象树释放
	dlg2->resize(200, 100);
	dlg2->show(); // 对话框独立展示后,还可以向下执行
	qDebug() << "非模态对话框执行了!" << endl;});

注意:
如果不停的点击按钮触发非模态对话框,就会不停的new空间,
但是对象树是在程序结束时统一释放的,
所以这个对象就有可能导致内存溢出,
解决方法:
设置Attribute属性,在对话框关闭的时候就释放申请的空间

dlg2->setAttribute(Qt::WA_DeleteOnClose);

3、消息对话框

connect(ui->actionww, &QAction::triggered, this, [=]{
	QMessageBox::critical(this, "hello", "错误:");
});

在这里插入图片描述

返回值:选项;参数1:指定父类;参数2:对话框标题;参数3:显示的内容;参数4:选项;参数5:关联回车的选项;
其他都类似,列举一下:

// 信息对话框
QMessageBox::information(this, "information", "信息:");
// 提问对话框
QMessageBox::question(this, "question", "请问:");
// 警告对话框
QMessageBox::warning(this, "warning", "警告:");

提问对话框可以修改选项值,默认为yes|no

// 提问对话框
QMessageBox::question(this, "question", "请问:", 
							QMessageBox::Save|QMessageBox::Cancel);

提问对话框的第五参数表示默认关联回车的选项

// 提问对话框
QMessageBox::question(this, "question", "请问:", 
							QMessageBox::Save|QMessageBox::Cancel,
							QMessageBox::Cancel);

其他对话框

// 颜色选择对话框,返回值是颜色的QColor类型的色域值
QColor color = QColorDialog::getColor(QColor(255,0,0,2)); // 第四参数为透明度
qDebug() << color.red() << color.green() << color.blue() << color.alpha() << endl;

// 文件对话框
QString str = QFileDialog::getOpenFileName(this, "D:/DeskTop", "(*.txt)"); // 第三参数文件过滤
qDebug() << "str: " << str << endl;// 返回值是选中文件的路径

 // 字体对话框
bool flag = true;
QFont font = QFontDialog::getFont(&flag, QFont("华文彩云", 36));
qDebug() << "字体:" << font.family().toUtf8().data() << "字号:" << font.pointSize() 
         << "是否加粗:" << font.bold() << "是否倾斜:" << font.italic() << endl; // 返回值

界面布局

在这里插入图片描述

对齐方式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行结果
在这里插入图片描述

若想将用户名和密码框都对齐,可将这4个组件拖入一个widget中进行栅格布局。

自定义控件

右键项目—>添加新文件(Add New…)—>选Qt—>设计师界面类—>确定。
在这里插入图片描述
在这里插入图片描述
然后给自己的ui界面起一个名字
创建成功后就出现了一个新的ui
在这里插入图片描述

在自己创建的ui文件中自定义拖拽想要封装的控件组合成一个新的控件。
在这里插入图片描述

记下自己创建的是什么控件类型
在这里插入图片描述

然后点击进入程序默认创建的ui文件
在这里插入图片描述

因为我创建的控件类型是widget
在这里插入图片描述

右键widget控件—>提升为
在这里插入图片描述
在这里插入图片描述

成功后可以看到这个控件的类型变成了自定义控件类型
在这里插入图片描述

运行看结果,封装成功
在这里插入图片描述
若想给自定义控件加功能,在自定义的类中写逻辑代码即可。

	// QSpinBox移动 QSlider跟着移动
    void (QSpinBox::* sp)(int) = &QSpinBox::valueChanged;
    connect(ui->spinBox, sp, ui->horizontalSlider, &QSlider::setValue);

    // QSlider滑动 QSpinBox数字跟着变化
    connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);

Qt中的鼠标事件

myLabel::myLabel(QWidget* parent): QLabel(parent)
{
    // 设置鼠标追踪,不需要按下,鼠标移动就能被捕获到
    setMouseTracking(true);
}

void myLabel::enterEvent(QEvent* event){
//    qDebug() << "鼠标进入了" << endl;
}
void myLabel::leaveEvent(QEvent*){
//    qDebug() << "鼠标离开了" << endl;
}

// 鼠标移动
void myLabel::mouseMoveEvent(QMouseEvent *ev){
    QString str; // 移动检测得用buttons()函数,并用&操作
    if(ev->buttons() & Qt::LeftButton) // 右键
    str = QString("鼠标释放了  x = %1  y = %2 "
                          "globalx = %3  global = %4")
            .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug() << "鼠标移动了" << endl;
}
// 鼠标按下
void myLabel::mousePressEvent(QMouseEvent *ev){
    QString str;
    // Qt中的字符串格式化
    // x,y函数是基于控件的,globalx,globaly是基于整个电脑屏幕的
    if(ev->button() == Qt::LeftButton) // 鼠标左键
    str = QString("鼠标按下了  x = %1  y = %2 "
                          "globalx = %3  global = %4")
            .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug() << str << endl;
}
// 鼠标释放
void myLabel::mouseReleaseEvent(QMouseEvent *ev){
    QString str;
    if(ev->button() == Qt::RightButton) // 右键
    str = QString("鼠标释放了  x = %1  y = %2 "
                          "globalx = %3  global = %4")
            .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug() << str << endl;
}

定时器

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 启动定时器
    startTimer(1000);// 参数1:间隔时间 毫秒
}
// 重写定时器事件
void Widget::timerEvent(QTimerEvent *){
    static int num = 1;
    ui->label_2->setText(QString::number(num++));
}

startTimer()函数返回值是定时器的唯一标识,当有多个定时器时可以用来做区分

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 启动定时器
    id1 = startTimer(1000);// 参数1:间隔时间 毫秒
    id2 = startTimer(2000);
	// 定义成员变量来存放定时器的唯一值
}
// 重写定时器事件
void Widget::timerEvent(QTimerEvent * ev){
    if(ev->timerId() == id1){
        static int num = 1;
        ui->label_2->setText(QString::number(num++));
    }
    if(ev->timerId() == id2){
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
}

实际上,当startTimer函数调用后会启动一个全局唯一的定时器,在指定时间间隔后调用定时器事件,事件函数可通过timerId函数来区分是哪个定时器调用的当前事件。
按时间间隔重复调用事件函数。

定时器的另一种实现 (推荐使用)

    // 定时器的第二种实现方式
    QTimer *time = new QTimer(this);
    time->start(500); // 单位毫秒
    connect(time, &QTimer::timeout, this, [=](){
        static int num = 1;
        ui->label_4->setText(QString::number(num++));
    });

event事件分发器

在这里插入图片描述

事件拦截 (不建议实际使用,仅供学习练习)
不让事件分发器继续向下分发

// event分发拦截
bool myLabel::event(QEvent *e){
    // 如果是鼠标按下事件
    if(e->type() == QEvent::MouseButtonPress){
        qDebug() << "鼠标按下事件被拦截了" << endl;
        return true;
    }
    
    // 其他事件交给父类处理
    return QLabel::event(e);
}

事件过滤器

在这里插入图片描述

    // 步骤1:给label安装事件过滤器
    ui->label->installEventFilter(this);
}
// 步骤2:重写事件过滤器事件
bool Widget::eventFilter(QObject* obj, QEvent* e){
    if(obj == ui->label){
        if(e->type() == QEvent::MouseButtonPress){
            qDebug() << "事件过滤:" << endl;
            QMouseEvent* ev = static_cast<QMouseEvent *>(e); // 强制类型转换,静态转换
            QString str = QString("鼠标按下了  x = %1  y = %2 "
                                  "globalx = %3  global = %4")
                    .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
            qDebug() << str << endl;
            return true;
        }
    }

    return QWidget::eventFilter(obj,e);
}

绘图事件

只需重写paintEvent函数,系统会自动调用。

// 绘图事件
void Widget::paintEvent(QPaintEvent*){
    // 实例化画家对象  this指定的是绘图的设备
    QPainter painter(this);

    // 设置画笔的颜色
    QPen pen(QColor(255, 0, 0));
    pen.setWidth(3); // 设置笔的宽度(粗细)
    pen.setStyle(Qt::DotLine); // 设置画笔风格 (DotLine为虚线)

    // 让画家使用这个笔
    painter.setPen(pen);

    // 画刷,封闭图形填充
    QBrush brush(QColor(0,255,0));
    // 设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);

    // 让画家使用刷子
    painter.setBrush(brush);

    // 画线
    painter.drawLine(QPoint(0,0), QPoint(100,100));
    // 画圆
    painter.drawEllipse(QPoint(100,100), 50, 50); // 第二参数和第三参数相当于椭圆中的a和b系数
    // 画矩形
    painter.drawRect(QRect(20,20,60,50)); // 在20,20点画长为60宽为50的矩形
    // 画文字
    painter.drawText(QRect(10, 200, 200, 50), "好好学习,天天向上");

}

高级绘图

// 绘图事件
void Widget::paintEvent(QPaintEvent*){
    // 实例化画家对象  this指定的是绘图的设备
	QPainter pain(this);

    pain.drawEllipse(QPoint(100,50), 50, 50);

    // 设置 抗锯齿能力,消除走样(线条更精细单效率下降)
    pain.setRenderHint(QPainter::Antialiasing);
    pain.drawEllipse(QPoint(200,50), 50, 50);

    pain.drawRect(QRect(100, 150, 60, 30));
    // 移动画家的起始位置
    pain.translate(200, 0);
    pain.drawRect(QRect(100, 150, 60, 30)); // 因为移动了画家的位置,所以这两个矩形不在同一个位置
    // 移动画家的起始位置
    pain.translate(200, 0);
    // 保存画家状态
    pain.save();
    pain.drawRect(QRect(100, 150, 60, 30));
    // 移动画家的起始位置
    pain.translate(200, 0);
    // 还原画家上一次状态
    pain.restore();
    pain.drawRect(QRect(100, 150, 60, 30)); // 因为移动了画家的位置,所以这两个矩形不在同一个位置
}

画资源图片

// 绘图事件
void Widget::paintEvent(QPaintEvent*){
    // 实例化画家对象  this指定的是绘图的设备
	QPainter painter(this);
    painter.drawPixmap(posx, 100, QPixmap(":/img/2.jpg"));
}

手动调用绘画事件

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    connect(ui->pushButton, &QPushButton::clicked, this, [=](){
        posx+=20;
        // 如果要手动调用绘图事件,最好用update()更新
        update();
    });
}

绘图设备

Qt在进行绘图操作的时候实际上是使用Qpainter在QPainterDevice上进行绘制,它们之间使用QPaintEngine进行通讯。
在这里插入图片描述

绘图设备是指继承QPainterDevice的子类,Qt一共提供了4个这样的类。

  • QPixmap:专门为图像在屏幕上的显示做了优化。
  • QBitmap:是QPixmap的一个子类,它的色深限定为1,可以使用QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。只有黑色和白色。
  • QImage:专门为图像的像素级访问做了优化。可以访问具体的像素点。
  • QPicture:则可以记录和重现QPainter的各条命令。

QPixmap
主要是专门为了平台做显示上的优化。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Pixmap绘图设备:相当于可以往磁盘上进行绘制
    QPixmap pix(300, 300);
    
    // 声明颜色:默认为黑色
    pix.fill(Qt::white);
    
    // 定义画家
    QPainter painter(&pix);
    painter.setPen(QPen(Qt::green));
    painter.drawEllipse(QPoint(150,150), 100, 100);
    
    // 保存
    pix.save("D:\\test.png");
}

上述代码运行后并不会出现任何结果,而是将这个绘图保存到了D:\\test.png路径下。

图像文件在Pixmap和Bitmap的不同表现

void Widget::paintEvent(QPaintEvent *event){
    QPixmap pixmap(":/img/1.jpg");
    QBitmap bitmap(":/img/1.jpg");

    QPainter * pain = new QPainter(this);
    pain->drawPixmap(0, 0, pixmap); // 五颜六色
    pain->drawPixmap(0,400, bitmap); // 只显示黑白
}

QImage
对像素点进行操作

void Widget::paintEvent(QPaintEvent *event){
    QPainter *paint = new QPainter(this);

    // 利用QImage对像素进行修改
    QImage img;
    img.load(":/img/1.jpg");

    // 修改像素点
    for(int i = 50; i < 200; ++i){
        for(int j = 0; j < 200; ++j){
            QRgb value = qRgb(0, 255, 0);
            img.setPixel(i, j, value); // 将指定像素点修改为指定RGB颜色
        }
    }
    paint->drawImage(0,0,img);
}

在这里插入图片描述
可以看到有一坨被改成了绿色。

QPictrue

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // QPicture 绘图设备, 可以记录和重新执行绘图指令
    QPicture pic;
    QPainter paint;
    paint.begin(&pic); // 开始往pic上画
    paint.setPen(QPen(Qt::cyan));
    paint.drawEllipse(QPoint(150,150), 100, 100);
    paint.end(); // 结束绘画

    // 保存到磁盘
    pic.save("D:\\pic"); // 此时生成的文件记录了绘图指令记录,以便于后面的重新执行
}

执行过上述指令后将在指定路径生成pic文件,现在利用这个文件重新执行绘图指令

void Widget::paintEvent(QPaintEvent *event){
    QPainter paint(this);
    // 重现绘图指令
    QPicture pic;
    pic.load("D:\\pic"); // 读取记录文件
    paint.drawPicture(0,0, pic);
}

在这里插入图片描述

文件读写

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 点击按钮,弹出文件对话框

    connect(ui->pushButton, &QPushButton::clicked, [=](){
        QString path = QFileDialog::getOpenFileName(this, "打开文件", "D:\\DeskTop");
        // 将路径放入lineEdit中
        ui->lineEdit->setText(path);

        QFile file(path); // 参数:文件路径
        // 设置打开方式
        file.open(QIODevice::ReadOnly);

        // 将所有的数据读取到array中
        QByteArray array = file.readAll();
		// 读取内容放入textEdit中
        ui->textEdit->setText(array);
    });
}

运行结果:
在这里插入图片描述

默认读取的是utf-8的格式,若读取gbk格式将出现乱码
在这里插入图片描述

下面是读取GBK格式的写法,使用QTextCodec类指定文件的编码格式

connect(ui->pushButton, &QPushButton::clicked, [=](){
        QString path = QFileDialog::getOpenFileName(this, "打开文件", "D:/code/qtStudy");
        // 将路径放入lineEdit中
        ui->lineEdit->setText(path);

        // 编码格式类
        QTextCodec* codec = QTextCodec::codecForName("gbk");

        QFile file(path); // 参数:文件路径
        // 设置打开方式
        file.open(QIODevice::ReadOnly);

        // 将所有的数据读取到array中
        QByteArray array = file.readAll();

        // 读取内容放入textEdit中
        ui->textEdit->setText(codec->toUnicode(array));// 转换为先前指定的格式
    });

写文件

// 进行写文件
file.open(QIODevice::Append); // 追加的方式打开文件
file.write("aaa");
file.close();

文件的具体操作

// QFileInfo文件信息类
QFileInfo info(path);
qDebug() << "大小:" << info.size()
         << "后缀名:" << info.suffix()
         << "文件名称:" << info.fileName()
         << "文件路径:" << info.filePath()
         << "创建日期:" << info.created().toString("yyyy/MM/dd hh:mm:ss")
         << "修改日期:" << info.lastModified().toString("yyyy-MM-dd hh:mm:ss")
         << endl;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt基础学习笔记 的相关文章

  • 上手Nucleo H743ZI 开发板下载失败问题解决方法

    准备研究Stm32H7 xff0c 买了块Nucleo H743ZI开发板回来研究 之前一直使用的是stm32F4 xff0c 开发环境为keil 5 13 43 STM32F4xx DFP 2 10 0 st linkV2 开工之前仔细读
  • 固定翼武德充沛,多旋翼费拉不堪

    实际飞行测试 同样的动力组合 xff1a 2205电机 43 5030 3叶桨 同样的动力电池 xff1a 2200ma xff0c 3s xff0c 20c 基本一致的起飞全重 xff1a 固定翼680g xff0c 多轴700g 续航时
  • PH7系统简介

    PH7系统简介 PH7是什么 xff1f 狭义的PH7是一套以无人机飞控为典型应用案例 xff0c 涵盖无人车或船 GCS数据采集 伺服控制 AHRS 地面模拟仿真系统等的通用控制器代码框架 xff0c 该框架以Stm32CubeMx生成代
  • 小型无人机的布线与布局设计

    小型无人机的布线与布局设计 xff0c 似乎看上去像是在总体设计当中一个细枝末节 xff0c 是往往会被忽略掉的部分 但实际上 xff0c 布线与布局虽然不像飞控算法设计 飞行平台气动设计是总体设计当中最核心和最重要的部分 xff0c 但却
  • Bread Board Pilot 即将发布

    Bread Board Pilot xff08 简称BBP xff09 为基于 PH7 代码框架 xff08 PH7 系统简介 xff09 的一款飞控快速原型开发板 相比传统飞控板 xff0c BBP 的硬件设计具有以下突出特点 xff1a
  • Mavlink 协议硬解析主要代码

    int MAVLinkProtocol ParseMsg BYTE arMsgBuf MSGVALUE pMavMsg CString amp strMsgText Function Parameters arMsgBuf 为完整的 mav
  • 网络调试助手(NetAssist)不能正常创建TCP Serve连接问题

    一 问题由来 第一次使用网络调试助手 xff08 NetAssist xff09 建立服务端 xff08 TCP Server xff09 连接时碰到链接失败的问题 xff0c 如图所示 xff0c 其原因在于本地主机端口8080被其他进程
  • postman调用J-WSSE认证方式接口

    J WSSE认证方式的内容包括 xff1a 用户名 密码 nonce 时间戳 nonce是一个随机字符串 xff1b 时间戳 Created 为W3DTF格式 xff1b 密码创建方式为 xff1a PasswordDigest 61 Ba
  • ROS 三种通信编程入门:【话题通信】【服务通信】【动作通信】

    目录 一 创建工作空间二 ROS通信编程2 1 话题编程2 2 服务编程2 3 动作编程 五 总结六 参考资料 本文内容 xff1a 学习古月居 ROS 教学课件和相关视频 xff0c 练习课件上的话题通信 服务通信编程代码示例 一 创建工
  • .Net6.0系列-8 依赖注入(一)

    依赖注入 Dependency Injection DI 是控制反转 Inversion of Control IOC 思想的实现方式 依赖注入简化模块的组装过程 降低模块之间的耦合度 DI的几个概念 服务 Service 和框架请求之后返
  • Git学习记录

    Git学习记录 概念 xff1a 两个人同时参与开发 xff0c 那么就把这个项目放在一个公共的地方 xff0c 需要的时候都可以去获取 xff0c 有什么改动 xff0c 都可以进行提交 Git就是这样一个免费 开源的分布式版本控制系统
  • Maven学习记录

    Maven学习笔记 导读 xff1a Maven 是专门用于构建和管理Java相关项目的工具 Maven的主要用处 xff1a 项目结构一致统一维护jar包 xff0c 使jar包实现共享 流程 xff1a idea配置 打开File gt
  • 软件需求总结(总)

    软件需求工程复习归纳 课程目标 xff1a 系统地掌握需求开发和管理的技术和方法掌握需求分析和建模的技术和方法掌握需求规格的验证和评审等要点和方法结合具体的实际项目开发 xff0c 解决软件项目开发中的有关需求的各种问题能够适应目前各种应用
  • C++: extern关键字功能和用法研究

    今天遇到在aaa cpp文件中定义如下函数 xff1a 在bbb h文件中有以下声明 xff1a 但在aaa cpp中没有包含相关头文件 xff0c 那么为什么可以调用相关函数 xff0c 这就是extern的功能 1 extern的功能一
  • C语言之断言

    define assert param expr expr void 0 assert failed char FILE LINE Exported functions void assert failed char file int li
  • NMEA 0183协议解析

    NMEA 0183协议是目前GNSS接收机上使用最广泛的协议 xff0c 大多数常见的GNSS接收机 GNSS数据处理软件 导航软件都遵守或者至少兼容这个协议 XXGGA 时间 经纬度位置 解算状态 卫星颗数等相关信息 单GPS GPGGA
  • HTTP Digest认证客户端的实现

    HTTP Digest认证客户端的实现 http lwccb blog 163 com blog static 116970122006727338520 networks 2006 08 27 15 38 52 阅读34 评论0 字号 x
  • 解决vscode C++代码查找所有引用“Find all reference“慢的问题

    概述 使用vscode编写C 43 43 代码右键 34 Find all reference 34 时 xff0c 发现响应特别慢 xff0c 而且很不准确 一个解决方法是使用global组件待的gtags 步骤 在VSCode中安装gt
  • 安防摄像头云端录像计划快捷配置-LiveNVR Onvif/RTSP流媒体服务

    LiveNVR Onvif RTSP流媒体服务 xff0c 支持RTSP稳定拉流接入 xff0c 支持Onvif协议接入 xff0c 支持RTMP HLS HTTP FLV分发 xff0c 将传统安防监控设备互联化 xff0c 无插件直播等
  • LiveNVR中使用Onvif协议控制预置位

    LiveNVR支持预置位控制 xff0c 包括转到指定预置位 xff0c 设置指定预置位 xff0c 删除指定预置位 预置位在安防领域有较为普遍的应用 xff0c 可以进行很多既定位置的跳转 xff0c 很方便 之前我们说过如何用Onvif

随机推荐

  • .NET C#利用ZXing生成、识别二维码/条形码

    文章的原来的IP地址是 xff1a http www jb51 net article 99312 htm ZXing是一个开放源码的 xff0c 用Java实现的多种格式的1D 2D条码图像处理库 xff0c 它包含了联系到其他语言的端口
  • 监控实时直播的四分屏的前端展示

    完成运行效果图 xff1a 一 四分屏展示样式布局 1 通过html css等来进行样式排版 根据需求的四分屏的样式 xff1b 来合理的划分出四个大块 xff0c 分别用于放置四个播放器 xff1b 以四等分结构为例进行前端的排版 xff
  • 通过LiveGBS/LiveNVR实现安防监控视频统一接入汇聚管理(GB28181、Onvif/RTSP等)

    汇聚范围 1 支持GB28181的设备 平台 设备或是平台如果支持GB28181的平台接入 xff0c 就可以在自身的配置管理页面里 xff0c 配置平台接入 直接通过GB28181接入 xff0c LiveGBS国标流媒体服务平台 通过G
  • 智慧工地、雪亮工程、明厨亮灶等各类视项目通过GB28181汇聚视频监控到LiveGBS流媒体管理平台后,视频管理页面简介...

    目前市面上各类监控设备 摄像头 录像机 监控管理平台 等基本都支持GB28181协议 当设备通过GB28181统一汇聚到LiveGBS流媒体视频平台后 xff0c LiveGBS管理页面会管理所有接入进来的监控视频以及服务器硬件 网络状态的
  • LiveNVR Onvif/RTSP流媒体软件接入监控摄像头后如何获取直播流地址进行大屏展示、播放端拉流、网页播放监控视频等...

    1 LiveNVR介绍 LiveNVR的安防监控的视频直播 xff0c 可以按标准的Onvif RTSP协议接入监控设备 xff0c 也可以通过海康 大华 天地伟业等厂家私有SDK接入监控 xff0c 实现web页面的播放和录像回放 可以分
  • GB28181国标平台LiveGBS视频统一汇聚后如何获取固定的播放地址,实现监控视频Web页面无插件播放、拉流分析、上大屏等目的...

    目前汇聚各种厂家监控设备的视频汇聚平台 xff0c 基本都是通过GB28181标准协议实现的 下面介绍下LiveGBS Web无插件直播的GB28181视频平台将各厂家 包括海康 大华 华为 宇视 天地伟业等 监控汇聚到同一个服务器上后 x
  • 解决 LiveQing 流媒体服务器videojs flash播放RTMP、HLS提示错误的问题

    问题 LiveQing流媒体服务器可以输出HTTP FLV Websocket FLV RTMP HLS流 xff0c 在做RTMP HLS flash播放时候 xff0c 经常会遇到网站flash被禁用的情况 xff0c 每一次都会有用户
  • webpack 混淆压缩 javascript 后端代码

    需求背景 JavaScript 是脚本语言 没有编译过程 直接以源码就可以运行 有的时候 出于安全或者其他的原因 我们不希望别人直接读到源码 或者很容易对源码做出修改使用 这个时候 就需要对源码进行混淆压缩处理 经过处理后的代码体积变小 不
  • VideoJS 网页直播实现默认静音

    在开发 LiveQing高性能流媒体服务器 网页直播多分屏的时候 产品提出议建说 能不能在多分屏的时候 默认静音状态 因为多分屏界面 如果声音打开 好多个直播画面同时发出声音太过嘈杂 体验不好 我表示赞同 心想 这个应该不难处理吧 结果踩到
  • VideoJS 网页直播实现双击全屏

    最近接到客户需求 要求我们的网页直播播放器更加符合广大人民群众的使用习惯 实现双击全屏的效果 目前网页直播播放器使用了开源的 VideoJS 它的默认效果是单击播放区域暂停 只能通过右下角的最大化按钮触发最大化 要实现双击全屏播放的效果 就
  • LivePlayer H5直播/点播播放器安装与使用

    LivePlayer H5播放器 简介 H5直播 点播播放器 xff0c 使用简单 xff0c 功能强大 xff0c 免费使用 支持m3u8播放 支持HTTP FLV播放 支持RTMP播放 支持直播和点播播放 支持播放器快照截图 支持点播多
  • Echarts 修改折线的颜色和折线的点的大小方法

    在做SPC分析的时候或者一些专业的分析的时候有的客户会要求 点的大小 样式等 具体的设置方法如下 series type 39 line 39 showSymbol true symbol 39 circle 39 设定为实心点 symbo
  • 抽象工厂模式

    抽象工厂模式针对的是对产品族 xff0c 而不是产品等级结构 产品族 xff1a 同一厂商生产的产品 产品等级 xff1a 同一产品 xff0c 不同厂商的产品 比如水果类里面由苹果和香蕉 xff0c 水果就是产品族 xff0c 苹果香蕉就
  • 面向对象单例模式

    单例模式 xff1a 一个类只能创建一个对象 span class token keyword class span span class token class name A span span class token punctuati
  • 设计模式之代理模式

    概念 xff1a 为其他对象提供一种代理 xff0c 用来控制对象的访问 在某些情况下 xff0c 一个对象不适合或不能直接引用另一个对象 xff0c 而代理对象可以在客户端和目标对象之间起到中介作用 span class token co
  • ARM接口技术基础

    ARM介绍 嵌入式系统 xff1a 嵌入式系统 61 嵌入式硬件 43 嵌入式软件 硬件是软件的载体 xff0c 软件是硬件的灵魂 嵌入式软件 xff1a 1 裸机 xff1a APP 2 系统 xff1a OS 43 APP 嵌入式硬件
  • ARM指令之MOV指令汇编与机器码的对应关系

    指令条件码 条件码就是一种简单的测试ALU状态标志位的方法 mov指令机器码 比如 xff1a mov r1 3 立即数 xff1a 3 第一个操作数 xff1a 寄存器1 S xff1a 0 xff08 注意 xff1a mov指令后面加
  • 设计模式之外观模式

    什么是外观模式 外观模式就是将一个复杂的子类系统抽象到同一个接口进行管理 外界只需要通过此接口与子类系统进行交互 xff0c 不需要直接与复杂的子类系统进行交互 外观模式属于结构型模式 外观模式案例 1 实现KTV模式 xff1a 打开电视
  • 设计模式之适配器模式

    概念 将一个类的接口转换成客户希望的另外一个接口 使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 用vector容器中的for each 举例子 span class token keyword class span span c
  • Qt基础学习笔记

    Qt中的常用快捷键 注释 xff1a ctrl 43 运行 xff1a ctrl 43 r 编译 xff1a ctrl 43 b 帮助文档 xff1a F1 自动对齐 xff1a ctrl 43 i 同名之间 h文件与 cpp文件的切换 x