C++ QT开发 学习笔记(3)

C++ QT开发 学习笔记(3) - WPS项目

标准对话框

对话框类说明静态函数函数说明
QFileDialog文件对话框getOpenFileName()选择打开一个文件
getOpenFileNames()选择打开多个文件
getSaveFileName()选择保存一个文件
getExistingDirectory()选择一个己有的目录
getOpenFileUrl()选择打幵一个文件,可选择远程网络文件
QColorDialog颜色对话框getColor()选择颜色
QFontDialog字体对话框QFont getFont()选择字体
QInputDialog输入对话框getText()输入单行文字
getlnt()输入整数
getDouble()输入浮点数
getltem()从一个下拉列表框中选择输入
getMultiLineText()输入多行字符串
QMessageBox消息框information()信息提示对话框
question()询问并获取是否确认的对话框
waming()警告信息提示对话框
critical()错误信息提示对话框
about()设置自定义信息的关于对话框
aboutQt()关于Qt的对话框

新建桌面应用程序,项目名testStandardDialogs,类名Dialog,基类QDialog,不勾选创建界面文件。

编辑dialog.h文件

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPushButton>
#include <QLineEdit>
#include <QGridLayout>
#include "inputdlg.h"
#include "msgboxdialog.h"class Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = 0);~Dialog();private:QPushButton* m_fileBtn;     //打开文件对话框QLineEdit* m_fileLineEdit;  //显示所源文件路径QGridLayout* m_mainLayout;  //布局管理器QPushButton *m_ColorBtn;    //打开颜色对话框QFrame* m_ColorFrame;       //显示所愿颜色效果QPushButton* m_fontBtn;     //打开字体对话框QLineEdit* m_fontLineEdit;  //显示所选字体效果QPushButton* m_inputBtn;    //显示输入对话框InputDlg* m_inputDlg;       //自定义InputDlg 对象QPushButton* m_msgBtn;      //显示消息对话框MsgBoxDialog* m_msgboxDlg;  //消息对话框QPushButton* m_customBtn;   //自定义消息框QLabel* m_customLabel;      //自定义标签private slots:void ShowFileDlg();void ShowColorDlg();void ShowFontDlg();void ShowInputDlg();void ShowMsgDlg();void ShowCustomDlg();
};#endif // DIALOG_H

编辑dialog.cpp编辑构造函数及添加相应成员函数的定义

#include "dialog.h"
#include <QFileDialog>
#include <QColorDialog>
#include <QFontDialog>
#include <QMessageBox>Dialog::Dialog(QWidget *parent): QDialog(parent)
{setWindowTitle("Standrad Dialog Example");m_fileBtn = new QPushButton("File Standard Dialog");m_fileLineEdit = new QLineEdit;m_ColorBtn = new QPushButton("Color Dialog");m_ColorFrame = new QFrame;//设置边框风格m_ColorFrame->setFrameStyle(QFrame::Box);//设置填充背景属性m_ColorFrame->setAutoFillBackground(true);m_fontBtn = new QPushButton("Font Dialog");m_fontLineEdit = new QLineEdit("Test Font");m_inputBtn = new QPushButton("Standard Input Dialog");m_msgBtn = new QPushButton("Standard Message Box Dialog");m_customBtn = new QPushButton("Custom Message Box");m_customLabel = new QLabel;m_customLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);m_mainLayout = new QGridLayout(this);m_mainLayout->addWidget(m_fileBtn,0,0);m_mainLayout->addWidget(m_fileLineEdit,0,1);m_mainLayout->addWidget(m_ColorBtn,1,0);m_mainLayout->addWidget(m_ColorFrame,1,1);m_mainLayout->addWidget(m_fontBtn,2,0);m_mainLayout->addWidget(m_fontLineEdit,2,1);m_mainLayout->addWidget(m_inputBtn,3,0,1,2);   //第三参数是占几行,第四参数是占几列m_mainLayout->addWidget(m_msgBtn,4,0,1,2);m_mainLayout->addWidget(m_customBtn,5,0);m_mainLayout->addWidget(m_customLabel,5,1);connect(m_fileBtn, &QPushButton::clicked,this,&Dialog::ShowFileDlg); // connect(sender, signal, receiver, slot);// sender:发出信号的对象。//signal:需要连接的信号,通常使用 &SenderClassName::signalName 形式表示。//receiver:接收信号并响应的对象,即槽函数所属的对象实例。//slot:当信号被发出时,应该被调用的函数,使用 &ReceiverClassName::slotName 形式表示。//connect(this,SIGNAL(Comeon(QString&)),this,SLOT(ComeonGuys(QString&))); <<<为什么这个写法没有 :: 呢? 因为 SIGNAL/SLOT 宏将它们转换为字符串。//这个字符串不需要包括函数所属的类名称,因为 SIGNAL 和 SLOT 宏已经处理了所有必要的信息,以便 Qt 的元对象系统可以解析它们。connect(m_ColorBtn,&QPushButton::clicked,this,&Dialog::ShowColorDlg);connect(m_fontBtn, &QPushButton::clicked,this,&Dialog::ShowFontDlg);connect(m_inputBtn, &QPushButton::clicked,this,&Dialog::ShowInputDlg);connect(m_msgBtn,&QPushButton::clicked, this,&Dialog::ShowMsgDlg);connect(m_customBtn, &QPushButton::clicked, this, &Dialog::ShowCustomDlg);
}Dialog::~Dialog()
{}void Dialog::ShowFileDlg()
{QString sPath = QFileDialog::getOpenFileName(this,"File Standard Dialog",".","C++ files(*.cpp);;C files(*.c;; Header files(*.h))");m_fileLineEdit->setText(sPath);
}void Dialog::ShowColorDlg()
{QColor color = QColorDialog::getColor(Qt::red);    //red as default color // Not QColor::redif(color.isValid())m_ColorFrame->setPalette(QPalette(color));
}void Dialog::ShowFontDlg()
{bool ok;QFont font= QFontDialog::getFont(&ok);      //参数位是否成功if(ok)m_fontLineEdit->setFont(font);
}void Dialog::ShowInputDlg()
{m_inputDlg = new InputDlg(this);m_inputDlg->show();
}void Dialog::ShowMsgDlg()
{m_msgboxDlg = new MsgBoxDialog(this);m_msgboxDlg->show();
}void Dialog::ShowCustomDlg()
{m_customLabel->setText("Custom Message Dialog");QMessageBox* customMsgBox = new QMessageBox(this);customMsgBox->setWindowTitle("Custom Message Dialog");QPushButton* yes = customMsgBox->addButton("Yes",QMessageBox::ActionRole);  //ActionRole = 触发特定动作的按钮,这些动作与对话框的主要目的(如确认或取消)不直接相关。QPushButton* no = customMsgBox->addButton("No",QMessageBox::ActionRole);QPushButton* cancel = customMsgBox->addButton(QMessageBox::Cancel);customMsgBox->setIconPixmap(QPixmap("cat.gif"));customMsgBox->exec();if(customMsgBox->clickedButton() == yes)m_customLabel->setText("Clicked Yes");if(customMsgBox->clickedButton() == no)m_customLabel->setText("Clicked No");if(customMsgBox->clickedButton() == cancel)m_customLabel->setText("Clicked Cancel");}
  • m_customLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);setFrameStyle函数和带入参数是为了*

    • QFrame::Panel - 这个枚举值指定框架应该有一个面板风格,这意味着它会被渲染为一个凸起或凹陷的区域,具体取决于与之组合的另一个样式(如凹陷或凸起)
    • QFrame::Sunken - 个枚举值表示框架应该呈现为凹陷风格,这在视觉上给人的感觉是框架边缘向内陷进去,使得框架内部的内容看起来像是低于周围表面的
  • 另外,这里面使用了多次的connect函数,大部分写法为 connect(m_ColorBtn,&QPushButton::clicked,this,&Dialog::ShowColorDlg);

    • 为什么之前写的方法connect(this,SIGNAL(Comeon(QString&)),this,SLOT(ComeonGuys(QString&))); 第四个参数没有:: 符号?

      • 这是因为SLOT 宏将它们转换为字符串,从而执行该槽函数了
  • 另外,请注意QDialog类的对象要显示Dialog出来都需要 .show().exec() 函数, 但 QFileDialog, QMessageBox, QColorDialog, QFontDialog, QInputDialog对象不需要

  • QPushButton* yes = customMsgBox->addButton("Yes",QMessageBox::ActionRole); 这里面 addButton函数的参数 ActionRole 为触发特定动作的按钮,这些动作与对话框的主要目的(如确认或取消)不直接相关。

当前项目添加C++类,类名InputDlg,基类QDialog

编辑inputdlg.h文件

