QT:使用“状态模式”绘制界面

   QT与很多GUI库不同(如MFC),它不能随时随地地在界面上画图,只能在界面类的painterEvent中画图,如此一来,想在绘制QT界面时使用状态模式(GOF的23种设计模式之一)就有点困难了,作为解决方案,我先把要界面上的图片绘制在一张图片上(QPixmap),然后再在painterEvent中将Pixmap“画”到界面上。以下是这种方法的一个小例子。

截图:

源代码:

  1. #include <QtGui>  
  2.   
  3. //状态类的基类,定义了各个公用接口,  
  4. //其中,SetPixmap是一个纯虚接口  
  5. class BasePen  
  6. {  
  7. protected:  
  8.     //这三个类成员理应是BasePen的私有成员,然后通过接口访问  
  9.     //我这里为了方便,直接把它们设为保护成员了  
  10.     QPixmap m_Pixmap;  
  11.     QPoint m_StartPoint;  
  12.     QPoint m_EndPoint;  
  13.     virtual void SetPixmap() = 0;  
  14. public:  
  15.     BasePen()  
  16.     {   
  17.         m_StartPoint = m_EndPoint = QPoint(0, 0);  
  18.         m_Pixmap = QPixmap(500, 500);  
  19.     }  
  20.     void SetStartPoint(QPoint point) { m_StartPoint = point; }  
  21.     void SetEndPoint(QPoint point)  
  22.     {   
  23.         m_EndPoint = point;   
  24.         SetPixmap();  
  25.     }  
  26.     QPixmap GetPixmap() { return m_Pixmap; }  
  27. };  
  28.   
  29. //矩形类,在界面上画一个红色的矩形  
  30. class RectPen : public BasePen  
  31. {  
  32. protected:  
  33.     void SetPixmap()  
  34.     {  
  35.         m_Pixmap.fill(Qt::white);  
  36.         QPainter painter(&m_Pixmap);  
  37.         QRect rect(m_StartPoint, m_EndPoint);  
  38.         painter.setPen(Qt::red);  
  39.         painter.drawRect(rect);  
  40.     }  
  41. };  
  42.   
  43. //直线类,在界面上画一条蓝色的直线  
  44. class LinePen : public BasePen  
  45. {  
  46. protected:  
  47.     void SetPixmap()  
  48.     {  
  49.         m_Pixmap.fill(Qt::white);  
  50.         QPainter painter(&m_Pixmap);  
  51.         painter.setPen(Qt::blue);  
  52.         painter.drawLine(m_StartPoint, m_EndPoint);  
  53.     }  
  54. };  
  55.   
  56. //圆形类,在界面上画一个绿色的椭圆  
  57. class CirclePen : public BasePen  
  58. {  
  59. protected:  
  60.     void SetPixmap()  
  61.     {  
  62.         m_Pixmap.fill(Qt::white);  
  63.         QPainter painter(&m_Pixmap);  
  64.         QRect rect(m_StartPoint, m_EndPoint);  
  65.         painter.setPen(Qt::green);  
  66.         painter.drawEllipse(rect);  
  67.     }  
  68. };  
  69.   
  70. class Widget : public QWidget  
  71. {  
  72.     Q_OBJECT  
  73. private:  
  74.     bool m_MouseDown;  
  75.     BasePen *m_BasePen;  
  76.     RectPen *m_RectPen;  
  77.     LinePen *m_LinePen;  
  78.     CirclePen *m_CirclePen;  
  79.     //在界面上放三个按钮,用来控制画图状态  
  80.     QRadioButton *m_LineButton;  
  81.     QRadioButton *m_RectButton;  
  82.     QRadioButton *m_CircleButton;  
  83. protected:  
  84.     void mousePressEvent(QMouseEvent *event);  
  85.     void mouseMoveEvent(QMouseEvent *event);  
  86.     void mouseReleaseEvent(QMouseEvent *event);  
  87.     void paintEvent(QPaintEvent *event);  
  88. public:  
  89.     Widget(QWidget *parent = 0);  
  90.     ~Widget();  
  91.     private slots:  
  92.         void ClickedLineButton() { m_BasePen = m_LinePen; }  
  93.         void ClickedRectButton() { m_BasePen = m_RectPen; }  
  94.         void ClickedCircleButton() { m_BasePen = m_CirclePen; }  
  95. };  
  96.   
  97. Widget::Widget(QWidget *parent /* = 0 */)  
  98. : QWidget(parent)  
  99. {  
  100.     m_MouseDown = false;  
  101.     m_RectPen = new RectPen;  
  102.     m_LinePen = new LinePen;  
  103.     m_CirclePen = new CirclePen;  
  104.     m_LineButton = new QRadioButton("Line", this);  
  105.     m_RectButton = new QRadioButton("Rect", this);  
  106.     m_CircleButton = new QRadioButton("Circle", this);  
  107.     m_LineButton->move(10, 10);  
  108.     m_RectButton->move(100, 10);  
  109.     m_CircleButton->move(200, 10);  
  110.     connect(m_LineButton, SIGNAL(clicked()), this, SLOT(ClickedLineButton()));  
  111.     connect(m_RectButton, SIGNAL(clicked()), this, SLOT(ClickedRectButton()));  
  112.     connect(m_CircleButton, SIGNAL(clicked()), this, SLOT(ClickedCircleButton()));  
  113.     m_BasePen = m_LinePen;  
  114.     m_LineButton->setChecked(true);  
  115.     setFixedSize(500, 500);  
  116. }  
  117.   
  118. Widget::~Widget()  
  119. {  
  120.     delete m_LinePen;  
  121.     delete m_RectPen;  
  122.     delete m_CirclePen;  
  123. }  
  124.   
  125. void Widget::mousePressEvent(QMouseEvent *event)  
  126. {  
  127.     if( event->button() == Qt::LeftButton )  
  128.     {  
  129.         m_MouseDown = true;  
  130.         m_BasePen->SetStartPoint(event->pos());  
  131.     }  
  132. }  
  133.   
  134. void Widget::mouseMoveEvent(QMouseEvent *event)  
  135. {  
  136.     if( m_MouseDown )  
  137.     {  
  138.         m_BasePen->SetEndPoint(event->pos());  
  139.         update();  
  140.     }  
  141. }  
  142.   
  143. void Widget::mouseReleaseEvent(QMouseEvent *event)  
  144. {  
  145.     if( event->button() == Qt::LeftButton )  
  146.     {  
  147.         m_MouseDown = false;  
  148.     }  
  149. }  
  150.   
  151. void Widget::paintEvent(QPaintEvent *event)  
  152. {  
  153.     QPixmap temp = m_BasePen->GetPixmap();  
  154.     QPainter painter(this);  
  155.     painter.drawPixmap(0, 0, temp);  
  156. }  
  157.   
  158. #include "main.moc"  
  159.   
  160. int main(int argc, char **argv)  
  161. {  
  162.     QApplication app(argc, argv);  
  163.     Widget *ww = new Widget;  
  164.     ww->show();  
  165.     return app.exec();  
  166. }  

http://blog.csdn.net/small_qch/article/details/7632226

原文地址:https://www.cnblogs.com/findumars/p/4993538.html