返回

Qt学习第三天

发布时间:2023-12-13 18:12:10 220

一、QPainter绘图

1.整个绘图系统基于Qpainter,QPianterDevice和QPainEngine三个类

2.QPainter用来执行绘制的操作,QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在上面进行绘制,也就是QPainter的工作空间。

3.QPiantEngine提供了画笔(QPianter)在不同设备上绘制统一的接口。QPaintEngine类应用于QPainter和QPaintDevice之间,使用人员不必了解其细节。

可以将QPianter理解成一个画家,将QPainterDevice理解为纸张或者是屏幕。

Qt学习第三天_文件操作

4.Qt的绘图系统实际上就是使用QPianter在QPainterDevice上进行绘制,它们之间使用QPainEngine进行通讯(也就是翻译QPainter的指令)。

rectangular :矩形结构
rectangle:区域
brush:笔刷
ellipse:椭圆
setPen:设置画笔画出的边框的颜色
setBrush:设置画笔画出的区域的颜色

5.QPainter有很多以draw开头的函数,用于各种图形的绘制,比如:drawLine()、drawRect()、drawEllipse()等

6.QPainter绘图主要属性

Qpen:画笔,用来控制线条的颜色和宽度等
QBrush:画刷,用来填充颜色、渐变特性等
QFont:字体的属性,用来绘制文字时,设置文字的样式和大小等等

练习一:在窗口中设置背景图片

第一步:widget.h文件中重写绘图事件

#ifndef WIDGET_H
#define WIDGET_H

#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void paintEvent(QPaintEvent *);
//重写绘图事件 虚函数
//如果在窗口绘图,必须放在放在绘图事件里实现
//窗口需要重绘时(窗口放大缩小时),绘图事件自动调用(背景图片也作出相应的变化)
private:
Ui::Widget *ui;
};
#endif // WIDGET_H

第二步:在widget.cpp中实现绘图事件

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

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
//实例化一个画家,并将此窗口作为他的画图设备
QPixmap pix;
pix.load("../image/picture.png");
//图片放在和项目同级的文件夹中
p.drawPixmap(0,0,width(),height(),pix);
//p.darwPixmap(0.0.width(),height(),Qpixmap("../image/picture.png"));
//从原点出发,指定高度为窗口的高度,指定宽度为窗口的宽度
}
Widget::~Widget()
{
delete ui;
}

第三步:结果显示

Qt学习第三天_QPainter_02

练习二:在窗口中绘制直线、圆形和矩形、显示文字等

#ifndef WIDGET_H
#define WIDGET_H

#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
void paintEvent(QPaintEvent *);

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);
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.drawPixmap(0,0,width(),height(),QPixmap("../image/p.png"));
QPen pen;
//定义画笔
pen.setWidth(5);
pen.setColor(Qt::red);//设置颜色
//pen.setColor(QColor(14,9,23));
//rgb设置颜色
p.setPen(pen);
p.drawEllipse(40,40,100,100);
p.drawEllipse(80,80,100,100);
p.drawLine(50,80,90,40);
//从坐标点(50,80)到坐标点(90,40)
p.drawRect(180,180,50,80);
p.drawLine(500,500,80,90);
QBrush bursh;
bursh.setColor(Qt::blue);
bursh.setStyle(Qt::SolidPattern);
p.setBrush(bursh);
p.drawRect(500,500,80,90);
QFont font;
font.setPointSize(40);
font.setBold(true);
p.setFont(font);
p.drawText(600,600,QString("多云"));
}

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

Qt学习第三天_QPixmap_03

二、绘图设备(QPixmap、QImage、QBitmap、QPicture)

1.绘图设备是指继承QPainterDevice的子类。Qt一共提供了四个这样的类,分别是QPixmap、QBitmap、QImage和QPicture。

2.QPixmap专门为图像在屏幕上的显示做优化,因此他与底层显示设备息息相关,这里指的底层显示设备并不是硬件,而是操作系统所提供的原生的绘图引擎。

3.QBitmap是QPixmap的一个子类,它的色深限定为1,可以使用QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。

4.QImage专门为图像的像素级访问做了优化,是独立于硬件的绘制系统,实际上就是自己绘制自己。

5.QPicture可以记录和重现QPainter的各条命令。

三、文件操作

(QFile,QFileInfo、QDataStream、QTextStream、QBuffter)

1.Qt作为通用开发库,提供了跨平台的文件操作能力。

2.Qt通过QIODevice提供了对 I/O 设备的抽象,这些设备具有读写字节块的能力。

Qt学习第三天_QPainter_04

QIODevice:所有 I/O 设备类的父类,提供了字节块读写的通用操作以及基本接口;

QFileDevice:Qt5新增加的类,提供了有关文件操作的通用实现。

QFlie:访问本地文件或者嵌入资源;

QTemporaryFile:创建和访问本地文件系统的临时文件;

QBuffer:读写QbyteArray, 内存文件;

QProcess:运行外部程序,处理进程间通讯;

QAbstractSocket:所有套接字类的父类;

QTcpSocket:TCP协议网络数据传输;