#ifndef INPUTDLG_H
#define INPUTDLG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>class InputDlg : public QDialog
{Q_OBJECT
public:InputDlg(QWidget* parent = 0);private:QLabel* m_nameTitle;    //Name:QLabel* m_sexTitle;     //Sex:QLabel* m_ageTitle;QLabel* m_scoreTitle;QLabel* m_nameLabel;    //QLabel* m_sexLabel;QLabel* m_ageLabel;QLabel* m_scoreLabel;QPushButton* m_nameBtn;QPushButton* m_sexBtn;QPushButton* m_ageBtn;QPushButton* m_scoreBtn;QGridLayout* m_mainLayout ;     //布局管理器private slots:void editName();void editAge();void editSex();void editScore();
};#endif // INPUTDLG_H

编辑InputDlg构造函数及添加相应槽函数的定义

#include "inputdlg.h"
#include <QInputDialog>InputDlg::InputDlg(QWidget* parent):QDialog(parent)
{setWindowTitle("Input Dialog");m_nameTitle = new QLabel("Name:");m_sexTitle = new QLabel("Sex:");m_ageTitle = new QLabel("Age:");m_scoreTitle = new QLabel("Mark:");m_nameLabel = new QLabel("CCS");m_sexLabel = new QLabel("Male");m_ageLabel = new QLabel("27");m_scoreLabel = new QLabel("99.9");m_nameBtn = new QPushButton("Edit Name");m_sexBtn = new QPushButton("Edit Sex");m_ageBtn = new QPushButton("Edit Age");m_scoreBtn = new QPushButton("Edit Score");m_mainLayout = new QGridLayout(this);m_mainLayout->addWidget(m_nameTitle,0,0);m_mainLayout->addWidget(m_nameLabel,0,1);m_mainLayout->addWidget(m_nameBtn,0,2);m_mainLayout->addWidget(m_sexTitle,1,0);m_mainLayout->addWidget(m_sexLabel,1,1);m_mainLayout->addWidget(m_sexBtn,1,2);m_mainLayout->addWidget(m_ageTitle,2,0);m_mainLayout->addWidget(m_ageLabel,2,1);m_mainLayout->addWidget(m_ageBtn,2,2);m_mainLayout->addWidget(m_scoreTitle,3,0);m_mainLayout->addWidget(m_scoreLabel,3,1);m_mainLayout->addWidget(m_scoreBtn,3,2);m_mainLayout->setSpacing(20);m_mainLayout->setMargin(10);connect(m_nameBtn, &QPushButton::clicked,this,&InputDlg::editName);connect(m_sexBtn, &QPushButton::clicked,this,&InputDlg::editSex);connect(m_ageBtn, &QPushButton::clicked,this,&InputDlg::editAge);connect(m_scoreBtn, &QPushButton::clicked,this,&InputDlg::editScore);}void InputDlg::editName()
{bool ok;QString sName = QInputDialog::getText(this,"Standard Text Input","Please Edit Name",QLineEdit::Normal,m_nameLabel->text(),&ok);if(ok)m_nameLabel->setText(sName);
}void InputDlg::editAge()
{bool ok;int age = QInputDialog::getInt(this,"Standard int data type dialog","Please Edit Age",m_ageLabel->text().toInt(),0,120,1,&ok);  //why toInt, what is the parameter meansif (ok)m_ageLabel->setText(QString("%1").arg(age));    //from int change to QString.
}void InputDlg::editSex()
{bool ok;QStringList sexList;sexList<<"Male"<<"Female"<<"Non-stated";QString sex = QInputDialog::getItem(this,"Standard Selection Input","Please Select Sex:",sexList,0,false,&ok);if(ok)m_sexLabel->setText(sex);}void InputDlg::editScore()
{bool ok;double score = QInputDialog::getDouble(this,"Standard double datatype input dialog","Please input value",m_scoreLabel->text().toDouble(),0,100,2,&ok); // what is the parameter means for .toDoubleif(ok)m_scoreLabel->setText(QString::number(score));  //number convert to QString}

m_ageLabel->setText(QString("%1").arg(age));

正则表达式

正则表达式即一个文本匹配字符串的一种模式,Qt中QRegExp类实现使用正则表达式进行模式匹配,且完全支持Unicode,主要应用:字符串验证、搜索、查找替换、分割。

正则表达式中字符及字符集

元素含义
c匹配字符本身,如a匹配a
\c跟在\后面的字符匹配字符本身,但本表中下面指定的这些字符除外。
\a匹配ASCII的振铃
\f匹配ASCII的换页
\n匹配ASCII的换行
\r匹配ASCII的回车
\t匹配ASCII的水平制表符
\v匹配ASCII的垂直制表符
\xhhhh匹配Unicode字符对应的十六进制数
\0ooo匹配八进制的ASCII/Latin1字符
.匹配任意字符
\d匹配任意一个数字
\D匹配一个非数字
\s匹配一个空白字符,包括“\t”、“\n”、“\v”、“\f”、“\r”及“”
\S匹配一个非空白字符
\w匹配一个单词字符,包括任意字符数字下划线,即AZ,az,0~9中任意一个
\W匹配一个非单词字符
\n第n个反向引用

正则表达式中的量词

量词含义
E?匹配0次或1次等价于E{0,1}
E+匹配1次或多次,等价于E{1,}
E*匹配0次或多次,等价于E{0,}
E{n}匹配n次
E{n,}匹配至少n次
E{,m}匹配至多m次
E{n,m}匹配至少n次,至多m次

正则表达式中的断言

断言含义
^标志字符串的开始。若匹配“”则使用“\
$标志字符串的结尾。若匹配“$”则使用“\$”
\b一个单词的边界
\B一个非单词的边界。当\b为false则它为true
(?=E)表达式后紧跟E才匹配
(?!E)表达式后不跟E才匹配

QRegExp同时支持通配符

通配符含义
c任意一个字符,表字符本身
任意一个字符,类似regexp中“.”
*任意0个或多个字符
[…]在[]中的字符集

新建控制台应用程序,项目名QRegExp

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include <QRegularExpression>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QRegExp reg("a");qDebug() <<"Match Char 'abc':"<<reg.exactMatch("abc");qDebug() <<"Match char 'a':"<<reg.exactMatch("a");QRegExp reg0("(\\d*\\D{2})");qDebug()<<"Match Num:"<<reg0.exactMatch("183cm")<<reg0.exactMatch("183m")<<reg0.exactMatch("72in");QRegExp rx("*.txt");rx.setPatternSyntax(QRegExp::Wildcard); //支持通配符 - 设置匹配语法qDebug()<<"Wildcard Match:"<<rx.exactMatch("License.txt")<<rx.exactMatch("License.txt.bak");//匹配单词边界QRegExp reg1;reg1.setPattern("\\b(hello|Hello)\\b");     // \\b可以帮助确保你的正则表达式匹配完整的单词而不是单词的一部分qDebug()<<"Match Muiltiple Word:"<<reg1.indexIn("Hi,helloEveryOne") //-1 没找到<<reg1.indexIn("Hmmm hello everyone")                        //5 在第5个位置<<reg1.indexIn("Hi Boys, Hello girls");                       //9  在第9个位置//捕获匹配文本//由"(?:"开始, ")" 结束QRegExp regHeight("(\\d+)(?:\\s*)(cm|inch)");int res = regHeight.indexIn("YaoMing 226cm");if(res > -1){qDebug()<<"The text captured:"<<"Cap(0):"<<regHeight.cap(0)<<"cap(1):"<<regHeight.cap(1)<<"cap(2):"<<regHeight.cap(2);}//断言?! 不紧跟才算匹配.  ?= 紧跟才匹配QRegExp reg2;reg2.setPattern("Noodle(?!s)");//reg2.setCaseSensitivity(Qt::CaseInsensitive); 如果需要设置成大小写不敏感QString str = "Noodle is sold out, but Noodles have! Noodles is the best!";qDebug()<<str<<endl;str.replace(reg2,"Bread");qDebug()<<str<<endl;//QT5 引入新的类QRegularExpression regExp("hello");qDebug()<<"QRegularExpression Match Character:"<<regExp.match("hello world!");regExp.setPattern("^[A-Z]{3,8}$");  //设置匹配模式regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);qDebug()<<"Case Insensitive Match:"<<regExp.match("hello");QRegularExpression reDate("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$");QRegularExpressionMatch match0 = reDate.match("01/10/1949");if(match0.hasMatch()){QString strMatch = match0.captured(0);QString day = match0.captured(1);QString month = match0.captured(2);QString year = match0.captured(3);qDebug()<<"QRegularExpression Captured Text: "<<"strMatch:"<<strMatch<<"day:"<<day<<"month:"<<month<<"year:"<<year;}//部分匹配QString sPattern;sPattern = "^(Jan|Feb|March|April|May|June) \\d\\d \\d\\d\\d\\d$";QRegularExpression reDate1(sPattern);QString ss("Feb 28");QRegularExpressionMatch match2;match2 = reDate1.match(ss,0,QRegularExpression::PartialPreferCompleteMatch);bool bHasMatched = match2.hasMatch();bool bPartial = match2.hasPartialMatch();qDebug()<<bHasMatched <<bPartial;return a.exec();
}
  • 当在使用正则表达式并且该表达式包含反斜杠 \时,需要使用两个反斜杠 \\ 来表达一个单独的反斜杠

  • rx.setPatternSyntax(QRegExp::Wildcard); setPatternSyntax 的函数用于设置用于解析正则表达式的语法模式. 代码 rx.setPatternSyntax(QRegExp::Wildcard); 的意思是将 QRegExp 对象 rx 的解析模式设置为 Wildcard

  • IndexIn函数用于在字符串中查找与正则表达式匹配的第一个位置

  • .cap()方法用于返回由正则表达式匹配的特定捕获组的内容

  • \b 单词的边界 意思是单词边界可以帮助确保你的正则表达式匹配完整的单词而不是单词的一部分

  • QRegularExpression是QT5引入的新类,需要包括头文件 #include <QRegularExpression>>

  • QRegExpQRegExpression 设置大小写不敏感匹配方法不一样, QRegExp是使用方法setCaseSensitivityQRegularExpression是使用setPatternOptions(QRegularExpression::CaseInsensitiveOption)方法

  • QRegularExpressionMatch类用于表示由 QRegularExpression 对象进行模式匹配操作后的结果。

    QRegularExpressionMatch` 类提供了多种方法来检索有关匹配的信息,例如:

    • 是否匹配成功:可以通过调用 hasMatch() 方法来检查是否存在至少一个匹配。
    • 是否部分匹配成功**:hasPartialMatch() 方法用于检查是否存在部分匹配,这在某些高级匹配情况下有用。
    • 捕获组的内容:可以使用 captured(int) 方法获取具体的捕获组的文本。这里的参数是捕获组的索引,其中 0 索引代表整个匹配的文本,1 和更高的索引代表具体的子捕获组。**
    • 捕获组的开始和结束位置:通过 capturedStart(int)capturedEnd(int) 方法可以获取任意捕获组的开始和结束位置。
    • 捕获组的数量:使用 capturedTexts()lastCapturedIndex() 方法可以获得匹配中包含的捕获组数量。
  • QRegularExpression 部分匹配需写成 QRegularExpressionMatch match2 = reDate1.match(ss,0,QRegularExpression::PartialPreferCompleteMatch);

  • QRegExp不直接支持像 QRegularExpression 那样的部分匹配模式选项.

    • 所以类似部分匹配需写成"^(Jan|Feb|March|April|May|June) \\d\\d(?: \\d\\d\\d\\d)?$" 这样的话无论有没有输入年份都可以匹配了.

文件处理

QFile类用于文件操作,它提供了读写文件的接口,可以读写文件、二进制文件和Qt资源文件。

处理文本文件和二进制文件,可以使用QTextStream类和QDataStream类。处理临时文件可以使用QTemporaryFile,获取信息可以使用QFileInfo,处理目录可以使用QDir,监视文件和目录变化可以使用QFileSystemWatcher

QTextStream的流操作符

操作符作用描述
bin设置读写的整数为 二进制数
oct设置读写的整数为 八进制数
dec设置读写的整数为十进制数
hex设置读写的整数为十六进制数
showbase强制显示进制前缀,如十六进制(0x)、八进制(0)、二进制(0b)
forcesign强制显示符号(+、-)
forcepoint强制显示小数点
noshowbase强制不显示前缀
noforcesign强制不显示符号
uppercasebase显示大写的进制前缀
lowercasebase显示小些的进制前缀
uppercasedigits用大写字母表示
lowercasedigits用小写字母表示
fixed固定小数点表示
scientific科学计数法表示
left左对齐
right右对齐
center居中
endl换行
flush清除缓冲

QFile QTextStream操作文件示例:

新建控制台引用程序,编辑main函数,main.cpp添加头文件:

#include <QCoreApplication>
#include <QFile>
#include <qDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QFile file("hello.txt");//读取文件if(file.open(QIODevice::ReadOnly))     //参数是带入QIODevice的枚举类型, 因为点开open函数的话,他是需要OpenMode 类型//然而OpenMode 类型是通过Q_DECLARE_FLAGS<新函数名,枚举类型>函数创建的新类型,其枚举类型是//QIODevice 的枚举类型,因此此处带入QIODevice没问题.{char buffer[100];qint32 n;               //等于int类型n = file.readLine(buffer,sizeof(buffer));    //.readLine函数若返回-1,表示读取失败//若成功读取则返回读取的字节数if(n!=-1){qDebug()<<"Sucessfully read the file";qDebug()<<"Length:"<<n<<"buffer:"<<buffer;file.close();                             //一定要记得关闭文件}else{qDebug()<< file.errorString();      //会返回QIODevice(QFile的父类)的成员的错误原因}//文件写入double dPI = 3.1415926;int age = 13;QFile dataFile;dataFile.setFileName("data.txt");   //设置 QFile类对象的文档名字if(dataFile.open(QFile::WriteOnly | QFile::Truncate))           //和dataFile.open(QIODevice::WriteOnly | QIODevice::Truncate) 写法一样//因为QFile是作为QIODevice的子类,继承了枚举值{QTextStream out(&dataFile);     //带入参数为QIODevice类型,QFile类型也可以.out.setRealNumberPrecision(3);out.setFieldWidth(10);out.setFieldAlignment(QTextStream::AlignRight);//文件流操作out<<QString("PI:")
//               <<qSetRealNumberPrecision(3) //需设置精度,否则默认为6位
//               <<qSetFieldWidth(10)         //文件内容必须为10位宽,否则会加入多个空行,默认右对齐<<scientific<<left                       //设置成右对齐<<dPI;
//              <<hex
//              <<showbase
//              <<uppercasebase
//              <<age;}}return a.exec();
}
  • open参数是带入QIODeviceQFile的, 其参数是枚举值,但为什么点开Open函数的话带入的类型是OpenMode类型的呢?

    原因是 openMode类型是通过Q_DECLARE_FLAGS<新函数名,枚举类型>函数创建的新类型,其枚举类型是QIODevice 的枚举类型,因此此处带入QIODevice没问题, QFile也没问题是因为QFileQIODevice的子类

  • qint32类型也等于int类型

  • readLine 第一参数为读取文档内容后放置的变量,第二参数为读取最大限制字符大小.返回值为读取字符大小,若返回-1表示读取数据失败

  • setFileName函数用于设置 QFile类对象的文档名字

  • QTextStream out(&dataFile); 带入参数为QIODevice类型,QFile类型也可以.

  • 上表格的文件流的操作是基于类似out<<QString("PI:")<<qSetRealNumberPrecision(3) <<scientific<<dPI 的写法

    • 然而,QTextStream也有基于成员函数的写法,比如setRealNumberPrecision(3), setFieldWidth(10)
    • 为什么有两种不同的写法呢? 原因是一种是基于成员函数设置, 另一种是基于操纵符的设置

    示例代码差异

    out.setRealNumberPrecision(3);
    out.setFieldWidth(10);
    out.setFieldAlignment(QTextStream::AlignRight);out << scientific<< left<< dPI;
    

读写二进制文件示例:

新建控制台应用程序,编辑main函数,main.cpp添加头文件

#include <QCoreApplication>
#include <QFile>
#include <QDate>
#include <QDataStream>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QFile binFile("info.bat");if(binFile.open(QIODevice::WriteOnly | QIODevice::Truncate)){//往文件中写入数据QDataStream out(&binFile);out<<QString("Micheal Jackson")<<QDate::fromString("1950-11-29","yyyy-MM-dd")<<(qint32)19;binFile.close();}else{qDebug()<<binFile.errorString();}//binFile.setFileName("info.bat");    //可以不执行这一行,但是如果前面没有 into.txt的话只是读取一个外部的文件的话就需要设置.if(binFile.open(QIODevice::ReadOnly)){QDataStream in(&binFile);QString name;QDate birthday;qint32 age;in>>name>>birthday>>age;qDebug()<<name<<birthday<<age;binFile.close();}return a.exec();
}
  • 上面代码的binFile.setFileName("info.bat")可以不写,但是如果情况是上面没有定义过 binFile的文档名的话就需要,不然程序都不知道要对哪个文档执行操作
  • QDate::fromString("1950-11-29","yyyy-MM-dd") 第一参数为日期,第二参数为日期格式

QFileInfo类获取文件信息示例:

新建桌面应用程序,基类QWidget,类名FileInfo,勾选创建界面文件

设计模式下设计界面

在这里插入图片描述

fileinfo.h文件添加成员函数及槽函数声明:

#ifndef FILEINFO_H
#define FILEINFO_H#include <QWidget>namespace Ui {
class FileInfo;
}class FileInfo : public QWidget
{Q_OBJECTpublic:explicit FileInfo(QWidget *parent = 0);~FileInfo();void getFileInfo(QString& fileName);private slots:void on_browseFileBtn_clicked();private:Ui::FileInfo *ui;
};#endif // FILEINFO_H

fileinfo.cpp编辑构造函数并添加成员函数定义:

#include "fileinfo.h"
#include "ui_fileinfo.h"
#include <QFileDialog>
#include <QDateTime>FileInfo::FileInfo(QWidget *parent) :QWidget(parent),ui(new Ui::FileInfo)
{ui->setupUi(this);setWindowTitle("File Information");
}FileInfo::~FileInfo()
{delete ui;
}void FileInfo::getFileInfo(QString &fileName)
{QFileInfo info(fileName);qint64 size = info.size();  //.size函数返回qint64类型.QDateTime createTime = info.created();  //文件创建时间QDateTime lastMTime = info.lastModified();  //文件修改时间QDateTime lastRTime = info.lastRead();  //文件访问时间//文件的属性信息bool bIsDir = info.isDir();bool bIsFile = info.isFile();bool bIsSymLink = info.isSymLink();bool bIsHidden = info.isHidden();bool bIsReadable = info.isReadable();bool bIsWriteable = info.isWritable();bool bIsExutable = info.isExecutable();ui->fileSizeLineEdit->setText(QString::number(size));       //数字转QStringui->fileCreatedLineEdit->setText(createTime.toString());    //日期转QStringui->fileModifiedLineEdit->setText(lastMTime.toString());ui->fileVisitedLineEdit->setText(lastRTime.toString());ui->isDirCheckBox->setChecked(bIsDir);ui->isFileCheckBox->setChecked(bIsFile);ui->IsSymLnkCheckBox->setChecked(bIsSymLink);ui->isHideCheckBox->setChecked(bIsHidden);ui->isWriteCheckBox->setChecked(bIsWriteable);ui->isReadCheckBox->setChecked(bIsReadable);ui->isExecuteCheckBox->setChecked(bIsExutable);
}void FileInfo::on_browseFileBtn_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,"Open File...",".","files(*)");//QString path = QFileDialog::getExistingDirectory(this,"Select Directory", ".");   //选择目录方法ui->fileNameLineEdit->setText(fileName);getFileInfo(fileName);
}

我的WPS项目

新建项目

新建WPS,基类QMainWindow,勾选界面文件

菜单项工具栏

在这里插入图片描述

在这里插入图片描述

菜单属性

在这里插入图片描述

新建子窗口

项目添加ChildWnd类,继承自QTextEdit

ChildWnd.h

#ifndef CHILDWND_H
#define CHILDWND_H
#include <QTextEdit>class ChildWnd : public QTextEdit
{Q_OBJECTpublic:ChildWnd();QString m_CurDocPath;   //当前文档路径void newDoc();          //新建文档QString getCurDocName();  //文件路径中提取文档名private slots:void docBeModified();   //文档修改时,窗口标题栏加个'*'private:bool m_bSaved;          //文档是否保存};#endif // CHILDWND_H

ChildWnd.cpp

#include "childwnd.h"
#include <QFileInfo>ChildWnd::ChildWnd()
{setAttribute(Qt::WA_DeleteOnClose);     //子窗口关闭时,销毁该类的实例对象m_bSaved = false;}void ChildWnd::newDoc()
{static int wndSeqNum = 1;m_CurDocPath = QString("WPS 文档 %1").arg(wndSeqNum++);//设置窗体标题,文档改动后名称加'*'号标识setWindowTitle(m_CurDocPath+"[*]"+ "- MyWPS");connect(document(),SIGNAL(contentsChanged()),this,SLOT(docBeModified()));       //contentsChanged是QTextDocument对象发出的信号,而不是QTextEdit.所以此处第一参数是documwnt() (返回QTextDocument当前对象的指针)}QString ChildWnd::getCurDocName()
{return QFileInfo(m_CurDocPath).fileName();
}void ChildWnd::docBeModified()
{setWindowModified(document()->isModified());    //setWindowModified通常用在QWidget类,这个方法用来指示窗口的内容自上次保存以来是否已被修改
}
  • setAttribute 方法用于设置窗口或对话框关闭时自动删除对象,释放内存。这是一种管理内存的便捷方式,特别是在处理多个窗口或对话框时非常有用
  • contentsChanged槽方法是QTextDocument对象发出的信号,而不是QTextEdit.所以此处第一参数是document() (返回QTextDocument当前对象的指针)
  • setWindowModified方法通常用在QWidget类,这个方法用来指示窗口的内容自上次保存以来是否已被修改
  • 疑问:为什么上述代码setAttribute&setWindowModified方法无需this->呢?这是因为有隐藏式的使用this指针

Mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();void initMainWindow();void docNew();private slots:void on_newAction_triggered();private:void formatEnabled();private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <childwnd.h>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);initMainWindow();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::initMainWindow()
{//初始化字号列表项QFontDatabase fontdb;foreach(int fontsize,fontdb.standardSizes())ui->textSizeComboBox->addItem(QString::number(fontsize));QFont defFont;          //当前应用程序默认字体QString sFontSize;int defFontSize;        //当前应用程序默认字体字号int defFontindex;       //当前字号在组合框中的索引号defFont = QApplication::font();defFontSize = defFont.pointSize();sFontSize = QString::number(defFontSize);defFontindex = ui->textSizeComboBox->findText(sFontSize);ui->textSizeComboBox->setCurrentIndex(defFontindex);
}void MainWindow::docNew()
{ChildWnd *childwnd = new ChildWnd;ui->mdiArea->addSubWindow(childwnd);connect(childwnd,SIGNAL(copyAvailable(bool)),ui->Cut_Action,SLOT(setEnabled(bool)));        //childwnd对象会发出copyAvailable的信号,而此信号的bool会决定setEnabled的bool是true/false.connect(childwnd,SIGNAL(copyAvailable(bool)),ui->Copy_Action,SLOT(setEnabled(bool)));       //写成connect(childwnd, &ChildWnd::copyAvailable, ui->Copy_Action, &QAction::setEnabled);childwnd->newDoc();childwnd->show();formatEnabled();
}void MainWindow::formatEnabled()        //启用一组与文本格式化相关的操作
{   ui->BoldAction->setEnabled(true);       //setEnabled在Qt中同时是一个普通的成员函数和一个可以用作槽的函数ui->ItalicAction->setEnabled(true);     //QT里面定义的public slot槽方法可以作为响应信号的槽,也可以作为普通的类方法被调用ui->Underline_Action->setEnabled(true);ui->leftAlignAction->setEnabled(true);ui->CentreAction->setEnabled(true);ui->RightAction->setEnabled(true);ui->justifyAction->setEnabled(true);ui->ColorAction->setEnabled(true);
}void MainWindow::on_newAction_triggered()
{docNew();
}
  • connect(childwnd,SIGNAL(copyAvailable(bool)),ui->Cut_Action,SLOT(setEnabled(bool))); childwnd对象会发出copyAvailable的信号,而此信号的bool会决定setEnabled的bool是true/false.
  • 上面代码也可写成connect(childwnd, &ChildWnd::copyAvailable, ui->Copy_Action, &QAction::setEnabled);

子窗口管理

设置图标,.pro文件添加RC_ICONS += images/wps.ico

QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgets
RC_ICONS += images/wps.ico

设置窗体标题

在这里插入图片描述

Mainwindow.h

``````
private slots:void on_newAction_triggered();void refreshMenus();void addSubWndListMenu();void on_closeAction_triggered();void on_closeAllAction_triggered();void on_titleAction_triggered();void on_cascadeAction_triggered();void on_nextAction_triggered();void on_previousAction_triggered();void setActiveSubWindow(QWidget* wnd);protected:void closeEvent(QCloseEvent *event);private:void formatEnabled();ChildWnd *activateChildWnd();private:Ui::MainWindow *ui;QSignalMapper* m_WndMapper;     //信号映射器
};#endif // MAINWINDOW_H

MainWindow.cpp

#include <childwnd.h>
#include <QMdiSubWindow>
#include <QCloseEvent>
``````void MainWindow::initMainWindow()
{``````ui->textSizeComboBox->setCurrentIndex(defFontindex);//设置多文档滚动条ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);refreshMenus();connect(ui->mdiArea,&QMdiArea::subWindowActivated,this,&MainWindow::refreshMenus);  //信号是当用户激活(选择或切换)到其中一个子窗口时,调用槽函数addSubWndListMenu();connect(ui->menu_W,&QMenu::aboutToShow,this,&MainWindow::addSubWndListMenu);    //在ui界面右键'窗体'选项就可以看到该选项名字为'menu_W'//点击窗体后就会发射信号,addSubWndListMenu槽函数会被调用//创建信号映射器m_WndMapper = new QSignalMapper(this);		//信号映射器connect(m_WndMapper,SIGNAL(mapped(QWidget*)),this,SLOT(setActiveSubWindow(QWidget*)));}
void MainWindow::on_newAction_triggered()
{docNew();
}void MainWindow::refreshMenus()
{bool hasChild = false;hasChild = (activateChildWnd() != 0);ui->SaveAction->setEnabled(hasChild);ui->SaveAsAction->setEnabled(hasChild);ui->PrintAction->setEnabled(hasChild);ui->PrintPreAction->setEnabled(hasChild);ui->Paste_Action->setEnabled(hasChild);ui->closeAction->setEnabled(hasChild);ui->closeAllAction->setEnabled(hasChild);ui->titleAction->setEnabled(hasChild);ui->cascadeAction->setEnabled(hasChild);ui->nextAction->setEnabled(hasChild);ui->previousAction->setEnabled(hasChild);//文档打开且有内容选中bool hasSelect = (activateChildWnd() && activateChildWnd()->textCursor().hasSelection());ui->Cut_Action->setEnabled(hasSelect);ui->Copy_Action->setEnabled(hasSelect);ui->BoldAction->setEnabled(hasSelect);ui->ItalicAction->setEnabled(hasSelect);ui->Underline_Action->setEnabled(hasSelect);ui->leftAlignAction->setEnabled(hasSelect);ui->RightAction->setEnabled(hasSelect);ui->justifyAction->setEnabled(hasSelect);ui->ColorAction->setEnabled(hasSelect);}
void MainWindow::addSubWndListMenu()
{ui->menu_W->clear();                        //清除所有操作ui->menu_W->addAction(ui->closeAction);ui->menu_W->addAction(ui->closeAllAction);ui->menu_W->addSeparator();ui->menu_W->addAction(ui->titleAction);ui->menu_W->addAction(ui->cascadeAction);ui->menu_W->addSeparator();ui->menu_W->addAction(ui->nextAction);ui->menu_W->addAction(ui->previousAction);QList<QMdiSubWindow*> wnds = ui->mdiArea->subWindowList();      //把所有的subWindow都加进QList容器里if(!wnds.isEmpty()) ui->menu_W->addSeparator();					//menu_W在ui界面右键可以查看当前menu名称,然后对这个menu_W菜单加上separator分割窗for(int i =0; i<wnds.size(); i++){ChildWnd* childwnd = qobject_cast<ChildWnd*>(wnds.at(i)->widget());	//类型转换QString menuitem_text;menuitem_text = QString("%1 %2").arg(i+1).arg(childwnd->getCurDocName());QAction *menuitem_act = ui->menu_W->addAction(menuitem_text);menuitem_act->setCheckable(true);menuitem_act->setChecked(childwnd == activateChildWnd());connect(menuitem_act,SIGNAL(triggered(bool)),m_WndMapper,SLOT(map()));m_WndMapper->setMapping(menuitem_act,wnds.at(i));      //第一参数为信号源对象,第二参数为希望传递给 QSignalMapper 的 mapped() 信号的参数//信号映射器通常需要两个connect函数,//第一个 connect: 连接不同的信号源到 QSignalMapper 的 map() 槽。//第二个 connect: 连接 QSignalMapper 的 mapped() 信号到实际的槽函数。}formatEnabled();}void MainWindow::on_closeAction_triggered()
{ui->mdiArea->closeActiveSubWindow();
}void MainWindow::on_closeAllAction_triggered()
{ui->mdiArea->closeAllSubWindows();
}void MainWindow::on_titleAction_triggered()
{ui->mdiArea->tileSubWindows();
}void MainWindow::on_cascadeAction_triggered()
{ui->mdiArea->cascadeSubWindows();
}void MainWindow::on_nextAction_triggered()
{ui->mdiArea->activateNextSubWindow();
}void MainWindow::on_previousAction_triggered()
{ui->mdiArea->activatePreviousSubWindow();
}void MainWindow::setActiveSubWindow(QWidget *wnd)
{if(!wnd) return;ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(wnd));
}void MainWindow::closeEvent(QCloseEvent *event)
{ui->mdiArea->closeAllSubWindows();if(ui->mdiArea->currentSubWindow())event->ignore();    //忽略此事件elseevent->accept();    //接受此事件
}
  • bool hasSelect = (activateChildWnd() && activateChildWnd()->textCursor().hasSelection()); 这行代码表示 文档打开且有内容选中

  • ChildWnd* childwnd = qobject_cast<ChildWnd*>(wnds.at(i)->widget()); 这个代码表示了类型转换, 其中wnds是装有多个QMdiSubWindow的容器,而实际的子窗口是通过widget()函数返回的,这个函数返回的是一个指向QWidget的指针

  • qobject_cast可以直接将指针转换为目标类型,只要目标类型是源类型的子类或派生类,无需进行中间转换。

  • 信号映射器QSignalMapper通常需要两个connect函数,

    • 第一个 connect: 连接不同的信号源到 QSignalMappermap() 槽。

      connect(menuitem_act,SIGNAL(triggered(bool)),m_WndMapper,SLOT(map()));

    • 第二个 connect: 连接 QSignalMapper 的 mapped() 信号到实际的槽函数。

      connect(m_WndMapper,SIGNAL(mapped(QWidget*)),this,SLOT(setActiveSubWindow(QWidget*)));

  • 通常需要使用信号映射器时,需要new 一个QSignalMapper对象,并且在谅解不同信号到QSignalmapper的Map槽函数时需要

    • m_WndMapper->setMapping(menuitem_act,wnds.at(i)); 第一参数为信号源对象,第二参数为希望传递给 QSignalMapper 的 mapped() 信号的参数
  • void MainWindow::closeEvent(QCloseEvent *event) 中的 QCloseEvent类是继承自QEvent,并且是一个特定类型的事件对象,当一个窗口(如QWidget或其子类)即将关闭时,Qt会发出这个事件

打开文档

ChildWnd.h添加声明

``````public:bool loadDoc(const QString& docName);void setCurDoc(const QString& docName);

ChildWnd.cpp添加定义

bool ChildWnd::loadDoc(const QString &docName)
{if(!docName.isEmpty()){QFile file(docName);if(!file.exists()) return false;if(!file.open(QFile::ReadOnly)) return false;QByteArray text = file.readAll();if(Qt::mightBeRichText(text))setHtml(text);elsesetPlainText(text);setCurDoc(docName);connect(document(),SIGNAL(contentsChanged()),this,SLOT(docBeModified()));}
}void ChildWnd::setCurDoc(const QString &docName)
{//canonicalFilePath()返回标准名称路径,可过滤"."m_CurDocPath = QFileInfo(docName).canonicalFilePath();m_bSaved = true;                        //文档已被保存document()->setModified(false);           //文档未改动setWindowModified(false);               //窗口不显示改动标识setWindowTitle(getCurDocName() + "[*]");  //设置子窗口标题
}
  • file.open()方法用于打开文件。这个方法的参数是一个枚举值QIODevice::OpenModeFlag,用于指定打开文件的模式
    • 里面可以带入ReadOnly, WriteOnly, ReadWrite 枚举值
  • QByteArray text = file.readAll();此行代码readAll()方法会返回一个QByteArray参数.其中QByteArray可以存储和表示任何二进制数据,这使得它可以用于读取任意类型的文件内容,包括文本文件和二进制文件
  • if(Qt::mightBeRichText(text)) 此Qt静态函数若点开的话该带入一个QString参数,但为什么上面代码带入QByteArray也可以呢?
    • 这是因为Qt 提供了灵活的转换机制,使得某些函数可以接受不同但相关的参数类型。这是通过隐式构造函数实现的
    • QString(const QByteArray &);这个构造函数可以让 QByteArray 隐式地转换为 QString。因此,当一个函数接受 QString 作为参数时,你可以传入一个 QByteArray,它会自动转换为 QString。
  • setHtmlsetPlainText 方法源自于QTextEdit,也就是ChildWnd的基类
  • m_CurDocPath = QFileInfo(docName).canonicalFilePath(); docName是一个QString类型参数,需要带入进QFileInfo来使QFileInfo的构造函数创建一个QFileInfo对象然后再调用canonicalFilePath()方法返回一个文件的规范路径 (消除了路径中的冗余部分(如 ... 等))
  • QTextEdit::document() 返回的 QTextDocument 对象是与该 QTextEdit 小部件关联的文本文档对象。每个 QTextEdit 实例都有一个独立的 QTextDocument 对象,用于存储和管理该编辑器中的文本内容及其格式化信息。

Mainwindow.h

``````
public:
void docOpen();
````````private:
QMdiSubWindow *findChildWnd(const QString& docName);
```````private slots:
void on_OpenAction_triggered();

