QT场景视图父子关系图元打印研究

在以前的一篇文章中,实现了QT场景视图的打印功能,主要经过render函数来实现,很是简单和方便。html

在实际的项目需求中,除了打印整个场景外,还须要对单个图形进行打印操做,基于item的图形能够在paint函数中打在QPrinter做为绘图设备实现打印,基于Widget的图形则提供了更方便的render函数,均可以很好地实现。可是,若是图形存在父子嵌套关系,则须要在打印该图形时,连同其子图形以及孙子图形也要一块儿打印出来,为此,本文对此进行了研究,方便参考。dom

目的:实现QT场景视图中父子关系打印ide

具体要求: 打印某图形时,打印其为根的一颗图形树;  打印左上角不留空白区域函数

主要代码,仅供参考:测试

 MyItem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
#ifndef  MYITEM_H
#define  MYITEM_H

#include  <QGraphicsItem>

class  QPainter;
class  MyItem :  public  QGraphicsItem
{
public :
    
explicit  MyItem(QGraphicsItem *parent = nullptr);
    MyItem(
const  QString &name, QGraphicsItem *parent = nullptr);

    
// custom item type
     enum  {Type = UserType +  1 };
    
// overriding bounding rect
    QRectF boundingRect()  const  override;
    
// overriding type()
     int  type()  const  override;
    
// overrriding paint()
     void  paint(QPainter *painter,
               
const  QStyleOptionGraphicsItem *option,
               QWidget *widget = nullptr) override;
    
// recursive print items
     void  printAll(QPainter *painter,     // painter
                   int  xOffset =  0 ,       // x偏移
                   int  yOffset =  0 ,       // y偏移
                   bool  root =  true );     // 是不是最顶层item

protected :
    
// overriding mouse events
     virtual   void  mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);

private :
    
// actual drawing
     void  draw(QPainter *painter,     // painter
               int  xOffset =  0 ,       // x偏移
               int  yOffset =  0         // y偏移
             );

    
// find item from full parent/child tree
     void  findInherit(MyItem *itemFind,  bool  &find);

private :
    QString     m_name;
    QColor      m_color;
    QPointF     m_scenePos;

};

#endif   // MYITEM_H

 

 MyItem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
 
#include   "MyItem.h"
#include  <QPainter>
#include  <QGraphicsScene>
#include  <QRandomGenerator>
#include  <QPrinter>
#include  <QPrintDialog>

MyItem::MyItem(QGraphicsItem *parent)
    : QGraphicsItem (parent)
    , m_name(
"" )
{
    
// radom color
    m_color.setRed(QRandomGenerator::global()->bounded( 255 ));
    m_color.setGreen(QRandomGenerator::global()->bounded(
255 ));
    m_color.setBlue(QRandomGenerator::global()->bounded(
255 ));
    
// item options
    setFlag(ItemIsMovable);
    setFlag(ItemIsSelectable);
}

MyItem::MyItem(
const  QString &name, QGraphicsItem *parent)
    : QGraphicsItem (parent)
    , m_name(name)
{
    
// radom color
    m_color.setRed(QRandomGenerator::global()->bounded( 255 ));
    m_color.setGreen(QRandomGenerator::global()->bounded(
255 ));
    m_color.setBlue(QRandomGenerator::global()->bounded(
255 ));
    
// item options
    setFlag(ItemIsMovable);
    setFlag(ItemIsSelectable);
}

QRectF MyItem::boundingRect() 
const
{
    
// outer most edges
     return  QRectF( 0 0 100 100 );
}

int  MyItem::type()  const
{
    
// Enable the use of qgraphicsitem_cast with this item.
     return  Type;
}

void  MyItem::paint(QPainter *painter,  const  QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    draw(painter);
}

