Qt小案例

工程概述

MainWindows 还是 Widget
Qt 中,创建 "MainWindow" "Widget" 项目的主要区别在于他们的用途和功能范围:
1. MainWindow :这是一个包含完整菜单栏、工具栏和状态栏的主窗口应用程序框架。它适合于更复 杂的应用程序,需要这些额外的用户界面元素来提供丰富的功能和交互。
2. Widget :这通常是一个简单的窗口,没有内置的菜单栏、工具栏或状态栏。它适合于更简单或专用 的应用程序,不需要复杂的用户界面组件
简而言之,选择 "MainWindow" "Widget" 取决于你的应用程序需要多少内置的用户界面元素和复杂 性。 MainWindow 提供了更全面的框架,而 Widget 则更适合简单、专注的界面。

QApplication的作用

是创建一个 QApplication 类的 实例。这是几乎每个Qt 应用程序必须做的第一步,因为它负责管理应用程序的许多核心功能, 它为应用程序提供了必要的环境和框架,确保GUI 组件能够正常 工作并响应用户的操作。
简而言之, QApplication a(argc, argv); 用于初始化Qt应用程序的环境,设置事件循环,并准备应 用程序处理GUI事件。

return a.exec()

Qt 应用程序中, QApplication::exec() 函数是用来启动应用程序的事件循环的当你调用这个函数 时,它会开始处理和分发事件,如用户的点击、键盘输入等。这个函数会一直运行,直到事件循环结 束,通常是因为调用了 QApplication::quit() 函数或者关闭了应用程序的主窗口。简而言之, exec() 是Qt 程序中的主循环,负责监听和响应事件,保持应用程序运行直到用户决定退出。

namespace Ui { class Widget; }

Qt 框架中, namespace Ui { class Widget; } 是一种常见的用法,通常出现在使用 Qt Designer 设计GUI 时自动生成的代码中。这里的 Ui 是一个命名空间,而 class Widget 是一个前向声明,它声明了一个名为 Widget 的类。这种做法允许你在 .cpp 源文件中引用由 Qt Designer 创建的 UI 界面,而不需要在头文件中包含完整的UI 类定义。这种分离的方法有助于减少编译依赖性并保持代码的清晰和组织。 在你的源文件中,你会创建一个 Ui::Widget 类型的对象来访问和操作UI组件。

QT_BEGIN_NAMESPACE

QT_BEGIN_NAMESPACE Qt 框架中用于支持命名空间的宏定义。 Qt 使用这些宏来确保其库中的类和函数 不会与其他库中的同名类和函数冲突。 QT_BEGIN_NAMESPACE 宏在定义 Qt 类和函数之前使用,用来指定 接下来的代码位于Qt 的命名空间, QT_END_NAMESPACE 配对使用,后者标志着命名空间的结 束。这种机制对于在大型项目中维护代码的清晰度和防止命名冲突非常重要。

Q_OBJECT

Q_OBJECT 宏是 Qt 框架中一个非常重要的宏,用于启用 Qt 对象的元对象系统。当你在 Qt 中定义一个类时,如果这个类继承自 QObject 或其子类,并且你想使 Qt 的信号和槽机制、国际化、属性系统或其他 Qt元对象系统提供的功能,就必须在类定义中包含 Q_OBJECT 宏。 这个宏允许 Qt 的元对象编译器( moc )识别并处理这个类,生成额外的代码,这些代码是实现信号和槽 机制以及其他元对象功能所必需的。简单地说, Q_OBJECT 宏为Qt类提供了额外的元数据,使得类能够 完全利用Qt框架的功能。

Widget::Widget(QWidget *parent) : QWidget(parent),ui(new Ui::Widget)

代码 : QWidget(parent) 是初始化列表,用于调用基类 QWidget 的构造函数,并将 parent 传递给 它。 ui(new Ui::Widget) 是初始化类内部的 ui 成员变量,这是通过 new 关键字动态分配的。 Ui::Widget 是由 Qt Designer 工具生成的,用于处理用户界面。这种方式允许将用户界面的设计与后端 逻辑代码分离,有助于提高代码的可维护性和可读性。
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);//创建实例 负责核心功能 管理功能 如检测按键灯
    MainWindow w;   //
    w.show();
    return a.exec(); //exec负责程序运行退出、主循环、监听事件
}