MainWindow.cpp

#include <QFileDialog>void MainWindow::docOpen()
{QString docName = QFileDialog::getOpenFileName(this,"Open the file","","Text Document(*.txt);;HTML File(*.html *.htm);;" "All Files(*.*)");if(!docName.isEmpty()){QMdiSubWindow *existWnd = findChildWnd(docName);if(existWnd){ui->mdiArea->setActiveSubWindow(existWnd);return;}ChildWnd *childWnd = new ChildWnd;ui->mdiArea->addSubWindow(childWnd);connect(childWnd,SIGNAL(copyAvailable(bool)),ui->Cut_Action,SLOT(setEnabled(bool)));connect(childWnd,SIGNAL(copyAvailable(bool)),ui->Copy_Action,SLOT(setEnabled(bool)));if(childWnd->loadDoc(docName)){statusBar()->showMessage("Document is opened",3000);childWnd->show();formatEnabled();}else{childWnd->close();}}}QMdiSubWindow *MainWindow::findChildWnd(const QString &docName)
{QString strFile = QFileInfo(docName).canonicalFilePath();foreach(QMdiSubWindow* subWnd, ui->mdiArea->subWindowList()){ChildWnd* childWnd = qobject_cast<ChildWnd*>(subWnd->widget());if(childWnd->m_CurDocPath == strFile) return subWnd;}return 0;
}void MainWindow::on_OpenAction_triggered()
{docOpen();
}
  • QString docName = QFileDialog::getOpenFileName(this,"Open the file","","Text Document(*.txt);;HTML File(*.html *.htm);;" "All Files(*.*)"); 这个文档对话框过滤文档类型时需使用符号;; 分隔不同的文档类型
  • statusBar()->showMessage("Document is opened",3000); statusBarQMainWindow自带的方法,QMainWindow 提供了一个默认的状态栏,您可以通过 statusBar() 方法访问