void  MyItem::printAll(QPainter *painter,  int  xOffset,  int  yOffset,  bool  root)
{
    
if  (root)
    {
        
bool  bFindH =  false ;
        
bool  bFindV =  false ;
        
unsigned   int  xPos = scenePos().x();
        
unsigned   int  yPos = scenePos().y();
        
// 若是其child item不在其坐标的左上区域,则移除打印的左上角空白区域
        QRectF rectBlankH = QRectF( 0 . 0 0 . 0 , scene()->width(), scenePos().y());
        QRectF rectBlankV = QRectF(
0 . 0 0 . 0 , scenePos().x(), scene()->height());
        
// 水平区域
        QList<QGraphicsItem *> itemListH = scene()->items(rectBlankH);
        foreach (QGraphicsItem *item, itemListH)
        {
            
if  (item->type() == MyItem::Type)
            {
                MyItem *itemTmp = qgraphicsitem_cast<MyItem *>(item);
                
if  (itemTmp != nullptr)
                {
                    
bool  find =  false ;
                    findInherit(itemTmp, find);
                    
if  (find)
                    {
                        bFindH = 
true ;
                        
if  (itemTmp->m_scenePos.y() < yPos)
                        {
                            yPos = itemTmp->m_scenePos.y() < 
0  ?  0  : itemTmp->m_scenePos.y();
                        }
                    }
                }
            }
        }
        
if  (bFindH)
        {
            painter->translate(-QPointF(
0 . 0 , yPos));
        }
        
else
        {
            painter->translate(-QPointF(
0 . 0 , scenePos().y()));
        }

        
// 垂直区域
        QList<QGraphicsItem *> itemListV = scene()->items(rectBlankV);
        foreach (QGraphicsItem *item, itemListV)
        {
            
if  (item->type() == MyItem::Type)
            {
                MyItem *itemTmp = qgraphicsitem_cast<MyItem *>(item);
                
if  (itemTmp != nullptr)
                {
                    
bool  find =  false ;
                    findInherit(itemTmp, find);
                    
if  (find)
                    {
                        bFindV = 
true ;
                        
if  (itemTmp->m_scenePos.x() < xPos)
                        {
                            xPos = itemTmp->m_scenePos.x() < 
0  ?  0  : itemTmp->m_scenePos.x();
                        }
                    }
                }
            }
        }
        
if  (bFindV)
        {
            painter->translate(-QPointF(xPos, 
0 . 0 ));
        }
        
else
        {
            painter->translate(-QPointF(scenePos().x(), 
0 . 0 ));
        }
    }
    draw(painter, m_scenePos.x(), m_scenePos.y());

    QList<QGraphicsItem *> childList = childItems();
    foreach (QGraphicsItem *item, childList)
    {
        
if  (item->type() == MyItem::Type)
        {
            MyItem *myChilditem = qgraphicsitem_cast<MyItem *>(item);
            
if  (myChilditem != nullptr)
            {
                myChilditem->printAll(painter, m_scenePos.x(), m_scenePos.y(), 
false );
            }
        }
    }
}

void  MyItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
    QPrinter printer;
    QPrintDialog printDlg(&printer);
    
if  (printDlg.exec())
    {
        QPainter painter(&printer);
        QRectF rect = scene()->sceneRect();
        painter.translate(-rect.x(), -rect.y());
        printAll(&painter);
    }
}

void  MyItem::draw(QPainter *painter,  int  xOffset,  int  yOffset)
{
    QRectF rect = boundingRect();
    qreal width = rect.width();
    qreal height = rect.height();
    rect.setX(xOffset);
    rect.setY(yOffset);
    rect.setWidth(width);
    rect.setHeight(height);
    painter->drawText(rect.x() + rect.width() / 
2 ,
                      rect.y() + rect.height() / 
2 ,
                      m_name);
    QPen pen(m_color, 
2 );
    painter->setPen(pen);
    painter->drawRect(rect);

    m_scenePos = scenePos();
}

void  MyItem::findInherit(MyItem *itemFind,  bool  &find)
{
    QList<QGraphicsItem *> childList = childItems();
    
if  (childList.size() >  0 )
    {
        foreach (QGraphicsItem *item, childList)
        {
            
if  (item->type() == MyItem::type())
            {
                MyItem *itemChild = qgraphicsitem_cast<MyItem *>(item);
                
if  (itemChild != nullptr)
                {
                    
if  (itemChild == itemFind)
                    {
                        find = 
true ;
                    }
                    itemChild->findInherit(itemFind, find);
                }
            }
        }
    }
}

测试代码:this

 

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
m_view =  new  QGraphicsView( this );
m_scene = 
new  QGraphicsScene();
m_scene->setSceneRect(
0 . 0 0 . 0 800 . 0 800 . 0 );
m_view->setScene(m_scene);

// 绘制场景坐标系
QPen pen(Qt::black,  1 , Qt::DashLine);
m_scene->addLine(QLineF(-
400 . 0 0 . 0 400 0 . 0 ), pen);
m_scene->addLine(QLineF(
0 . 0 , - 400 0 . 0 400 . 0 ), pen);

// item-based
MyItem *item =  new  MyItem( "parent" );
m_scene->addItem(item);

MyItem *child1 = 
new  MyItem( "child1" );
child1->setParentItem(item);
child1->setPos(-
100 , - 100 );
m_scene->addItem(child1);

MyItem *child2 = 
new  MyItem( "child2" );
child2->setParentItem(item);
child2->setPos(
100 100 );
m_scene->addItem(child2);

MyItem *child21 = 
new  MyItem( "child21" );
child21->setParentItem(child2);
child21->setPos(
50 50 ); m_scene->addItem(child21);
相关文章
相关标签/搜索