QUdpSocket:传输 UDP 报文;

QSslSocket:使用 SSL/TLS 传输数据;

四、文件系统分类

1.顺序设备

指它们的数据只能访问一遍:从头走到尾,从第一个字节开始访问,直到最后一个字节,中途不能返回去读取上一个字节。这其中QProcess、QTcpSocket、QUdpSocket和QSslScoket是顺序访问设备。

2.随机访问设备

可以访问任意位置任意次数,还可以使用QIODevice::seek()函数来重新定位文件访问位置指针,QFile、QTemporaryFile和QBuffer是随机访问设备。

五、基本的文件操作

1.QFile提供了从文件中读取和写入的能力。通常将文件路径作为参数传给QFile的构造函数。也可以创建好对象之后,使用setFileName来修改。QFile需要使用 / 作为文件分隔符,不过,它会自动将其转换成操作系统所需要的形式。例如 C:/windows 这样的路径在 Windows 平台下同样是可以的。

QFile主要提供了有关文件的各种操作,比如打开文件、关闭文件、刷新文件等。我们可以使用QDataStream或QTextStream类来读写文件,也可以使用QIODevice类提供的read()、readLine()、readAll()以及write()这样的函数。值得注意的是,有关文件本身的信息,比如文件名、文件所在目录的名字等,则是通过QFileInfo获取,而不是自己分析文件路径字符串。

QFile提供了各种有关的文件操作,比如打开文件、关闭文件、刷新文件内等。可以使用QDataStream和QTextStream来读写文件,也可以使用QIODevice类提供的read(),readline(),readAll(),write()这样的函数。但是有关文件本身的信息,需要使用QFileInfo获取,而不是自己分析文件路径字符串。

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QFile file("in.txt");
//使用QFile创建一个文件对象,文件名为in.txt
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Open file failed.";
return -1;
//使用open函数打开这个文件,打开方式为只读
} else {
while (!file.atEnd()) {
qDebug() << file.readLine();
}
}
QFileInfo info(file);
qDebug() << info.isDir();
//该文件是否为目录
qDebug() << info.isExecutable();
//该文件是否为可执行文件
qDebug() << info.baseName();
//直接获得文件名
qDebug() << info.completeBaseName();
//获取完整的文件名
qDebug() << info.suffix();
//获取文件后缀名
qDebug() << info.completeSuffix();
//获取完整的文件后缀名
return app.exec();
}


练习三:选择文件,在QLineEdit和TextEdit中输入字符串,点击提交按钮写入到选择的文件中

//MainWindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

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

public slots:
void onFileClicked();
//选择相应的文件
void onSubmitTextClicked();
void onSubmitSerialClicked();

private:
Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H
//logger.h文件
#ifndef LOGGER_H
#define LOGGER_H

void SetLogFile(const char *name);
void LogInit();

#endif // LOGGER_H
//logger.cpp文件
#include "qdebug.h"
#include
#include
#include
#include
#include
#include
#include "mainwindow.h"
using namespace std;

static char *logfile_name = NULL;
QMutex logMutex;

void SetLogFile(const char *name)
{
logMutex.lock();
logfile_name = (char *)name;
printf("name=%s\n", logfile_name);
logMutex.unlock();
}


void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
//const QString &msg
{
if (logfile_name == NULL)
return;

QString text;
switch(type)
{
case QtDebugMsg:
text = QString("Debug:");
break;
case QtWarningMsg:
text = QString("Warning:");
break;
case QtCriticalMsg:
text = QString("Critical:");
break;
case QtFatalMsg:
text = QString("Fatal:");
break;
case QtInfoMsg:
text = QString("Info:");
}

QString context_info= QString("File:(%1) Line:(%2)").arg(QString(context.file)).arg(context.line);
QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
QString current_date = QString("(%1)").arg(current_date_time);
QString message = QString("%1 %2 %3 %4").arg(current_date).arg(context_info).arg(text).arg(msg);

logMutex.lock();
QFile file(logfile_name);
file.open(QIODevice::WriteOnly | QIODevice::Append);


QTextStream text_stream(&file);
text_stream.setCodec(QTextCodec::codecForName("utf-8"));
// QTextCodec *codec =QTextCodec::codecForName("utf-8");
// QTextCodec::setCodecForLocale(codec);
text_stream << message << "\r\n";
file.flush();

file.close();
logMutex.unlock();
}

void LogInit()
{
qInstallMessageHandler(outputMessage);
}
//mainwidow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "logger.h"

#include
#include
#include
#include
#include


MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTextCodec *codec = QTextCodec::codecForName("GDK");
ui->lineEdit_file->setEnabled(false);
//关闭写功能,只能选择文件
connect(ui->pushButton_file, &QPushButton::clicked, this, &MainWindow::onFileClicked);
connect(ui->pushButton_serial, &QPushButton::clicked, this, &MainWindow::onSubmitSerialClicked);
connect(ui->pushButton_text, &QPushButton::clicked, this, &MainWindow::onSubmitTextClicked);
}

