2012-08-31 115 views
3

我是Python新手。我用固定的座標繪製了多邊形和圓。現在我想用鼠標將這個多邊形和圓形移動到窗口上的其他位置。請指導我如何做到這一點?Python PyQt:如何使用鼠標在窗口上移動窗口小部件?

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 

class MyFrame(QWidget): 
    def __init__(self, parent=None): 
      QWidget.__init__(self) 

    def paintEvent(self, event=None): 
      paint=QPainter(self) 
      paint.setPen(QPen(QColor(Qt.green).dark(150),1,Qt.SolidLine)) 
      segColor=QColor(Qt.green).dark(150) 
      paint.setBrush(segColor) 
      paint.setBrushOrigin(QPoint(225,225)) 
      polygon=QPolygon([QPoint(250,175), QPoint(265,175), QPoint(250,190), QPoint(265,190),QPoint(250,175)]) 
      paint.drawPolygon(polygon) 
      paint.setPen(QPen(QColor(Qt.red),1,Qt.SolidLine)) 
      paint.setBrush(QBrush(Qt.NoBrush)) 
      polygon1=QPolygon([QPoint(250,300), QPoint(250,500), QPoint(350,500), QPoint(350,300)]) 
      paint.drawPolyline(polygon1) 
      paint.drawEllipse(50,50,50,50) 


app=QApplication(sys.argv) 
f=MyFrame() 
f.show() 
app.exec_() 

回答

8

你應該看看QGraphicsView而不是你在做什麼,它已經全部內置於此。

http://doc.qt.nokia.com/4.7-snapshot/qgraphicsview.html

http://doc.qt.nokia.com/4.7-snapshot/qgraphicsscene.html

from PyQt4 import QtGui, QtCore 

class MyFrame(QtGui.QGraphicsView): 
    def __init__(self, parent = None): 
     super(MyFrame, self).__init__(parent) 

     self.setScene(QtGui.QGraphicsScene()) 

     # add some items 
     x = 0 
     y = 0 
     w = 45 
     h = 45 
     pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.green)) 
     brush = QtGui.QBrush(pen.color().darker(150)) 

     item = self.scene().addEllipse(x, y, w, h, pen, brush) 
     item.setFlag(QtGui.QGraphicsItem.ItemIsMovable) 

if (__name__ == '__main__'): 
    app = QtGui.QApplication([]) 
    f = MyFrame() 
    f.show() 
    app.exec_() 

編輯:顯示如何創建一個QPainterPath

from PyQt4 import QtGui, QtCore 

class MyFrame(QtGui.QGraphicsView): 
    def __init__(self, parent = None): 
     super(MyFrame, self).__init__(parent) 

     scene = QtGui.QGraphicsScene() 
     self.setScene(scene) 

     # add some items 
     x = 0 
     y = 0 
     w = 45 
     h = 45 
     pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.green)) 
     brush = QtGui.QBrush(pen.color().darker(150)) 

     item = scene.addEllipse(x, y, w, h, pen, brush) 
     item.setFlag(QtGui.QGraphicsItem.ItemIsMovable) 

     # create an open path 
     path = QtGui.QPainterPath() 
     path.moveTo(-w, -h) 
     path.lineTo(-w, h) 
     path.lineTo(w, h) 
     path.lineTo(w, -h) 

     clr = QtGui.QColor('blue') 
     clr.setAlpha(120) 
     brush = QtGui.QBrush(clr) 
     pen = QtGui.QPen(QtCore.Qt.NoPen) 
     fill_item = scene.addRect(-w, y, w*2, h, pen, brush) 
     path_item = scene.addPath(path) 

if (__name__ == '__main__'): 
    app = QtGui.QApplication([]) 
    f = MyFrame() 
    f.show() 
    app.exec_() 
+0

謝謝埃裏克寶貴的回覆,但這解決了我的部分問題。其實我想畫一個水槽,我覺得會使用Polyline繪製,因爲我需要三面而不是頂面。而'QGraphicsScene'對象沒有屬性'addPolyline'。其次,我想根據自己的價值來裝滿坦克。我怎樣才能填滿水箱(讓我們看看藍色)? – mrtak

+0

您可以控制場景中的對象 - 它們不必是簡單的形狀對象。我首先看看QGraphicsPathItem,它允許你定義任何要繪製的QPainterPath,並支持填充。對於比這更復雜的項目,你可以繼承任何QGraphicsItem,讓你關閉並實現自己的paintEvent方法 –

+0

Btw添加路徑的快捷方式是QGraphicsScene.addPath –

0

由Eric的回答啓發,這裏的一些代碼,通過更新其x動畫點和y座標。


from PyQt5.QtGui import QPen, QBrush, QColor 
from PyQt5.QtCore import Qt, QTimer 
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsItem, QApplication 

class GameWindow(QGraphicsView): 
    def __init__(self, parent = None): 
     super().__init__(parent) 

     self.sx = 635 
     self.sy = 475 

     scene = QGraphicsScene(0,0,self.sx,self.sy) 
     self.setScene(scene) 

     self.x = 0 
     self.y = 0 
     self.w = 30 
     self.h = 30 
     pen = QPen(QColor('dodgerblue')) 
     #pen = QPen(QColor(Qt.green)) 
     brush = QBrush(pen.color()) 
     #brush = QBrush(pen.color().darker(150)) 

     # As opposed to using QPen and QBrush, this colors the periphery only 
     #dot = scene.addEllipse(self.x, self.y, self.w, self.h, QColor('dodgerblue')) 

     self.dot = scene.addEllipse(self.x, self.y, self.w, self.h, pen, brush) 
     self.dot.setFlag(QGraphicsItem.ItemIsMovable) 


if __name__ == '__main__': 
    import sys 

    fps = 50 
    refresh_period = 1000/fps # ms 

    app = QApplication(sys.argv) 

    gw = GameWindow() 
    gw.resize(640,480) 
    gw.show() 


    # if the steps match the gw aspect ratio, the dot will move along the main diagonal, 
    # otherwise the dot will drift 
    xstep = 4 
    ystep = 3 
    #ystep = xstep * gw.sy/gw.sx 

    def moveDot(): 
     # In place of the next four lines, one can have a function 
     # or a feed from an external source to update gw.x and gw.y 
     gw.x += xstep 
     gw.x %= gw.sx 

     gw.y += ystep 
     gw.y %= gw.sy 

     gw.dot.setRect(gw.x,gw.y,gw.w,gw.h) 

    timer = QTimer() 
    timer.timeout.connect(moveDot) 

    # Comment this line out to be able to click and drag the dot 
    timer.start(refresh_period) 

    sys.exit(app.exec_())