文档保存

ChildWnd.h添加声明

``````
public:
bool saveDoc();
bool saveAsDoc();
bool saveDocOpt(QString docName);private:
bool promptSave();

ChildWnd.cpp添加定义

bool ChildWnd::saveDoc()
{if(m_bSaved) return saveDocOpt(m_CurDocPath);else saveAsDoc();
}bool ChildWnd::saveAsDoc()
{QString docName = QFileDialog::getSaveFileName(this,"Save as...",m_CurDocPath,"HTML doc (*.html);;""All files(*.*)");if(docName.isEmpty())   return false;else return saveDocOpt(docName);}bool ChildWnd::saveDocOpt(QString docName)
{if(!(docName.endsWith(".htm",Qt::CaseInsensitive)||docName.endsWith(".html",Qt::CaseInsensitive))){docName += ".html";}QTextDocumentWriter writer(docName);bool isSuccess = writer.write(this->document());if(isSuccess) setCurDoc(docName);return isSuccess;
}void ChildWnd::closeEvent(QCloseEvent *event)
{if (promptSave())event->accept();elseevent->ignore();
}bool ChildWnd::promptSave()
{if(!document()->isModified()) return true;QMessageBox::StandardButton result;result = QMessageBox::warning(this,"System Hint",QString("Your document%1 changed, do you want to save?").arg(getCurDocName()),(QMessageBox::Yes | QMessageBox:: Discard | QMessageBox::No));if (result == QMessageBox::Yes)return saveDoc();else if(result == QMessageBox::No)return false;return true;
}
  • QTextDocumentWrite 类 是 Qt 框架中用于将 QTextDocument(文本文档)对象保存到外部文件的类。
  • write 方法用于将 QTextDocument 对象的数据写入到指定的文件中
    • 通常使用方法是先声明一个QTextDocumentWriter对象,然后再对该对象调用write方法保存文档