记事本:

按键以及布局 看操作;

如何添加按钮新组件

 

QPushButton { border-image: url(:/icon/o1.png); }
QPushButton:hover:!pressed { border-image: url(:/icon/o2.png); }
QPushButton:pressed { border-image: url(:/icon/o3.png); }

//正常显示,这个路径下的这个图片

按键响应-初识信号与槽

信号与槽基本介绍
提出疑问,界面上已经有按键了,怎么操作才能让用户按下按键后有操作上的反应呢?
Qt 中, 信号和槽机制 是一种非常强大的事件通信机制。这是一个重要的概念,特别是对于初学者来 说,理解它对于编写 Qt 程序至关重要。
概要
1. 信号 (Signals) :是由对象在特定事件发生时发出的消息。例如, QPushButton 有一个
clicked() 信号,当用户点击按钮时发出。
2. (Slots) :是用来响应信号的方法。一个槽可以是任何函数,当其关联的信号被发出时,该槽函数 将被调用。
3. 连接信号和槽 :使用 QObject::connect() 方法将信号连接到槽。当信号发出时,关联的槽函数会自动执行。
按键QPushButton设置信号与槽
Qt 中,有几种不同的方式来设置按键信号与槽的连接,主要包括:
Qt 的信号和槽机制是其事件处理系统的核心。这种机制允许对象之间的通信,而不需要它们知道对方的 具体实现。
以下是Qt 信号和槽的几种常见连接方式的简要概述,我将它们整理成表格形式以便于理解:

这些方式各有优劣,选择哪种方式取决于具体的应用场景、代码风格以及个人偏好。
例如,直接使用 QObject::connect 是最通用的方式,
而使用 Lambda 表达式可以在同一位置编写信号处理逻辑,提高
代码的可读性。
使用函数指针的方式则在编译时提供更好的类型检查。自动连接通常在使用 Qt Designer
设计 UI 时比较方便。

四种信号与槽

第一种:简单信号与槽,通过右键创建槽,会自动生成对应槽信息

 第二种:最常用的方式,直接通过 QObject::connect 函数连接信号和 槽。

 

最常用第四类信号与槽 

使用QObject::connect函数来将一个信号(signal)和一个槽(slot)连接起来。当信号被触发时,与之连接的槽就会被自动调用。

在这个例子中,ui->bnt4是一个QPushButton对象,它的clicked信号会在按钮被点击时发出。我们使用&Widget::on_bnt4_clicked来指定槽函数,这是类Widget的一个成员函数。当按钮被点击时,on_bnt4_clicked函数就会被调用。

这种连接方式的优点包括:

  1. 类型安全:编译器会检查信号和槽的类型是否匹配,如果类型不匹配,编译器会报错。这有助于避免运行时错误。

  2. 代码清晰:不需要使用宏(如SIGNALSLOT),使得代码更加直观和易读。

  3. 支持C++11特性:可以使用C++11的新特性,如lambda表达式、自动类型推断等。

  4. 性能优化:在某些情况下,Qt能够为这种连接方式生成更高效的代码。

下面是这个连接方式的代码示例:

QObject::connect(ui->bnt4, &QPushButton::clicked, this, &Widget::on_bnt4_clicked);

这里,ui->bnt4是发送者(信号的来源),&QPushButton::clicked是信号,this是接收者(槽所在的对象),&Widget::on_bnt4_clicked是槽函数。

#include "widget.h"
#include "ui_widget.h"

