Pyqt5 Qgraphicsview scaled appropriately on load

我有一些 QGraphicItems 在多个预定的 X 和 Y 坐标处加载。我有一个名为 fitInView 的函数,当用户单击按钮调用该函数时,视图的缩放效果很好,但是如果我在加载过程中尝试调用该函数,它不会按我想要的方式缩放。我相信这与我如何确定比例因子有关。当我在加载时打印出视口的宽度和高度值以及当用户单击按钮时,它们是非常不同的。

我的问题是如何让对象在加载时与用户单击按钮时的缩放比例相同。感谢您的帮助。

代码

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
from PyQt5. QtCore import *
from PyQt5. QtGui import *
from PyQt5. QtWidgets import *
import sys
from math import sqrt

class Point (QGraphicsItem ):
    def __init__ ( self , x , y ):
        super (Point , self ). __init__ ( )
        self. setFlag (QGraphicsItem. ItemIsSelectable , True )
        self. rectF = QRectF ( 0 , 0 , 30 , 30 )
        self. x =x
        self. y =y
        self._brush = QBrush (Qt. black )

    def setBrush ( self , brush ):
        self._brush = brush
        self. update ( )

    def boundingRect ( self ):
        return self. rectF

    def paint ( self , painter = None , style = None , widget = None ):
        painter. fillRect ( self. rectF , self._brush )

    def hoverMoveEvent ( self , event ):
        point = event. pos ( ). toPoint ( )
        print (point )
        QGraphicsItem. hoverMoveEvent ( self , event )

class Viewer (QGraphicsView ):
    photoClicked = pyqtSignal (QPoint )
    rectChanged = pyqtSignal (QRect )

    def __init__ ( self , parent ):
        super (Viewer , self ). __init__ (parent )
        self. rubberBand = QRubberBand (QRubberBand. Rectangle , self )
        self. setMouseTracking ( True )
        self. origin = QPoint ( )
        self. changeRubberBand = False

        self._zoom = 0
        self._empty = True
        self._scene = QGraphicsScene ( self )

        self. setTransformationAnchor (QGraphicsView. AnchorUnderMouse )
        self. setResizeAnchor (QGraphicsView. AnchorUnderMouse )
        self. setVerticalScrollBarPolicy (Qt. ScrollBarAlwaysOff )
        self. setHorizontalScrollBarPolicy (Qt. ScrollBarAlwaysOff )
        self. setFrameShape (QFrame. NoFrame )
        self. area = float ( )
        self. setPoints ( )
        self. fitInView ( )

    def setItems ( self ):
            self. data = { ‘x’: [2414943.8686 ,2417160.6592 ,2417160.6592 ,2417856.1783 ,2417054.7618 ,2416009.9966 ,2416012.5232 ,2418160.8952 ,2418160.8952 ,2416012.5232 ,2417094.7694 ,2417094.7694 ] , ‘y’: [ 10454269.7008 ,
      10454147.2672 , 10454147.2672 , 10453285.2456 , 10452556.8132 , 10453240.2808 , 10455255.8752 , 10455183.1912 , 10455183.1912 , 10455255.8752 , 10456212.5959 , 10456212.5959 ] }
            maxX = max ( self. data [ ‘x’ ] )
            minX = min ( self. data [ ‘x’ ] )
            maxY = max ( self. data [ ‘y’ ] )
            minY = min ( self. data [ ‘y’ ] )
            distance = sqrt ( (maxX-minX )** 2+ (maxY-minY )** 2 )

            self. area = QRectF (minX , minY , distance , distance )
            for i ,x in enumerate ( self. data [ ‘x’ ] ):
                x = self. data [ ‘x’ ] [i ]
                y = self. data [ ‘y’ ] [i ]
                p = Point (x ,y )
                p. setPos (x ,y )
                self._scene. addItem (p )
            self. setScene ( self._scene )

    def fitInView ( self , scale = True ):
        rect = QRectF ( self. area )
        if not rect. isNull ( ):
            self. setSceneRect (rect )

            unity = self. transform ( ). mapRect (QRectF ( 0 , 0 , 1 , 1 ) )
            self. scale ( 1 / unity. width ( ) , 1 / unity. height ( ) )
            viewrect = self. viewport ( ). rect ( )
            scenerect = self. transform ( ). mapRect (rect )
            factor = min (viewrect. width ( ) / scenerect. width ( ) ,
                             viewrect. height ( ) / scenerect. height ( ) )
            self. scale (factor , factor )
            self._zoom = 0

            print ( ‘viewrect.width: ‘+ str (viewrect. width ( ) ) )
            print ( ‘scenerect.width: ‘+ str (scenerect. width ( ) ) )
            print ( ‘viewrect.height: ‘+ str (viewrect. height ( ) ) )
            print ( ‘scenerect.height: ‘+ str (scenerect. height ( ) ) )

    def setPoints ( self ):
        self._zoom = 0
        self. setItems ( )
        self. setDragMode ( self. ScrollHandDrag )
        # self.fitInView()

    def wheelEvent ( self , event ):
            if event. angleDelta ( ). y ( ) > 0:
                factor = 1.25
                self._zoom + = 1
            else:
                factor = 0.8
                self._zoom – = 1
            if self._zoom > 0:
                self. scale (factor , factor )
            elif self._zoom == 0:
                self. fitInView ( )
            else:
                self._zoom = 0

    def mousePressEvent ( self , event ):
        if event. button ( ) == Qt. LeftButton:

            self. origin = event. pos ( )
            self. rubberBand. setGeometry (QRect ( self. origin , QSize ( ) ) )
            self. rectChanged. emit ( self. rubberBand. geometry ( ) )
            self. rubberBand. show ( )
            self. changeRubberBand = True
            return
            #QGraphicsView.mousePressEvent(self,event)
        elif event. button ( ) == Qt. MidButton:
            self. viewport ( ). setCursor (Qt. ClosedHandCursor )
            self. original_event = event
            handmade_event = QMouseEvent (QEvent. MouseButtonPress ,QPointF (event. pos ( ) ) ,Qt. LeftButton ,event. buttons ( ) ,Qt. KeyboardModifiers ( ) )
            QGraphicsView. mousePressEvent ( self ,handmade_event )

        super (Viewer , self ). mousePressEvent (event )

    def mouseReleaseEvent ( self , event ):
        if event. button ( ) == Qt. LeftButton:
            self. changeRubberBand = False
            QGraphicsView. mouseReleaseEvent ( self ,event )
        elif event. button ( ) == Qt. MidButton:
            self. viewport ( ). setCursor (Qt. OpenHandCursor )
            handmade_event = QMouseEvent (QEvent. MouseButtonRelease ,QPointF (event. pos ( ) ) ,Qt. LeftButton ,event. buttons ( ) ,Qt. KeyboardModifiers ( ) )
            QGraphicsView. mouseReleaseEvent ( self ,handmade_event )
        super (Viewer , self ). mouseReleaseEvent (event )

    def mouseMoveEvent ( self , event ):
        if self. changeRubberBand:
            self. rubberBand. setGeometry (QRect ( self. origin , event. pos ( ) ). normalized ( ) )
            self. rectChanged. emit ( self. rubberBand. geometry ( ) )
            QGraphicsView. mouseMoveEvent ( self ,event )
        super (Viewer , self ). mouseMoveEvent (event )