MainWindow.h添加声明:

``````
public:void docSave();void docSaveAs();
``````
private slots:void on_SaveAction_triggered();void on_SaveAsAction_triggered();

MainWindow.cpp添加定义

void MainWindow::docSave()
{if(activateChildWnd() && activateChildWnd()->saveDoc()){statusBar()->showMessage("Save completed", 3000);}
}void MainWindow::docSaveAs()
{if(activateChildWnd() && activateChildWnd()->saveAsDoc()){statusBar()->showMessage("Sucessfully save",3000);}
}void MainWindow::on_SaveAction_triggered()
{docSave();
}void MainWindow::on_SaveAsAction_triggered()
{docSaveAs();
}

文档操作

MainWindow.h添加声明

``````
public:void docUndo();void docRedo();void docPaste();void docCut();void docCopy();
``````
private slots:void on_UndoAction_triggered();void on_Redo_Action_triggered();void on_Cut_Action_triggered();void on_Copy_Action_triggered();void on_Paste_Action_triggered();

MainWindow.cpp添加定义

void MainWindow::docUndo()
{if(activateChildWnd())activateChildWnd()->undo();
}void MainWindow::docRedo()
{if(activateChildWnd())activateChildWnd()->redo();
}void MainWindow::docPaste()
{if(activateChildWnd())activateChildWnd()->paste();
}void MainWindow::docCut()
{if(activateChildWnd())activateChildWnd()->cut();
}void MainWindow::docCopy()
{if(activateChildWnd())activateChildWnd()->copy();
}void MainWindow::on_UndoAction_triggered()
{docUndo();
}void MainWindow::on_Redo_Action_triggered()
{docRedo();
}void MainWindow::on_Cut_Action_triggered()
{docCut();
}void MainWindow::on_Copy_Action_triggered()
{docCopy();
}void MainWindow::on_Paste_Action_triggered()
{docPaste();
}