//初始化构造函数 列表初始化,并关联信号与槽
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    //QObject::connect 是 Qt 中用于连接信号和槽的函数
    //QObject::connect(sender,SIGNAL(signal()),receiver, SLOT(slot()));
    //在这类中的静态函数,连接(谁发送,信号类型,谁接收,接收函数 槽)
    QObject::connect(ui->bnt2,SIGNAL(clicked),this,SLOT(on_bnt2_clicked));

    //第三种 QObject::connect(sender,&Sender::signal, [=]() {/* lambda body */ });
    //QObject::connect 是 Qt 中用于连接信号和槽的函数。它接受三个参数:发送者对象、发送者的槽函数指针以及一个可调用对象(通常是 lambda 表达式)
    //sender 是发送者对象的指针,表示发出信号的对象、&Sender::signal 是发送者对象的槽函数指针,表示接收信号的槽函数、执行的匿名函数
    QObject::connect(ui->bnt3,&QPushButton::clicked,[=](){ cout << "这是信号与槽 No.3" << endl;});

    //第四种信号与槽QObject::connect(sender,&Sender::signal, receiver,&Receiver::slot);
//    sender 是发送者对象的指针,表示发出信号的对象。
//    &Sender::signal 是发送者对象的槽函数指针,表示要连接的信号。
//    receiver 是接收者对象的指针,表示要接收信号的对象。
//    &Receiver::slot 是接收者对象的槽函数指针,表示要连接的槽函数
    QObject::connect(ui->bnt4,&QPushButton::clicked,this,&Widget::on_bnt4_clicked);
}
//析构函数
Widget::~Widget()
{
    delete ui;
}
//信号槽1
void Widget::on_btn1_clicked()
{
    cout << "这是信号与槽 NO.1" << endl;
}
//信号槽2
void Widget::on_bnt2_clicked()
{
    cout << "这是信号与槽 NO.2" << endl;
}

//信号槽4
void Widget::on_bnt4_clicked()
{
    cout << "这是信号与槽 NO.4" << endl;
}

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <iostream>
using namespace std;

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
//定义了一个私有槽(private slots)的函数,名为on_pushButton_clicked()。这个函数的作用是在按钮被点击时触发相应的操作。
private slots:
    void on_btn1_clicked();
    void on_bnt2_clicked();
    void on_bnt4_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

手动创建信号与槽

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    //在构造函数中绑定信号与槽,信号、槽函数需要加括号
    connect(this,SIGNAL(mySignal()),this,SLOT(myLoats()));
    connect(this,SIGNAL(myLastSignal(int )),this,SLOT(myLastLoats(int )));
    
    //触发该信号
    emit mySignal();
    emit myLastSignal(100);

}

Widget::~Widget()
{
    delete ui;
}

//收到信号 槽开始反应
void Widget::myLoats()
{   //qDebug()函数是Qt提供的一个用于输出调试信息的宏,它会将括号内的内容输出
    qDebug() << "this is No.1" ;
}

void Widget::myLastLoats(int getValue)
{
    qDebug() << "这是信号与槽 值: " << getValue << endl;
}


#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <iostream>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
using namespace std;
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

signals:
    void mySignal();
    void myLastSignal(int value);

private slots:
    void myLoats();
    void myLastLoats(int getValue);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

文件操作类 QFile

QFile Qt 框架中用于文件处理的一个类。它提供了读取和写入文件的功能,支持文本和二进制文 件。 QFile 继承自 QIODevice ,因此它可以像其他 IO 设备一样使用。
主要功能
1. 文件读写 QFile 支持打开文件进行读取或写入操作
2. 文件信息 :可以检索有关文件的信息,如大小、修改日期等。
3. 文件操作 :提供了对文件进行重命名、移动、删除等操作的能力。
4. 错误处理 QFile 在操作文件时提供了错误处理机制,可以通过相应的函数检查和获取错误信息。
常用方法
open() :打开一个文件。需要指定模式(如只读、只写、读写等)。
close() :关闭文件。
read() write() :用于读取和写入数据。
exists() :检查文件是否存在。
remove() :删除文件。
copy() :复制文件。

 

文件读取QFile和QTextStream

直接 QFile读写或者通过 QTextStream in(&file)拷贝构造函数,再进行读写

#include "widget.h"
#include "ui_widget.h"

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

Widget::~Widget()
{
    delete ui;
}


