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);
相關文章
相關標籤/搜索