字体格式

设置加粗、倾斜、下划线菜单项可选属性。

在这里插入图片描述

ChildWnd.h添加声明

``````
public:
void setFormatOnSelectedWord(const QTextCharFormat &fmt);

ChildWnd.cpp添加定义

``````
void ChildWnd::setFormatOnSelectedWord(const QTextCharFormat &fmt)
{QTextCursor tCursor = textCursor();if(tCursor.hasSelection()) tCursor.select(QTextCursor::WordUnderCursor);tCursor.mergeCharFormat(fmt);mergeCurrentCharFormat(fmt);
}
  • textCursor方法返回一个 QTextCursor 对象,表示文本编辑器中的当前光标位置或选择
  • itCursor.hasSelection() 用于检查 QTextCursor 对象 tCursor 是否有选择范围
  • tCursor.select(QTextCursor::WordUnderCursor) 其中 select 用于选择特定范围的文本QTextCursor::WordUnderCursor 是一个枚举值,表示光标下的整个单词
  • megeCharFormat(fmt) 方法将传入的 QTextCharFormat 格式 fmt 应用于当前光标(或选择的文本)
  • mergeCurrentCharFormat(fmt); 用于将指定的字符格式 fmt 应用于当前的字符格式。它会影响后续的文本输入,即光标移动到其他地方时,新的文本会使用合并后的字符格式

MainWindow.h添加声明

``````
public:void textBold();void textItalic();void textUnderline();
private slots:void on_BoldAction_triggered();void on_ItalicAction_triggered();void on_Underline_Action_triggered();

MainWindow.cpp添加定义

``````
void MainWindow::textBold()
{QTextCharFormat fmt;fmt.setFontWeight(ui->BoldAction->isChecked()? QFont::Bold : QFont::Normal);if(activateChildWnd())activateChildWnd()->setFormatOnSelectedWord(fmt);
}void MainWindow::textItalic()
{QTextCharFormat fmt;fmt.setFontItalic(ui->ItalicAction->isChecked());if(activateChildWnd())activateChildWnd()->setFormatOnSelectedWord(fmt);
}void MainWindow::textUnderline()
{QTextCharFormat fmt;fmt.setFontUnderline(ui->Underline_Action->isChecked());if(activateChildWnd())activateChildWnd()->setFormatOnSelectedWord(fmt);
}void MainWindow::on_BoldAction_triggered()
{textBold();
}void MainWindow::on_ItalicAction_triggered()
{textItalic();
}void MainWindow::on_Underline_Action_triggered()
{textUnderline();
}
  • QTextCharFormat 是 Qt 框架中用于描述文本字符格式的类。它包含了关于文本外观的一些属性,比如字体、粗细、斜体等
  • setFontWeight()-设置文本的字体粗细(权重)
  • setFontItalic() -设置文本是否为斜体
  • setFontUnderline() - 设置文本是否带下划线

字号字体

MainWindow.h添加声明

public:
``````void textFamily(const QString& fmly);void textSize(const QString &ps);    
private slots:void on_fontComboBox_activated(const QString &arg1);void on_textSizeComboBox_activated(const QString &arg1);

MainWindow.cpp添加定义

void MainWindow::textFamily(const QString &fmly)
{QTextCharFormat fmt;fmt.setFontFamily(fmly);if(activateChildWnd())activateChildWnd()->setFormatOnSelectedWord(fmt);
}void MainWindow::textSize(const QString &ps)
{qreal pointSize = ps.toFloat();     //qreal就是double类型if(ps.toFloat() > 0){QTextCharFormat fmt;fmt.setFontPointSize(pointSize);if(activateChildWnd())activateChildWnd()->setFormatOnSelectedWord(fmt);}
}void MainWindow::on_fontComboBox_activated(const QString &arg1)
{textFamily(arg1);
}void MainWindow::on_textSizeComboBox_activated(const QString &arg1)
{textSize(arg1);
}
  • setFontFamily -设置文本的字体族(如 “Arial”, “Times New Roman” 等)
  • setFontPointSize() - 设置文本的字体大小(以点为单位)