void Widget::on_bntRead_clicked()
{
    // 1.文件io  //第二种写法 QFile file; file.setFileName("E:/demo.txt");
    QFile file("E:/demo.txt");

    // 2.打开 判断返回值布尔类型,以只读打开,Text为自动换行
    if(! file.open(QIODevice::ReadOnly |QIODevice::Text)){
        qDebug() << "open file ";
    }

    // 3.读取文件流 读到哪里 读多大
    int dataSize = file.size();
    char* pData = new char[dataSize];

//    char readBuff[100] = {'\0'};
    if(file.read(pData,dataSize) == -1){
        qDebug() << "read file!" ;
    }
    // 4.输出到控制台
    qDebug() << "this is read: " << pData ;
    delete[] pData;

    // 5.关闭文件
    file.close();
}

void Widget::on_bntWrite_clicked()
{
    // 1.定义文件和路径
    QFile file("E:/demo2.txt");

    // 2.打开文件,以只写自动换行方式打开
    if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
        qDebug() << "open file!";
    }

    // 3.打印写入内容
    char WriteBuff[] = "wirte datas------";
    file.write(WriteBuff,sizeof(WriteBuff));
    \
    qDebug() << WriteBuff;
    // 4.关闭
    file.close();
}

void Widget::on_bntRead2_clicked()
{
    // 1.定义打开
    QFile file("E:/demo.txt");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug() << "open error";
    }

    // 2.整个读取用 QTextStream in读取、setcodec设置读取字符编码、转换成字符串、
//    QTextStream in(&file);
//    in.setCodec("UTF-8");
//    QString str = in.read(file.size());
//    qDebug() << str;

    // 读取这个文件,到尾部为真不到为假,每次读取一行并输出,
    QTextStream in(&file);
    while(!in.atEnd()){ //到尾部为ture  没到false
        QString str = in.readLine();
        qDebug() << str;
        qDebug() << "----------";
    }
    // 3.打印

    // 4.关闭
    file.close();
}

void Widget::on_bntWrite2_clicked()
{
    // 1.创建怎么一个文件
    QFile file("E:/demo3.txt");

    // 2.打开
    if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
        qDebug() << "open error";
    }

    // 3.通过QtextStream方式写入 ,即先拷贝该对象,再写入
    QTextStream out(&file);//拷贝构造
    out.setCodec("UTF-8");//输入编码字符
    out << "this is out write datas form QFile";//把字符串往out对象中写入

    // 5.关闭
    file.close();
}
 QFileDialog函数用法

void Widget::on_bntDialog1_clicked()
{
//    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),"/home",tr("Images (*.png *.xpm *.jpg)"));
    
    // 返回类型 文件名 = 这个类中的静态函数, 
//    this:表示当前对象,通常是一个窗口或对话框对象。
//    tr("Open File"):表示对话框的标题,这里使用了翻译函数tr(),可以根据当前的语言环境自动翻译为相应的文本。
//    "/home":表示对话框打开时的默认目录,这里设置为/home目录。
//    tr("Images (*.png *.xpm *.jpg)"):表示对话框中显示的文件类型过滤器,这里设置为只显示PNG、XPM和JPG格式
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:/demo.txt",tr("Text (*.txt)"));
    qDebug() << fileName ;
}

通过按键按下,找到要打开的文件名,用file绑定打开,一行一行读取内容到TextView中,每次打开要ui->TextView->clear();清除页面

void Widget::on_btOpen_clicked()
{
//    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
//                                                    "/home",
//                                                    tr("Images (*.png *.xpm *.jpg)"));
//    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:",tr("Text (*.txt,*.doc)"));
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:/demo.txt",tr("Text (*.txt)"));
    // 1.打开哪个文件 返回文件名字
    ui->textEdit->clear();

    // 2.实例化file file绑定这个文件
    QFile file;
    file.setFileName(fileName);
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug() << "open error";
    }

    // 3.判断是否到尾部 循环读取 每次读1一行
    QTextStream in(&file);
    in.setCodec("UTF-8");
    while(!in.atEnd()){
        QString str = in.readLine();
        ui->textEdit->append(str);
    }

