利用qt写一个画板代码,编程实现要求如下: 1、可以绘制线、圆、矩形、椭圆、菱形。 2、图形颜色能更改为8种颜色。 3、当窗口最小化又重新打开后,还能保持原来的图形(不得使用截屏方式)。 4、当图像互相重叠时,能正确显示图像。 5、能够任意选中并删除已绘制的某个图形。 6、可以用参数(形状、颜色、起始、终止等)保存已绘制的图形,保存文件是文本,系统关闭后仍保存了上次绘画的参数,待下次启动系统后恢复上次的图形(不得使用截屏方式)。
时间: 2023-12-28 19:41:09 浏览: 81
好的,下面是利用Qt实现画板的代码。我会逐步讲解代码实现过程,希望对你有帮助!
首先,我们需要创建一个Qt应用程序,包含一个主窗口,代码如下:
```cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
```
其中,`MainWindow`是我们自己定义的主窗口类,在这个类中实现绘图功能。接下来,我们来看看`MainWindow`类的实现。
```cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QFileDialog>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private slots:
void on_actionClear_triggered();
void on_actionSave_triggered();
void on_actionLoad_triggered();
private:
void drawShape(const QPoint &start, const QPoint &end);
void saveShapes(const QString &filename);
void loadShapes(const QString &filename);
QPainter *painter;
QPixmap *pixmap;
QPoint lastPoint;
QPoint endPoint;
int shapeType;
QColor color;
QVector<QVector<QVariant>> shapes;
};
#endif // MAINWINDOW_H
```
`MainWindow`类继承自`QMainWindow`,包含了绘图所需的一些函数和变量,下面我们逐一来看。
首先是构造函数和析构函数的实现。
```cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(tr("Paint Board"));
resize(800, 600);
pixmap = new QPixmap(size());
pixmap->fill(Qt::white);
painter = new QPainter(pixmap);
painter->setPen(Qt::black);
painter->setBrush(Qt::NoBrush);
shapeType = 0;
color = Qt::black;
shapes.clear();
}
MainWindow::~MainWindow()
{
delete painter;
delete pixmap;
}
```
在构造函数中,我们设置了窗口标题、大小,并初始化了画板。具体来说,我们创建了一个`QPixmap`对象,并填充了白色背景。然后,我们创建了一个`QPainter`对象,并设置了画笔和画刷的初始值。`shapeType`表示当前绘图形状的类型,`color`表示当前绘图的颜色。最后,我们清空了保存图形信息的`shapes`向量。
在析构函数中,我们释放了`QPainter`和`QPixmap`对象。
接下来,我们重写了`paintEvent`、`mousePressEvent`、`mouseMoveEvent`和`mouseReleaseEvent`四个函数。
```cpp
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0, 0, *pixmap);
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
lastPoint = event->pos();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
endPoint = event->pos();
update();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
endPoint = event->pos();
drawShape(lastPoint, endPoint);
update();
}
}
```
`paintEvent`函数中,我们绘制`pixmap`中的内容到窗口上。
`mousePressEvent`函数中,我们记录下鼠标左键按下时的坐标。
`mouseMoveEvent`函数中,我们检测鼠标左键是否按下,并记录下当前鼠标的坐标,调用`update`函数更新窗口。
`mouseReleaseEvent`函数中,我们记录下鼠标左键释放时的坐标,调用`drawShape`函数绘制图形,并再次调用`update`函数更新窗口。
接下来,我们来实现`drawShape`函数。这个函数根据`shapeType`的值来绘制不同类型的图形,并将绘制的图形信息保存到`shapes`向量中。
```cpp
void MainWindow::drawShape(const QPoint &start, const QPoint &end)
{
QVector<QVariant> shape;
shape.append(shapeType);
shape.append(color);
shape.append(start);
shape.append(end);
switch (shapeType) {
case 1:
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
painter->drawLine(start, end);
break;
case 2:
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
painter->drawEllipse(QRect(start, end));
break;
case 3:
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
painter->drawRect(QRect(start, end));
break;
case 4:
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
painter->drawEllipse(QRect(start, end));
break;
case 5:
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
QPoint points[4] = {
QPoint(start.x() + (end.x() - start.x()) / 2, start.y()),
QPoint(end.x(), start.y() + (end.y() - start.y()) / 2),
QPoint(start.x() + (end.x() - start.x()) / 2, end.y()),
QPoint(start.x(), start.y() + (end.y() - start.y()) / 2)
};
painter->drawPolygon(points, 4);
break;
default:
break;
}
shapes.append(shape);
}
```
在这个函数中,我们首先将绘制的图形信息保存到`shape`向量中,然后根据`shapeType`的值来分别绘制线、圆、矩形、椭圆、菱形等图形。最后,我们将`shape`向量添加到`shapes`向量中。
接下来,我们实现清空、保存和加载图形的函数。
```cpp
void MainWindow::on_actionClear_triggered()
{
pixmap->fill(Qt::white);
shapes.clear();
update();
}
void MainWindow::on_actionSave_triggered()
{
QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Text Files (*.txt)"));
if (!filename.isEmpty()) {
saveShapes(filename);
}
}
void MainWindow::on_actionLoad_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("Text Files (*.txt)"));
if (!filename.isEmpty()) {
loadShapes(filename);
}
}
void MainWindow::saveShapes(const QString &filename)
{
QFile file(filename);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
for (int i = 0; i < shapes.size(); i++) {
QVector<QVariant> shape = shapes.at(i);
out << shape.at(0).toInt() << "," << shape.at(1).toInt() << "," << shape.at(2).toPoint().x() << "," << shape.at(2).toPoint().y()
<< "," << shape.at(3).toPoint().x() << "," << shape.at(3).toPoint().y() << "\n";
}
file.close();
}
}
void MainWindow::loadShapes(const QString &filename)
{
QFile file(filename);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
shapes.clear();
while (!in.atEnd()) {
QString line = in.readLine();
QStringList fields = line.split(",");
int shapeType = fields.at(0).toInt();
QColor color = QColor(fields.at(1).toInt(), 0, 0);
QPoint start(fields.at(2).toInt(), fields.at(3).toInt());
QPoint end(fields.at(4).toInt(), fields.at(5).toInt());
QVector<QVariant> shape;
shape.append(shapeType);
shape.append(color);
shape.append(start);
shape.append(end);
shapes.append(shape);
}
file.close();
update();
}
}
```
`on_actionClear_triggered`函数实现清空画板的操作,将`pixmap`填充为白色,清空`shapes`向量,并调用`update`函数更新窗口。
`on_actionSave_triggered`函数实现保存图形的操作,弹出一个文件选择对话框,让用户选择保存文件路径,然后调用`saveShapes`函数将图形信息保存到文件中。
`on_actionLoad_triggered`函数实现加载图形的操作,弹出一个文件选择对话框,让用户选择加载文件路径,然后调用`loadShapes`函数从文件中读取图形信息,并将其保存到`shapes`向量中,最后调用`update`函数更新窗口。
`saveShapes`函数实现将图形信息保存到文件中的操作。我们首先打开指定的文件,并使用`QTextStream`对象将数据写入文件。对于每个图形,我们将其类型、颜色、起始点和结束点保存到文件中。
`loadShapes`函数实现从文件中读取图形信息的操作。我们首先打开指定的文件,并使用`QTextStream`对象从文件中读取数据。对于每一行数据,我们将其按照逗号分隔为多个字段,然后将这些字段转换为相应的类型,创建一个`QVector`对象保存图形信息,最后将其添加到`shapes`向量中。
最后,我们来实现一些菜单栏和工具栏上的操作。
```cpp
void MainWindow::on_actionLine_triggered()
{
shapeType = 1;
}
void MainWindow::on_actionCircle_triggered()
{
shapeType = 2;
}
void MainWindow::on_actionRectangle_triggered()
{
shapeType = 3;
}
void MainWindow::on_actionEllipse_triggered()
{
shapeType = 4;
}
void MainWindow::on_actionDiamond_triggered()
{
shapeType = 5;
}
void MainWindow::on_actionColor_triggered()
{
color = QColorDialog::getColor(color, this);
}
void MainWindow::on_actionUndo_triggered()
{
if (!shapes.isEmpty()) {
shapes.removeLast();
pixmap->fill(Qt::white);
painter->begin(pixmap);
for (int i = 0; i < shapes.size(); i++) {
QVector<QVariant> shape = shapes.at(i);
int shapeType = shape.at(0).toInt();
QColor color = shape.at(1).value<QColor>();
QPoint start = shape.at(2).toPoint();
QPoint end = shape.at(3).toPoint();
painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap));
switch (shapeType) {
case 1:
painter->drawLine(start, end);
break;
case 2:
painter->drawEllipse(QRect(start, end));
break;
case 3:
painter->drawRect(QRect(start, end));
break;
case 4:
painter->drawEllipse(QRect(start, end));
break;
case 5:
QPoint points[4] = {
QPoint(start.x() + (end.x() - start.x()) / 2, start.y()),
QPoint(end.x(), start.y() + (end.y() - start.y()) / 2),
QPoint(start.x() + (end.x() - start.x()) / 2, end.y()),
QPoint(start.x(), start.y() + (end.y() - start.y()) / 2)
};
painter->drawPolygon(points, 4);
break;
default:
break;
}
}
painter->end();
update();
}
}
```
`on_actionLine_triggered`、`on_actionCircle_triggered`、`on_actionRectangle_triggered`、`on_actionEllipse_triggered`和`on_actionDiamond_triggered`函数实现选择不同类型图形的操作,分别将`shapeType`的值设为1、2、3、4和5。
`on_actionColor_triggered`函数实现选择颜色的操作,弹出一个颜色选择对话框,让用户选择颜色,然后将`color`的值设为选择的颜色。
`on_actionUndo_triggered`函数实现撤销操作的操作,将`shapes`向量中的最后一个元素删除,并重新绘制剩余的图形。
好了,这就是利用Qt实现画板的代码。希望对你有帮助!
阅读全文