段落对齐

ChildWnd.h添加声明

`````
public:void setAlignOfDocumentText(int aligntype);

ChildWnd添加定义

``````void ChildWnd::setAlignOfDocumentText(int aligntype)
{if(aligntype == 1)setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);else if(aligntype == 2)setAlignment(Qt::AlignRight | Qt::AlignAbsolute);else if(aligntype == 3)setAlignment(Qt::AlignCenter | Qt::AlignAbsolute);else if(aligntype == 4)setAlignment(Qt::AlignJustify);
}
  • setAlignment是QTextEditQTextDocument 类的方法.用于设置当前光标所在段落的对齐方式。如果有选择区域,则对齐方式会应用到所有被选中的段落

  • Qt::AlignAbsolute 的引入是为了确保对齐是基于绝对的左右方向,而不受布局方向的影响。当与 Qt::AlignLeftQt::AlignRight 一起使用时,它强制将对齐解释为绝对的左或右,而不考虑布局的书写方向。

MainWindow.cpp中initMainWindow方法最后添加如下代码:

``````
void MainWindow::initMainWindow()
{//保证互斥性,一次只能选择一个QActionGroup* alignGroup = new QActionGroup(this);alignGroup->addAction(ui->leftAlignAction);alignGroup->addAction(ui->RightAction);alignGroup->addAction(ui->CentreAction);alignGroup->addAction(ui->justifyAction);
}
  • QActionGroup 类可以将多个 QAction 组合在一起,形成一个动作组

MainWindow.h文件中添加声明:

void MainWindow::on_leftAlignAction_triggered()
{if(activateChildWnd())activateChildWnd()->setAlignOfDocumentText(1);
}void MainWindow::on_RightAction_triggered()
{if(activateChildWnd())activateChildWnd()->setAlignOfDocumentText(2);
}void MainWindow::on_CentreAction_triggered()
{if(activateChildWnd())activateChildWnd()->setAlignOfDocumentText(3);
}void MainWindow::on_justifyAction_triggered()
{if(activateChildWnd())activateChildWnd()->setAlignOfDocumentText(4);
}

字体颜色

MainWindow.h添加声明

public:
void textColour();private slots:
void on_ColorAction_triggered();

MainWindow.cpp添加定义

#include <QColorDialog>void MainWindow::textColour()
{if(activateChildWnd()){QColor color = QColorDialog::getColor(activateChildWnd()->textColor(),this);if(!color.isValid()) return;QTextCharFormat fmt;fmt.setForeground(color);activateChildWnd()->setFormatOnSelectedWord(fmt);QPixmap pix(16,16);pix.fill(color);ui->ColorAction->setIcon(pix);}
}void MainWindow::on_ColorAction_triggered()
{textColour();
}
  • setForeground 方法属于 QTextCharFormat 类,用于设置文本的前景色,也就是文本的颜色。

项目符号

ChildWnd.h添加声明

public:
``````void setParaStyle(int pStyle);

ChildWnd.cpp添加定义

#include <QTextBlockFormat>
#include <QTextListFormat>
#include <QtWidgets>``````
void ChildWnd::setParaStyle(int pStyle)
{QTextCursor tCursor = textCursor();QTextListFormat::Style sname;if(pStyle !=0){switch(pStyle){case 1:sname = QTextListFormat::ListDisc;  //黑色实心圆break;case 2:sname = QTextListFormat::ListCircle;    //空心圆break;case 3:sname = QTextListFormat::ListSquare;    //方形break;case 4:sname = QTextListFormat::ListDecimal;   //十进制整数break;case 5:sname = QTextListFormat::ListLowerAlpha;    //小写字母break;case 6:sname = QTextListFormat::ListUpperAlpha;    //大写字母break;case 7 :sname = QTextListFormat::ListLowerRoman;     //罗马小写break;case 8:sname  = QTextListFormat::ListUpperRoman;    //罗马大写break;default:sname = QTextListFormat::ListDisc;}tCursor.beginEditBlock();QTextBlockFormat tBlockFmt = tCursor.blockFormat();QTextListFormat tListFmt;if(tCursor.currentList()){tListFmt = tCursor.currentList()->format();}else{tListFmt.setIndent(tBlockFmt.indent() + 1);tBlockFmt.setIndent(0);tCursor.setBlockFormat(tBlockFmt);}tListFmt.setStyle(sname);tCursor.createList(tListFmt);tCursor.endEditBlock();}else{QTextBlockFormat tbfmt;tbfmt.setObjectIndex(-1);tCursor.mergeBlockFormat(tbfmt);}
}
  • beginEditBlock() - 这个方法允许在使用 QTextCursor 对文档进行编辑

    • 例子:

    • QTextEdit textEdit;QTextCursor cursor = textEdit.textCursor();cursor.beginEditBlock();  // 开始编辑块cursor.insertText("Hello, ");  // 插入文本cursor.insertText("world!");  // 插入更多文本cursor.endEditBlock();  // 结束编辑块
      
  • QTextBlockFormat类要用于设置和管理文本块(通常指段落)的格式

  • QTextListFormat类用于设置和管理有序列表(编号)和无序列表(项目符号)的属性

  • blockFormat()QTextCursor 类的一个方法,它用于获取光标当前位置的文本块(通常是一个段落)的格式

  • QTextCursor 类的 currentList() 方法用来获取光标当前所在位置的列表对象,如果存在的话。这个方法返回一个指向 QTextList 的指针

  • format() 方法是 QTextList 类的成员函数,用于获取关联列表的格式信息。这个方法返回一个 QTextListFormat 对象,它包含了定义列表样式和属性的各种设置,如列表的缩进、列表符号样式(例如圆点、数字等)、符号的对齐方式以及其他相关格式化选项。

  • setStyle() 方法通常关联于 QTextListFormat 类,用于设置列表的样式。这个方法允许你指定列表的类型,例如是否为有序列表(数字、字母等)或无序列表(项目符号等)。

  • createList() 方法用于创建列表,:该方法可以创建一个新的列表,并自动将当前光标位置的文本或新插入的文本块加入到这个列表中

  • tbfmt.setObjectIndex(-1)-setObjectIndex() 方法通常在 QTextBlockFormat 中用来关联文本块格式与特定的对象。置 objectIndex-1 可能是用来明确表示“没有任何关联对象”,或用于清除先前可能设置的任何对象关联

  • mergeBlockFormat() 方法将 tbfmt 中的格式合并到光标当前位置的文本块中。由于在 tbfmt 中只修改了 objectIndex(且设为 -1),这通常意味着这是一个格式化的重置操作,用于移除可能的特定格式设置。

MainWindow.h添加成员方法、槽函数

public:
``````void paraStyle(int nStyle);private slots:
``````void on_comboBox_activated(int index);

MainWindow.cpp添加定义

```````
void MainWindow::paraStyle(int nStyle)
{if(activateChildWnd())activateChildWnd()->setParaStyle(nStyle);
}void MainWindow::on_comboBox_activated(int index)
{paraStyle(index);
}

打印预览

项目文件添加打印支持模块

QT       += core gui
QT       += printsupport

MainWindow.h头文件声明打印、预览的成员方法,槽方法:

#include <QtPrintSupport/QPrinter>
public:
``````void docPrint();void docPrintPreview();private slots:
``````void printPreview(QPrinter* printer);void on_PrintPreAction_triggered();

MainWindow.cpp添加定义