//    while(!file.atEnd()){
//        QString str = file.readLine();
//        ui->textEdit->append(str);
//    }
    // 4. 显示再TextView中,追加显示,文件覆盖

    // 5.关闭
    file.close();
}

打开保存关闭实现方法 

#include "widget.h"
#include "ui_widget.h"

#include <QFile>
#include <QFileDialog>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    //widget和ui窗口进行关联,但是窗口发生变化时,里面布局不会发生改变
    ui->setupUi(this);

    //通过以下代码可以使串口和布局同时缩放    设置当前布局,为最大层布局
    this->setLayout(ui->verticalLayout);
   // ui->widgetBottom->setLayout(ui->horizontalLayout);
}

Widget::~Widget()
{
    delete ui;
}

//获取打开的文件名,把里面的数据读出来
void Widget::on_btOpen_clicked()
{
//    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
//                                                    "/home",
//                                                    tr("Images (*.png *.xpm *.jpg)"));
//    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:",tr("Text (*.txt,*.doc)"));
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:/demo.txt",tr("Text (*.txt)"));
    // 1.打开哪个文件 返回文件名字
    //每次打开保证刷新新页面
    ui->textEdit->clear();

    // 2.实例化file file绑定这个文件

    file.setFileName(fileName);
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug() << "open error";
    }

    // 3.判断是否到尾部 循环读取 每次读1一行
    QTextStream in(&file);
    in.setCodec("UTF-8");
    while(!in.atEnd()){
        QString str = in.readLine();
        ui->textEdit->append(str);
    }

//    while(!file.atEnd()){
//        QString str = file.readLine();
//        ui->textEdit->append(str);
//    }
    // 4. 显示再TextView中,追加显示,文件覆盖

}

//保存文件,返回文件名,往里面写东西
void Widget::on_btSave_clicked()
{
//                                       getOpenFileNames 返回QStringList
//    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
//                               "/home/jana/untitled.png",
//                               tr("Images (*.png *.xpm *.jpg)"));
    // 1.打开保存文件 返回名字
    QString filename = QFileDialog::getSaveFileName(this,tr("Save File"),"E:/newFileName.txt",tr("Text (*.txt,*.doc)"));

    // 2.实例化file 绑定文件名 打开
    file.setFileName(filename);
    file.open(QIODevice::WriteOnly|QIODevice::Text);

    // 3.以文件流形式,设置字符编码,把ui->textEdit中的文件返回到字符串中,通过<< 流向这个文件名中
    QTextStream out(&file);
    out.setCodec("UTF-8");
    //                                      把textEdit中的内容以字符串返回回来,然后把字符串以文件流输入到打开的这个文件中
    QString TextEditString = ui->textEdit->toPlainText();
    out << TextEditString;

}

void Widget::on_btClose_clicked()
{
    //先判断该file是否已经打开 打开则为ture 按下关闭清除
    qDebug() << file.isOpen();
    if(file.isOpen()){
        ui->textEdit->clear();
        file.close();
    }
}

comboBox用法

#include "widget.h"
#include "ui_widget.h"
#include "QDebug"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //绑定信号与槽函数
    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(oncurrentIndexChanged(int)));

}

Widget::~Widget()
{
    delete ui;
}

void Widget::oncurrentIndexChanged(int index)
{
    qDebug() << index;                      //输出当前序号
    qDebug() << ui->comboBox->currentText();//输出当前文字
}

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
public slots:
    void oncurrentIndexChanged(int index);

};
#endif // WIDGET_H

注释和窗口输出文字乱码问题

 行列显示

cursorPositionChanged 是一个事件,通常在文本编辑器、终端或其他需要处理光标位置的应用程序中使用。当光标的位置发生变化时,这个事件会被触发。它的作用是通知相关的对象或函数光标位置已经改变,以便进行相应的处理,例如更新屏幕显示、同步其他UI组件等。