MainWindow::~MainWindow()
{

delete ui;
}

void MainWindow::onFileClicked()
{
QString fileName = QFileDialog::getOpenFileName(
this,
tr("打开文件"),
"D:/",
tr("*.txt;;*.log"));

if (fileName.isEmpty()) {
QMessageBox::warning(this, "Warning!", "Failed to open the file!");
}
else {
ui->lineEdit_file->setText(fileName);

char *ch=fileName.toLatin1().data();
SetLogFile(ch);
// QByteArray byte = fileName.toLatin1();
// SetLogFile(byte.data());
}
}

void MainWindow::onSubmitSerialClicked()
{
QString ser = ui->lineEdit_serial->text();
qInfo("Serial = %s",qPrintable(ser));
}

void MainWindow::onSubmitTextClicked()
{
QString text = ui->textEdit_text->toPlainText();
qInfo("text = %s",qPrintable(text));
ui->textEdit_text->clear();
}
//main.cpp文件
#include "mainwindow.h"

#include

#include "logger.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;

LogInit();
SetLogFile("d://xxx.txt");
//设置默认的日志文件为xxx.txt

qDebug("test log");
qWarning("test log warnig");
w.show();
return a.exec();
}

//实现将输入的内容通过按钮添加到文本文件中
//写入到文本文件中出现乱码
//试着能不能从文件中读取到信息再添加到这个文本文件中

结果显示:

Qt学习第三天_QPainter_05

Qt学习第三天_QPixmap_06

Qt学习第三天_读写文件_07

存在的问题:写入中文字符 出现乱码,还未解决

练习四:输入ip地址,测试能否ping通

//widget.h 文件
#ifndef WIDGET_H
#define WIDGET_H

#include
#include
#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void Myping();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
//widget.cpp文件
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//使用正则表达式限制输入
ui->lineEdit_ip->setValidator(new QRegExpValidator(QRegExp("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b")));
connect(ui->pushButton_ip,&QPushButton::clicked,this,&Widget::Myping);

}

void Widget::Myping()
{
qDebug()<<QStringLiteral("开始点击");
ui->textBrowser->clear();
ui->textBrowser->setText(QStringLiteral("请等待"));
ui->textBrowser->update();
QProcess myProcess(this);
QString program = "C:/Windows/System32/cmd.exe";
QStringList arguments;
QString ipaddr;
// 正则表达式限制输入

ipaddr = ui->lineEdit_ip->text();
//用户输入的内容
QString message = "ping " + ipaddr;
//和ping命令拼接,字符串的拼接直接+链接就可
qDebug()<<message;
//将拼接后的结果在应用程序输出的位置打印一下
// 用于占位
//arguments=ui->lineEdit_ip->setInputMask("000.000.000.000; ");
//arguments <<"/c" <<"ping www.baidu.com";
arguments <<"/c" <<message;


myProcess.start(program,arguments);

while (myProcess.waitForFinished(100) == false) {
QByteArray qByteRead = myProcess.readAllStandardOutput();
if (!qByteRead.isEmpty()) {
ui->textBrowser->append(QString::fromLocal8Bit(qByteRead));
repaint();
}
}
QByteArray qByteRead = myProcess.readAllStandardOutput();
ui->textBrowser->append(QString::fromLocal8Bit(qByteRead));

qDebug()<<QString::fromLocal8Bit(qByteRead);
//输出应用程序输出上
qDebug()<<"结束点击";


}

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

结果显示:

Qt学习第三天_QPainter_08

Qt学习第三天_QPainter_09

Qt学习第三天_QPixmap_10

练习五:选择文件,然后将文件中的内容读出到文本框中

//widge.h 文件
#ifndef WIDGET_H
#define WIDGET_H

#include
#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();
void SetLogFile(const char *name);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
static char *filename = NULL;
QMutex logMutex;

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lineEdit->setEnabled(false);
connect(ui->pushButton,&QPushButton::clicked,this,
[=]()
{
QString fileName = QFileDialog::getOpenFileName(
this,
tr("打开文件"),
"D:/",
tr("*.txt;;*.log"));

if (fileName.isEmpty()) {
QMessageBox::warning(this, "Warning!", "Failed to open the file!");
}
else {
ui->lineEdit->setText(fileName);

char *ch=fileName.toLatin1().data();
SetLogFile(ch);
}
}
);
connect(ui->pushButton_r,&QPushButton::pressed,this,
[=]()
{
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Open file failed.";
return ;
} else {
while (!file.atEnd()) {

ui->textBrowser->setText(file.readAll());
}
}
});

}
void Widget::SetLogFile(const char *name)
{
logMutex.lock();
filename = (char *)name;
printf("name=%s\n", filename);
logMutex.unlock();
}

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

Qt学习第三天_读写文件_11

六、二进制文件的读写

1.QDataStream提供了基于QIODevice的二进制数据的序列化。数据流是一种二进制流。数据流是一种二进制流,这种流完全不依赖于底层操作系统、CPU 或者字节顺序(大端或小端)。

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
C语言链接和存储类型(15) 2023-12-13 15:13:22