一、概述
Designer中的Graphics View部件是個圖形視圖部件,對應類為QGraphicsView,其功能不是簡單的顯示圖形,老猿認為這是一種特殊的視圖,它與QGraphicsScene配套實現了類似Model/View的架構。
本節不介紹QGraphicsView和QGraphicsScene的所有屬性、方法,大家可以參考官方文檔,另外老猿推薦《Qt繪圖之QGraphicsScene QGraphicsView QGraphicsItem詳解》供大家參考。
二、QGraphicsView功能簡介
QGraphicsView主要是用於界面顯示圖形的,顯示的內容由QGraphicsScene決定。QGraphicsView支持鼠標的拖拽、點擊、滾動等事件,可以根據滾動條策略控制滾動條的出現,提供視圖、場景的坐標映射,支持設置對齊方式。
具體屬性、方法、信號可以參考官方文檔以及上面推薦的博文,在此需要重點說明如下幾點:
- QGraphicsView默認是帶有內邊距和邊界,會導致內置於內的QGraphicsScene坐標與視圖看到的效果不一致,具體請參考《QT:QGraphicsView QGraphicsScene QGraphicsItem理解》
- QGraphicsView的坐標體系與QWidget的坐標體系相同,視口范圍需要從其viewport視口屬性獲取
- QGraphicsView的場景可以從scene()方法獲取,場景大小范圍可以從sceneRect()獲取
- QGraphicsView的默認是居中對齊的,所以如果添加顯示對象,默認是顯示在中央的
三、QGraphicsScene功能簡介
QGraphicsScene用於管理一個需要繪制的圖形對象,每個對象稱為圖元(基類為QGraphicsItem),如果理解QGraphicsScene為一個Model對象的話,QGraphicsItem就是Model中的項。
QGraphicsItem具體屬性、方法、信號可以參考官方文檔以及上面推薦的博文,在此需要重點說明如下幾點:
- QGraphicsScene的圖元類型有多種,每種圖元在添加時要調用專屬的添加方法,方法會返回對應的圖元類型對象。這些方法包括addLine()、addPath()、addPixmap()、 addRect()、 addText()、addEllipse()、addPolygon()、addSimpleText等
- QGraphicsScene的圖元都可以通過setPos方法改變其位置,但需要注意,QGraphicsScene的坐標體系與QGraphicsView不同,具體請參考前面推薦的博文
- QGraphicsScene提供了大多數的鼠標和鍵盤等事件處理虛方法,如mousePressEvent、mouseMoveEvent、mouseReleaseEvent、mouseDoubleClickEvent、keyReleaseEvent、keyPressEvent等,可以通過子類化或者動態賦值方式接管相關的事件處理,從而實現對應的處理。但需要注意的是,這些方法中鼠標的位置應該通過scenePos()來獲取,不能通過pos()來獲取,pos是僅當鼠標點擊了對應圖元的時候才有值
四、案例
4.1、案例功能說明
在案例中需要在界面上顯示如下內容:
並實現除HELLO外的部分隨鼠標點擊移動位置。上面的內容包括圖片、文字、直線、橢圓以及曲線。
4.2、界面設計
界面UI設計非常簡單,就是一個窗口中放置了一個QGraphicsView,如圖:
窗口命名為mainWin,圖形視圖命名為graphicsView。
4.3、實現界面派生類構造方法
構造方法中除了圖形界面初始化外,還將圖形視圖的內邊距和邊界去除、改變圖形視圖的對齊方式、設置場景大小和圖形視圖大小一致,並繪制圖形,同時接管圖形場景的mousePressEvent 方法。具體代碼如下:
class mainWin(QtWidgets.QWidget,ui_mainWin.Ui_mainWin):
def __init__(self):
super().__init__()
self.setupUi(self)
self.graphicsView.setStyleSheet("padding: 0px; border: 0px;")#內邊距和邊界去除
self.scene = QtWidgets.QGraphicsScene(self)
self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) #改變對齊方式
self.graphicsView.setSceneRect(0,0,self.graphicsView.viewport().width(),self.graphicsView.height()) #設置圖形場景大小和圖形視圖大小一致
self.graphicsView.setScene(self.scene)
self.addScenes() #調用繪制圖形的方法
self.scene.mousePressEvent = self.mousePressEvent #接管圖形場景的鼠標事件
4.4、實現繪制圖形的addScenes方法
def addScenes(self): #繪制圖形
originX,originY = 40,60 #坐標基點
self.itemHELLO = self.scene.addText("HELLO!") #輸出hello
self.itemHELLO.setPos(0, 0)
#繪制矩形
pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.red))
rectF = QtCore.QRectF(originX+300-8, originY-25, 20, 50)
self.elpItem = self.scene.addEllipse(rectF, pen)
# 繪制曲線
pen.setColor(QtGui.QColor(QtCore.Qt.blue))
path = QtGui.QPainterPath()
path.moveTo(originX,originY)
path.cubicTo(originX+100, originY-150, originX+200, originY+150,originX+300,originY)
myGradient = QtGui.QLinearGradient()
myFont = QtGui.QFont()
textPoint = QtCore.QPointF(originX+35,originY-4)
path.addText(textPoint, myFont, "老猿Python")
self.itemPath = self.scene.addPath(path,pen,myGradient)
#繪制下划線
pen.setColor(QtGui.QColor(QtCore.Qt.darkRed))
line = QtCore.QLineF(QtCore.QPointF(originX+190, originY-20), QtCore.QPointF(originX+275, originY-20))
self.itemLine = self.scene.addLine(line, pen)
self.itemLine.setPos(0,originY-20)
#繪制文字
self.itemText = self.scene.addText("跟老猿學Python!")
self.itemText.setPos(originX+185,originY+1)
#繪制圖片
pixmap = QtGui.QPixmap(r"F:\coffeDog\咖啡狗小圖.jpg")
self.pixmapItem = self.scene.addPixmap(pixmap)
self.pixmapItem.setPos(originX-34,originY-16)
#繪制x軸
pen.setColor(QtGui.QColor(QtCore.Qt.red))
self.xLine = self.scene.addLine(originX,originY, originX+300, originY, pen)
4.5、實現鼠標按鍵響應myMousePressEvent方法
注意這個方法不要命名為mousePressEvent,因為這樣不但會接管圖形場景的鼠標按鍵事件,而且會接管主窗口的鼠標按鍵事件,而二者的參數類型是不同的,對應屬性也不同。
def myMousePressEvent(self,mouseEvent):
print("myMousePressEvent",mouseEvent.type(),mouseEvent.scenePos())
point = mouseEvent.scenePos()
if point:
self.movePath(point) #移動相關圖元,方法單獨實現
else:print("not valid point")
4.6、實現圖元移動的movePath方法
在該方法中需要將相關圖元的位置同步移動,所以在繪制方法中記錄下來了所有圖元對象。移動圖元是參考圖片的坐標。
4.7、運行效果
廣告
老猿關於PyQt的付費專欄《使用PyQt開發圖形界面Python應用》只需要9.9元,該部分與第十五章的內容基本對應,但同樣內容在付費專欄上總體來說更詳細、案例更多。本節內容對應付費專欄的《第四十章、PyQt顯示部件:QGraphicsView圖形視圖和QGraphicsScene圖形場景簡介及應用案例
》。如果有興趣也願意支持老猿的讀者,歡迎購買付費專欄。