// 假设有一个名为textEdit的QTextEdit对象
connect(textEdit, &QTextEdit::cursorPositionChanged, this, &MyClass::onCursorPositionChanged);

  1. 获取光标位置:可以使用 textCursor.position() 来获取光标的当前位置。
  2. 设置光标位置:可以使用 textCursor.setPosition(pos) 来设置光标的位置,其中 pos 是光标要移动到的位置。
  3. 获取选中的文本:可以使用 textCursor.selectedText() 来获取当前选中的文本内容。
  4. 设置选中的文本:可以使用 textCursor.insertText(text) 来插入文本,或者使用 textCursor.removeSelectedText() 来删除选中的文本。
  5. 移动光标:可以使用 textCursor.movePosition(QTextCursor::MoveMode, n) 来移动光标,其中 MoveMode 可以是 QTextCursor::UpQTextCursor::Down 等,而 n 是移动的行数或字符数。
  6. 选中文本:可以使用 textCursor.select(QTextCursor::SelectionMode) 来选中文本,其中 SelectionMode 可以是 QTextCursor::WordUnderCursorQTextCursor::BlockUnderCursor 等。

#include "widget.h"
#include "ui_widget.h"

#include <QFile>
#include <QFileDialog>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    //widget和ui窗口进行关联,但是窗口发生变化时,里面布局不会发生改变
    ui->setupUi(this);

    //通过以下代码可以使串口和布局同时缩放    设置当前布局,为最大层布局
    this->setLayout(ui->verticalLayout);
    //ui->widgetBottom->setLayout(ui->horizontalLayout);

    //字符选择
    //绑定信号与槽函数
    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(oncurrentIndexChanged(int)));

    //行列刷新 有文本编辑则发生cursorPositionChanged信号,通过槽接收
    //connect(textEdit, &QTextEdit::cursorPositionChanged, this, &MyClass::onCursorPositionChanged);
    connect(ui->textEdit,&QTextEdit::cursorPositionChanged,this,&Widget::onCursorPositionChanged);

}

Widget::~Widget()
{
    delete ui;
}

//获取打开的文件名,把里面的数据读出来
void Widget::on_btOpen_clicked()
{
//    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
//                                                    "/home",
//                                                    tr("Images (*.png *.xpm *.jpg)"));
//    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:",tr("Text (*.txt,*.doc)"));
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"E:/demo.txt",tr("Text (*.txt)"));
    // 1.打开哪个文件 返回文件名字
    //每次打开保证刷新新页面
    ui->textEdit->clear();

    // 2.实例化file file绑定这个文件

    file.setFileName(fileName);
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug() << "open error";
    }

    this->setWindowTitle(fileName);
    // 3.判断是否到尾部 循环读取 每次读1一行
    QTextStream in(&file);
    //通过combobox选择,对应字符类型,将其转换成const char*设置成对应字符编码
    QString str = ui->comboBox->currentText();
    const char* p_str = str.toStdString().c_str();
    in.setCodec(p_str);
    while(!in.atEnd()){
        QString str = in.readLine();
        ui->textEdit->append(str);
    }

//    while(!file.atEnd()){
//        QString str = file.readLine();
//        ui->textEdit->append(str);
//    }
    // 4. 显示再TextView中,追加显示,文件覆盖

}

//保存文件,返回文件名,往里面写东西
void Widget::on_btSave_clicked()
{
//                                       getOpenFileNames 返回QStringList
//    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
//                               "/home/jana/untitled.png",
//                               tr("Images (*.png *.xpm *.jpg)"));
    // 1.打开保存文件 返回名字
    QString filename = QFileDialog::getSaveFileName(this,tr("Save File"),"E:/newFileName.txt",tr("Text (*.txt,*.doc)"));

    // 2.实例化file 绑定文件名 打开
    file.setFileName(filename);
    file.open(QIODevice::WriteOnly|QIODevice::Text);
    this->setWindowTitle(filename);
    // 3.以文件流形式,设置字符编码,把ui->textEdit中的文件返回到字符串中,通过<< 流向这个文件名中
    QTextStream out(&file);
    out.setCodec("UTF-8");
    //                                      把textEdit中的内容以字符串返回回来,然后把字符串以文件流输入到打开的这个文件中
    QString TextEditString = ui->textEdit->toPlainText();
    out << TextEditString;

}

