Part 05 简易画板的实现(Qt)[2012.02.13]

 Part 05 简易画板的实现(Qt)

——2012.02.13


0. 本次学习Qt时主要方法:分析代码,理清实现画板功能的思路,弄清各类间的关系。
1. 编写学习笔记主要形式:展示程序功能,展示程序类的功能关系分析图,展示(经修改的)程序代码。
2. 主要参考学习资料: Qt Assistant与Qt学习之路(31)(豆子空间)。
3. 本Part内容:了解QPainter,QPointer,QEvent类的使用,认识Center Widget中功能的实现方法。

 


011 Program –paintApp(Widget)

 

01. 展示程序功能
   
程序有一工具栏,有一画板,刚开始时,画板为空,鼠标指向工具栏第二个选项,在状态栏中有“Draw a rectangle”的提示字样。
  
按下鼠标,拖动,释放,可以得出一个矩形于画板中显示,当多次画时,历史痕迹不会消去。
  
现在开始选中工具栏的第一项,Draw a Line.
  
与上次操作一样,按下鼠标,拖动,释放,可以得出一个直线于画板中显示,当然,每次所画图形如果发生重叠,新画的图形会将旧的图形覆盖。

 


02. 展示程序类的功能关系分析图
 


03. 程序代码

# MyApp.pro

TARGET = MyApp

TEMPLATE = app

SOURCES += \
    main.cpp \
    mainwindow.cpp \
    paintwidget.cpp \
    line.cpp \
    shape.cpp \
    rect.cpp

HEADERS += \
    mainwindow.h \
    paintwidget.h \
    line.h \
    shape.h \
    rect.h

RESOURCES += res.qrc


// main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.setWindowTitle(QObject::tr("Paint Application"));
    w.setWindowIcon(QIcon(":/main.png"));
    w.resize(800, 600);
    w.show();
    return app.exec();
}


// mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui>

#include "shape.h"
#include "paintwidget.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);

signals:
    void changeCurrentShape(Shape::Code newShape);

private slots:
    void drawLineActionTriggered();
    void drawRectActionTriggered();

};

#endif // MAINWINDOW_H


// PaintWidget.h

#ifndef PAINTWIDGET_H
#define PAINTWIDGET_H

#include <QtGui>
#include <QDebug>

#include "shape.h"
#include "line.h"
#include "rect.h"

class PaintWidget : public QWidget
{
    Q_OBJECT

public:
    PaintWidget(QWidget *parent = 0);

public slots:
    void setCurrentShape(Shape::Code s)
    {
        if(s != currShapeCode)
        {
            currShapeCode = s;  // 设定形状
        }
    }

protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

private:
    Shape::Code currShapeCode;
    Shape *shape;
    bool perm;
    QList<Shape*> shapeList;
};

#endif // PAINTWIDGET_H


// shape.h

#ifndef SHAPE_H
#define SHAPE_H

#include <QtGui>

class Shape
{
public:

    enum Code
    {
        Line,
        Rect
    };

    Shape();

    void setStart(QPoint s)
    {
        start = s;
    }

    void setEnd(QPoint e)
    {
        end = e;
    }

    QPoint startPoint()
    {
        return start;
    }

    QPoint endPoint()
    {
        return end;
    }

    void virtual paint(QPainter & painter) = 0;

protected:
    QPoint start;
    QPoint end;
};

#endif // SHAPE_H


// Line.h

#ifndef LINE_H
#define LINE_H

#include "shape.h"

class Line : public Shape
{
public:
    Line();

    void paint(QPainter &painter);
};

#endif // LINE_H


// rect.h

#ifndef RECT_H
#define RECT_H

#include "shape.h"

class Rect : public Shape
{
public:
    Rect();

    void paint(QPainter &painter);
};

#endif // RECT_H


// mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
// 设置工具栏
    QToolBar *bar = this->addToolBar("Tools");
    QActionGroup *group = new QActionGroup(bar);

// 设置Line动作
    QAction *drawLineAction = new QAction("Line", bar);
    drawLineAction->setIcon(QIcon(":/line.png"));
    drawLineAction->setToolTip(tr("Draw a line."));
    drawLineAction->setStatusTip(tr("Draw a line."));
    drawLineAction->setCheckable(true);
    drawLineAction->setChecked(true);
    group->addAction(drawLineAction);

    bar->addAction(drawLineAction);

// 设置Rect动作
    QAction *drawRectAction = new QAction("Rectangle", bar);
    drawRectAction->setIcon(QIcon(":/rect.png"));
    drawRectAction->setToolTip(tr("Draw a rectangle."));
    drawRectAction->setStatusTip(tr("Draw a rectangle."));
    drawRectAction->setCheckable(true);

    group->addAction(drawRectAction);
    bar->addAction(drawRectAction);

// 设置状态栏
    QLabel *statusMsg = new QLabel;
    statusBar()->addWidget(statusMsg);

// 设置中心部件
    PaintWidget *paintWidget = new PaintWidget(this);
    setCentralWidget(paintWidget);

// 信号连接
    connect(drawLineAction, SIGNAL(triggered()), this, SLOT(drawLineActionTriggered()));
    connect(drawRectAction, SIGNAL(triggered()), this, SLOT(drawRectActionTriggered()));
    connect(this, SIGNAL(changeCurrentShape(Shape::Code)), paintWidget, SLOT(setCurrentShape(Shape::Code)));
}

void MainWindow::drawLineActionTriggered()
{
    emit changeCurrentShape(Shape::Line);   // 设定形状为线形,发射信号
}

void MainWindow::drawRectActionTriggered()
{
    emit changeCurrentShape(Shape::Rect);   // 设定形状为Rectangle矩形,发射信号
}


// paintwidget.cpp

#include "paintwidget.h"

PaintWidget::PaintWidget(QWidget *parent)
    : QWidget(parent), currShapeCode(Shape::Line), shape(NULL), perm(false)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

void PaintWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setBrush(Qt::white);
    painter.drawRect(0, 0, size().width(), size().height());
    foreach(Shape * shape, shapeList)   // 这里遍历容器可以保留历史痕迹
    {
        shape -> paint(painter);
    }
    return;
}

void PaintWidget::mousePressEvent(QMouseEvent *event)
{
    switch(currShapeCode)
    {
    case Shape::Line:
        {
            shape = new Line;
            break;
        }
    case Shape::Rect:
        {
            shape = new Rect;
            break;
        }
    }
    if(shape != NULL)
    {
        perm = false;
        shapeList << shape;
        shape -> setStart(event->pos());
        shape -> setEnd(event->pos());
    }
}

void PaintWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(shape && !perm)
    {
        shape->setEnd(event->pos());
        update(); // void QWidget::update() [slot]
        // Updates the widget unless updates are disabled or the widget is hidden.
        // This function does not cause an immediate repaint;
        // instead it schedules a paint event for processing when Qt returns to the main event loop.
        // This permits Qt to optimize for more speed and less flicker than a call to repaint() does.
        // Calling update() several times normally results in just one QWidget:paintEvent() call.
    }
}

void PaintWidget::mouseReleaseEvent(QMouseEvent *event)
{
    perm = true;
}


// shape.cpp

#include "shape.h"

Shape::Shape()
{
}


// line.cpp

#include "line.h"

Line::Line()
{
}

void Line::paint(QPainter &painter)
{
    painter.drawLine(start, end);
}


// rect.cpp

#include "rect.h"

Rect::Rect()
{
}

void Rect::paint(QPainter &painter)
{
    painter.drawRect(start.x(), start.y(),
                     end.x() - start.x(), end.y() - start.y());
}



 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值