``````
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrintPreviewDialog>void MainWindow::docPrint()
{QPrinter pter(QPrinter::HighResolution);QPrintDialog *ddlg = new QPrintDialog(&pter,this);if(activateChildWnd())ddlg->setOption(QAbstractPrintDialog::PrintSelection,true);ddlg->setWindowTitle("Print Document");ChildWnd* ChildWnd = activateChildWnd();if(ddlg->exec() == QDialog::Accepted)ChildWnd->print(&pter);delete ddlg;}void MainWindow::docPrintPreview()
{QPrinter pter;QPrintPreviewDialog preview(&pter,this);connect(&preview,SIGNAL(paintRequested(QPrinter*)),this,SLOT(printPreview(QPrinter*)));preview.exec();
}void MainWindow::on_PrintAction_triggered()
{docPrint();
}void MainWindow::printPreview(QPrinter *printer)
{activateChildWnd()->print(printer);
}void MainWindow::on_PrintPreAction_triggered()
{docPrintPreview();
}
  • ddlg->setOption(QAbstractPrintDialog::PrintSelection,true); 这行代码是用来配置打印对话框的行为的。具体来说,它设置了 QPrintDialog 对话框的一个选项,允许用户只打印选中的部分(而非整个文档)

  • exec() 方法用来以模态方式运行对话框,并在对话框关闭时返回一个整数值。这个返回值通常是 ``QDialog::AcceptedQDialog::Rejected`

  • print()QTextEdit类的一个方法,用于打印文档.

  • docPrintPreview()方法中, 需要connect(&preview,SIGNAL(paintRequested(QPrinter*)),this,SLOT(printPreview(QPrinter*))); 因为如果不执行这个函数的话预览打印对话框会跳出,但是里面会没有内容. 当 QPrintPreviewDialog 需要渲染预览时,它会发出 paintRequested 信号。这个信号与 MainWindow 类的 printPreview(QPrinter*) 槽连接。这意味着一旦信号被触发,printPreview 函数将被自动调用.而printPreview里面的 print函数并不会执行实际的打印,而是渲染到预览对话框中.

  • 所以,print函数不能直接被定义成物理打印,而是需要取决于QPrinter的对象配置,若QPrinter对象是带入到QPrintDiaglog的话就是物理打印,而带入QPrintPreviewDialog的话就是渲染预览打印.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/393241.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【优秀python大屏案例】基于python flask的前程无忧大数据岗位分析可视化大屏设计与实现

随着大数据和人工智能技术的迅猛发展&#xff0c;数据分析和可视化在各个行业中的应用越来越广泛。特别是在招聘领域&#xff0c;大数据分析不仅能够帮助企业更好地了解市场需求&#xff0c;还能为求职者提供科学的职业规划建议。本文探讨了基于Python Flask框架的前程无忧大数…

如何判断IP地址属于住宅IP还是机房IP

在数字化时代,IP地址作为互联网通信的基础标识&#xff0c;扮演着重要的角色。无论是网络管理、数据分析还是安全监控&#xff0c;正确识别IP地址的类型——尤其是区分是住宅IP还是机房IP&#xff0c;对于确保网络安全、优化网络性能以及合法合规运营具有重要意义。IPIDEA代理I…

小白入门机器学习被劝退的4大原因,你中了哪一个?

hi&#xff0c;喵老师&#x1f431;来啦。 很多小白朋友&#xff0c;尤其是准研究生、文科生&#xff0c;刚开始接触机器学习之后常常在短时间内就「入门即放弃」了。 其实背后主要的原因无非那么几个&#xff0c;今天喵老师就给大家盘一盘&#xff0c;看看你是哪一种&#x1…

BUUCTF [安洵杯 2019]easy_serialize_php 1

打开题目&#xff0c;看到一串php代码&#xff0c;试着代码审计一下&#xff0c;看一下有用信息 可以看出是通过$_SESSION[img]来读取文件 extract可以将数组中的变量导入当前变量表 也就是说我们可以伪造$_SESSION 数组中的所有数据 这里传递一个参数fphpinfo 先用hackbar进…

缺失的第一个正数

思路&#xff1a;我的初步想法是先对数组排序&#xff0c;然后找到第一个正数的位置&#xff0c;从1开始顺序比对&#xff1a;哪个没出现就是答案。 代码&#xff1a; class Solution { public:int firstMissingPositive(vector<int>& nums) {sort(nums.begin(),nums…

常见中间件漏洞复现之【Apache】!

CVE-2021-41773 Apache HTTP Server 路径穿越漏洞 漏洞简介 该漏洞是由于Apache HTTP Server 2.4.49版本存在⽬录穿越漏洞,在路径穿越⽬录 <Directory/>Require all granted</Directory>允许被访问的的情况下&#xff08;默认开启&#xff09;&#xff0c;攻击者…

WEB渗透Web突破篇-WAF绕过

SQL注入分块传输 https://github.com/c0ny1/chunked-coding-converter跑注入点被拦截使用分块传输&#xff0c;右键选择使用SQLMAP跑注入>python sqlmap.py -r 1.txt --batch --proxyhttp://127.0.0.1:8080 --dbs自动提供可用的tamper Atlas GitHub - m4ll0k/Atlas: Quick…

常见中间件漏洞复现之【Tomcat】!

Tomcat介绍 tomcat是⼀个开源⽽且免费的jsp服务器&#xff0c;默认端⼝ : 8080&#xff0c;属于轻量级应⽤服务器。它可以实现 JavaWeb程序的装载&#xff0c;是配置JSP&#xff08;Java Server Page&#xff09;和JAVA系统必备的⼀款环境。 在历史上也披露出来了很多的漏洞 …

解决windows安装docker desktop打开报错问题

下载docker windows版本: https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_sourcedocker&utm_mediumwebreferral&utm_campaigndd-smartbutton&utm_locationmodule 正常安装&#xff0c;然后运行&#xff0c;弹出这个报错: 试了…

组件设计原则

state数据结构设计 用数据描述所有内容数据要结构化&#xff0c;易于程序操作&#xff08;遍历、查找&#xff09;数据要可扩展&#xff0c;以便增加新的功能 组件设计组件通讯 从功能上拆分层次尽量让组件原子化容器组件&#xff08;只管理数据&#xff09;& UI组件&am…

非负数、0和正数 限制最大值且保留两位小数在elementpuls表单中正则验证

一、结构 <el-form-item label="单价:" prop="price"><el-inputv-model.trim="formData.price"placeholder="请输入"@blur="formMethod.fixTwo"><template #append>(元)</template></el-input…

VS项目打包成lib库并使用

一、新建一个静态库项目 一般要把项目设为Release模式 二、添加文件 将所需要打包的头文件、源文件添加到该静态库项目中 三、生成项目 生成成功后即可在Release文件夹出现找到相应的.lib文件 四、使用静态库 将静态库文件复制到项目文件夹中&#xff0c;然后在项目属性设…

C++ 几何算法 - 向量点乘,叉乘及其应用

一&#xff1a;点乘介绍 1. 向量点乘&#xff1a; 2. 向量点乘的性质&#xff1a; 3. 向量点乘公式&#xff1a; 4. 向量的点乘的属性&#xff1a; &#xff08;1&#xff09;&#xff1a;向量与自身做点乘&#xff0c;会得到向量长度的平方&#xff1a; &#xff08;2&#xf…

看门狗应用编程-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

看门狗应用编程 看门狗应用编程介绍 看门狗定时器的基本概念 看门狗是一个可以在一定时间内被复位/重置的计数器 如果在规定时间内没有复位&#xff0c;看门狗计时器溢出会对CPU产生复位信号使系统重启 有些看门狗可以只产生中断信号而不会使系统复位 I.MX6UL/I.MX6ULL So…

尚品汇-创建ES索引库(二十七)

目录&#xff1a; &#xff08;1&#xff09;商品检索功能介绍 &#xff08;2&#xff09;根据业务搭建数据结构 &#xff08;3&#xff09;nested 介绍 &#xff08;4&#xff09;搭建service-list服务 &#xff08;5&#xff09;构建实体与es mapping建立映射关系 &…

常见中间件漏洞复现之【Jboss】!

Jboss介绍 JBoss是⼀个基于J2EE的开发源代码的应⽤服务器。JBoss代码遵循LGPL许可&#xff0c;可以在任何商业应⽤中免费使⽤。JBoss是⼀个管理EJB的容器和服务器&#xff0c;⽀持EJB1.1、EJB 2.0和EJB3的规范。但JBoss核⼼服务不包括⽀持servlet/JSP的WEB容器&#xff0c;⼀般…

常见中间件漏洞复现之【WebLogic】!

Weblogic介绍 WebLogic是美国Oracle公司出品的⼀个application server&#xff0c;确切的说是⼀个基于JAVAEE架构的中间件&#xff0c;默认端⼝&#xff1a;7001 WebLogic是⽤于开发、集成、部署和管理⼤型分布式Web应⽤、⽹络应⽤和数据库应⽤的Java应⽤服务器。将Java的动态…

从C++看C#托管内存与非托管内存

进程的内存 一个exe文件&#xff0c;在没有运行时&#xff0c;其磁盘存储空间格式为函数代码段全局变量段。加载为内存后&#xff0c;其进程内存模式增加为函数代码段全局变量段函数调用栈堆区。我们重点讨论堆区。 托管堆与非托管堆 C# int a10这种代码申请的内存空间位于函…

找工作准备刷题Day21 动态规划算法 (卡尔41期训练营 8.6)

上周有些事情回了趟老家&#xff0c;祝广大博友身体健康&#xff0c;多运动。前面的贪心算法题目后面慢慢补&#xff0c;近期找到了一个实习&#xff0c;大概持续三个月&#xff0c;现在计划是白天工作&#xff0c;晚上下班以后运动运动刷题。要加强牛客网那种两小时3道题的刷题…

Zero123 论文学习

论文链接&#xff1a;https://arxiv.org/abs/2303.11328 代码链接&#xff1a;https://github.com/cvlab-columbia/zero123 解决了什么问题&#xff1f; 人类通常能够仅凭一个相机视角来想象物体的三维形状和外观。这种能力对于日常任务非常重要&#xff0c;例如物体操纵和在…