//关闭文件
void Widget::on_btClose_clicked()
{
    //先判断该file是否已经打开 打开则为ture 按下关闭清除
    qDebug() << file.isOpen();
    if(file.isOpen()){
        ui->textEdit->clear();
        file.close();
        this->setWindowTitle("MyNotepad");
    }
}

//字符切换
void Widget::oncurrentIndexChanged(int index)
{
    ui->textEdit->clear();//要改变字体先清除
    file.seek(0);           //清除完光标移动到最前端
    if(file.isOpen()){      //该文件是否打开 打开
       QTextStream in(&file);//绑定该文件
       in.setCodec(ui->comboBox->currentText().toStdString().c_str());//将对应编码转换成字符串
       while(!in.atEnd()){   //判断是否在最尾巴上
           QString str = in.readLine();//每次读一行输出一行
           ui->textEdit->append(str);
       }
    }
}


//字符编码为GBK方便显示注释等信息 但是窗口文字会乱码
//窗口文字不乱码要设置成UTF-8 并重新打开工程

//行列显示的槽函数
void Widget::onCursorPositionChanged()
{
   //获取
   QTextCursor cursor =  ui->textEdit->textCursor();//获取光标对象
   QString blockNumbre = QString::number(cursor.blockNumber() + 1);//获取列 转换成int型
   QString columnNumbre = QString::number(cursor.columnNumber() + 1);//获取行 转换成int型
   QString mes = "L:"+blockNumbre + ",R:" + columnNumbre;//行列拼接
   ui->labelLine->setText(mes);//将行列显示在lab控建中  ui->labelLine 是一个指向标签控件的指针
   qDebug() << mes;
}

模板泛型

#include <iostream>

using namespace std;

class printInt{
private:
    int data;
public:
    void printIntData();
    void setData(int data);
};

void printInt::printIntData(){
    cout << data <<endl;
}
void printInt::setData(int data){
    this->data = data;
}


class printString{
private:
    string data;
public:
    void printStringData();
    void setStringData(string data);
};

void printString::printStringData(){
    cout << data <<endl;
}
void printString::setStringData(string data){
    this->data = data;
}

//函数模板  T是泛型   降低代码量减少函数重载
template<typename T>
class printEventhing{
private:
    T data;
public:
    void printEvenData(){
        cout << data <<endl;
    }
    void setEventhing(T data){
        this->data = data;
    }
};


int main()
{
    printInt p1;
    p1.setData(10);
    p1.printIntData();


    printString s1;
    s1.setStringData("这是string");
    s1.printStringData();

    printEventhing<int> p2;
    p2.setEventhing(100);
    p2.printEvenData();

    printEventhing<string> s2;
    s2.setEventhing("这是模板泛型");
    s2.printEvenData();

    return 0;
}

相关推荐

  1. 爬虫(案例

    2024-04-04 13:14:01       15 阅读
  2. 前端案例

    2024-04-04 13:14:01       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-04 13:14:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-04 13:14:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-04 13:14:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-04 13:14:01       20 阅读

热门阅读

  1. Vue的双向绑定v-model详细介绍

    2024-04-04 13:14:01       13 阅读
  2. 责任链模式详解+代码案例

    2024-04-04 13:14:01       16 阅读
  3. ES6模块与CommonJs模块异同

    2024-04-04 13:14:01       14 阅读
  4. git已经commit的怎么合并信息再push

    2024-04-04 13:14:01       18 阅读
  5. 前端查询前校验该输入的字段是否能够进行查询

    2024-04-04 13:14:01       13 阅读
  6. C++多态

    C++多态

    2024-04-04 13:14:01      15 阅读
  7. 【Vue.js 3.0】NProgress 进度条

    2024-04-04 13:14:01       15 阅读
  8. html中的div标签

    2024-04-04 13:14:01       16 阅读