class Window (QWidget ):
    def __init__ ( self ):
        super (Window , self ). __init__ ( )
        self. viewer = Viewer ( self )
        self. btnLoad = QToolButton ( self )
        self. btnLoad. setText ( ‘Fit Into View’ )
        self. btnLoad. clicked. connect ( self. fitPoints )

        VBlayout = QVBoxLayout ( self )
        VBlayout. addWidget ( self. viewer )
        HBlayout = QHBoxLayout ( )
        HBlayout. setAlignment (Qt. AlignLeft )
        HBlayout. addWidget ( self. btnLoad )

        VBlayout. addLayout (HBlayout )
        self. viewer. fitInView ( )

    def fitPoints ( self ):
        self. viewer. fitInView ( )

if __name__ == ‘__main__’:
    import sys
    app = QApplication ( sys. argv )
    window = Window ( )
    window. setGeometry ( 500 , 300 , 800 , 600 )
    window. show ( )
    sys. exit (app. exec_ ( ) )


在 QGraphicsView 显示之前的瞬间,内部元素被重新计算,以便您观察到不同的行为,因此解决方案是在显示后立即应用该函数。为此,至少有 2 个选项:

1。 QTimer.singleShot(0, …):

1
2
3
4
# …
self. setPoints ( )
QTimer. singleShot ( 0 , self. fitInView )
# …

1。覆盖 Viewer

的 showEvent 方法

1
2
3
def showEvent ( self , event ):
    self. fitInView ( )
    super (Viewer , self ). showEvent (event )



相关讨论

  • 效果很好!感谢您对 QGraphicsView 内部元素的解释。
  • 哪一个对你有用..我面临同样的问题..


声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。