QGraphicsView中的PyQt位置被移位

时间:2015-05-28 13:09:21

标签: python python-2.7 pyqt pyqt4 chess

我试图用PyQt中的棋子画一个棋盘。因此,我使用的是QtGui.QMainWindow。在QMainWindow中,我放置了一个QtGui.QGridLayout,并在网格中添加了一个QtGui.QGraphicsView作为中心窗口小部件。 QGraphicsView应该将棋盘与64个瓦片和棋子保持为QtGui.QGraphicsItem。

我实现了这个,但现在我的定位有问题。似乎所有东西的位置都被移动或偏移一定量,看起来这个数量取决于QGraphicsItem的位置。瓷砖彼此不相邻,但它们之间有相同大小的瓷砖空间。当我拖放一块时(我已经覆盖了这些功能,因为我想对移动部件进行一些调整:即使鼠标离开电路板也要将它们保留在电路板上,即使抓住它也要将光标置于光标下方在角落里,看起来这件作品移动的距离加倍了。

我制作了gui的截图来说明问题。在第二张图片中,我开始在左上角拖动并标记鼠标和棋子的位置。光标和工件之间的距离随光标位置而变化。 http://i.imgur.com/Y8aJAQK.png http://i.imgur.com/EQsWioa.png

所以这是源代码,请你看看并帮助我:

chessboard.py

import sys
from board import *

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()


    def initUI(self):
        grid = QtGui.QGridLayout()
        grid.setColumnStretch(1,1)
        grid.setRowStretch(1,1)

        self.board = Board()
        grid.addWidget(self.board)

        mainWidget = QtGui.QWidget()
        mainWidget.setLayout(grid)
        self.setCentralWidget(mainWidget)

        self.setGeometry(200, 200, 800, 600)
        self.setWindowTitle('ChessBoard')
        self.show()

def main():
    app = QtGui.QApplication(sys.argv)
    m = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

board.py

from PyQt4 import QtGui, QtCore, QtSvg

SQHT = 60
WHITE, BLACK = COLORS = range(2)
LIGHT_COL = QtGui.QColor(220,225,235)
DARK_COL = QtGui.QColor(130,150,180)

class Board(QtGui.QGraphicsView):
    def __init__(self):
        super(Board, self).__init__(None)
        self.scene = QtGui.QGraphicsScene(self)
        self.setScene(self.scene)

        self.svg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Creator: CorelDRAW --> <svg    xmlns:dc="http://purl.org/dc/elements/1.1/"    xmlns:cc="http://web.resource.org/cc/"    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"    xmlns:svg="http://www.w3.org/2000/svg"    xmlns="http://www.w3.org/2000/svg"    xmlns:xlink="http://www.w3.org/1999/xlink"    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"    xml:space="preserve"    width="50mm"    height="50mm"    shape-rendering="geometricPrecision"    text-rendering="geometricPrecision"    image-rendering="optimizeQuality"    fill-rule="evenodd"    clip-rule="evenodd"    viewBox="0 0 50 50"    id="svg2"    sodipodi:version="0.32"    inkscape:version="0.45"    sodipodi:docname="bn.svg"    sodipodi:docbase="/home/fkling/2/v0.1.2reduced/PieceThemes/Merida"    inkscape:output_extension="org.inkscape.output.svg.inkscape"    sodipodi:modified="true"><metadata    id="metadata13"><rdf:RDF><cc:Work        rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type          rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs    id="defs11"><linearGradient      inkscape:collect="always"      id="linearGradient2165"><stop        style="stop-color:#ffffff;stop-opacity:1;"        offset="0"        id="stop2167" /><stop        style="stop-color:#ffffff;stop-opacity:0;"        offset="1"        id="stop2169" /></linearGradient><linearGradient      inkscape:collect="always"      xlink:href="#linearGradient2165"      id="linearGradient2171"      x1="21.253071"      y1="37.59214"      x2="77.641281"      y2="37.469292"      gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview    inkscape:window-height="625"    inkscape:window-width="944"    inkscape:pageshadow="2"    inkscape:pageopacity="0.0"    guidetolerance="10.0"    gridtolerance="10.0"    objecttolerance="10.0"    borderopacity="1.0"    bordercolor="#666666"    pagecolor="#ffffff"    id="base"    inkscape:zoom="2.2972888"    inkscape:cx="119.13229"    inkscape:cy="84.28695"    inkscape:window-x="259"    inkscape:window-y="109"    inkscape:current-layer="svg2"    showgrid="true" />  <g    id="Layer_x0020_1">   <metadata    id="CorelCorpID_0Corel-Layer" />   <path    fill="#1F1A17"    d="M26.178 9.3952c2.5993,0.1694 5.0038,0.8382 7.2221,2.0151 2.2098,1.1684 4.0979,2.6755 5.6557,4.5127 1.0922,1.287 2.1167,2.8448 3.0819,4.6652 0.9737,1.8118 1.7441,3.7422 2.3199,5.7742 0.6604,2.3707 1.0837,4.8514 1.253,7.4592 0.1778,2.5992 0.2625,5.0122 0.2625,7.2305l0 5.4017c0,0 -1.2869,0 -3.8608,0 -2.5654,0 -5.9013,0 -10.0076,0l-16.637 0c-0.1524,0 -0.2201,-0.4064 -0.2117,-1.2107 0.0085,-0.8128 0.0593,-1.4647 0.1609,-1.9643 0.0593,-0.3979 0.2201,-0.9567 0.4657,-1.6848 0.254,-0.7282 0.6604,-1.6087 1.2446,-2.6501 0.2624,-0.5334 0.889,-1.3039 1.8796,-2.3199 0.999,-1.016 2.1336,-2.2013 3.429,-3.539 0.745,-0.762 1.3208,-1.7188 1.7441,-2.8787 0.4233,-1.1515 0.6011,-2.2013 0.5334,-3.1496 -0.6096,0.4995 -1.2785,0.9059 -2.0066,1.2192 -3.5052,1.2531 -6.0452,3.0734 -7.6115,5.4525 -0.1186,0.1524 -0.4911,0.8213 -1.1176,2.0151 -0.3302,0.6265 -0.6181,1.0583 -0.8467,1.2869 -0.3133,0.3133 -0.7705,0.4911 -1.3631,0.525 -0.9229,0.0423 -1.6426,-0.398 -2.159,-1.3462 -0.6943,0.2032 -1.3124,0.2878 -1.8627,0.254 -0.9229,-0.3472 -1.5917,-0.7197 -2.0066,-1.1176 -0.8467,-0.8467 -1.3885,-1.6849 -1.651,-2.5316 -0.254,-0.8466 -0.381,-1.7526 -0.381,-2.7262 0,-1.3886 0.8551,-3.2258 2.5823,-5.5118 2.0151,-2.6247 3.0904,-4.6313 3.2174,-6.0029 0,-0.5927 0.0592,-1.2615 0.1778,-2.0066 0.1016,-0.5165 0.3048,-1.0075 0.618,-1.4901 0.2202,-0.3302 0.3641,-0.5588 0.4318,-0.6774 0.0762,-0.127 0.2117,-0.3132 0.4149,-0.5588 0.1439,-0.2032 0.2709,-0.3556 0.3725,-0.4572 0.0932,-0.11 0.2202,-0.254 0.3726,-0.4402 0.1778,-0.2117 0.4064,-0.4572 0.6942,-0.7451 -0.8805,-2.413 -1.2361,-4.9022 -1.0668,-7.4591 3.2851,1.1684 6.0537,3.0141 8.2804,5.5287 0.5504,-1.8711 1.6256,-3.3867 3.2258,-4.5381 1.3208,0.9228 2.3707,2.1505 3.1496,3.666z"    id="path6" />   <path    fill="white"    d="M 15.6878,17.7857 C 16.0519,17.5994 16.2297,17.5063 16.2297,17.5063 C 16.7292,17.3116 16.8816,16.9475 16.7038,16.4141 C 16.5091,15.923 16.1281,15.7537 15.5608,15.923 C 13.6135,16.6342 12.2673,17.9381 11.5222,19.8431 C 11.4037,20.385 11.5984,20.7575 12.1149,20.9607 C 12.6314,21.1216 12.9785,20.9438 13.1563,20.4104 C 13.2918,20.131 13.3849,19.9447 13.4526,19.8685 C 13.6389,20.0124 13.876,20.114 14.1723,20.1648 C 15.1798,20.3257 15.7725,19.8854 15.9334,18.8271 C 15.9842,18.463 15.8995,18.1159 15.6878,17.7857 L 15.6878,17.7857 z M 11.573,34.5497 C 11.6323,34.3973 11.7424,34.1772 11.8948,33.8808 C 12.1742,33.1866 12.3096,32.7717 12.3096,32.6362 C 12.2842,32.179 12.0387,31.942 11.59,31.942 C 11.2598,31.942 10.8788,32.4161 10.43,33.3559 C 10.3623,33.4914 10.2607,33.6099 10.1337,33.703 C 9.685,34.1687 9.7527,34.5582 10.3284,34.8714 L 10.3284,34.8714 C 10.8618,35.1847 11.2682,35.0831 11.573,34.5497 L 11.573,34.5497 z M 26.2034,25.3464 C 27.3634,23.8224 27.9306,22.1291 27.9137,20.2664 C 27.846,19.7161 27.5327,19.4452 26.9739,19.4452 C 26.2119,19.4452 25.9156,19.7246 26.0764,20.2834 C 26.1272,21.1978 26.0426,21.9513 25.8055,22.544 C 25.4245,23.4838 25.0012,24.1865 24.544,24.6522 C 24.29,25.1517 24.4424,25.5158 24.9927,25.7444 L 24.9927,25.7444 C 25.5176,25.9899 25.924,25.8629 26.2034,25.3464 L 26.2034,25.3464 z M 19.7264,13.2391 C 19.6502,12.6464 19.6672,12.003 19.7772,11.3087 C 18.7866,11.5034 17.8553,11.9691 16.9748,12.6972 C 16.4498,12.9766 16.3228,13.3661 16.6022,13.8656 C 16.8816,14.3736 17.2711,14.4583 17.7706,14.1112 C 18.1178,13.9249 18.4395,13.7556 18.7274,13.6032 C 19.0152,13.4423 19.3454,13.3238 19.7264,13.2391 L 19.7264,13.2391 z M 42.9759,44.6928 C 42.959,44.6928 42.9759,44.244 43.0182,43.3466 C 43.149425,40.239133 43.11367,37.125892 43.0944,34.0163 C 43.0775,31.8065 42.7812,29.6052 42.2054,27.4038 C 41.365664,24.093859 40.08136,20.919205 38.133,18.1074 C 35.498872,14.261975 31.31864,12.073755 26.8469,11.1309 C 26.973151,11.896697 26.87985,12.670913 26.9231,13.4423 C 28.5233,13.9842 30.0388,14.6615 31.4612,15.4743 C 35.702058,18.028667 37.875209,22.749659 38.6579,27.4038 C 39.929701,33.557961 39.110533,38.961296 39.4707,44.6928 L 42.9759,44.6928 L 42.9759,44.6928 z M 9.4394,30.1386 C 9.9136,29.7999 9.9644,29.4104 9.5834,28.9448 C 9.1854,28.5638 8.7536,28.5299 8.271,28.8432 C 7.2635,29.5036 6.7216,30.3756 6.6539,31.4509 C 6.6708,31.9928 7.001,32.2552 7.6276,32.2214 C 8.2202,32.1706 8.5081,31.8658 8.4912,31.2985 C 8.6266,30.7736 8.9399,30.3841 9.4394,30.1386 z "    id="path8"    style="fill-opacity:1.0;fill:url(#linearGradient2171)"    sodipodi:nodetypes="cccccccccccccccsccccccccscccccccccccccccccccccccccccccccccc" />  </g> </svg>'
        self.pieces = []
        self.bRect = QtCore.QRectF(0,0,8*SQHT,8*SQHT)
        self.RANKS = 8
        self.FILES = 8

        self.setRenderHints(
            QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing | QtGui.QPainter.SmoothPixmapTransform)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setDragMode(self.NoDrag)
        self.setInteractive(True)
        self.setTransformationAnchor(self.NoAnchor)
        self.scene.setItemIndexMethod(self.scene.NoIndex)
        self.setMouseTracking(True)
        self.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)


        self.drawBoard()

        self._drawPiece(0, 0, WHITE, self.svg)

        for piece in self.pieces:
            piece.setMovable(True)


    def isLight(self, row, col):
        return (row % 2) == (col % 2)

    def drawBoard(self):
        for col in range(self.FILES):
            for row in range(self.RANKS):
                BTile(self, row, col, LIGHT_COL if self.isLight(row, col) else DARK_COL)

    def _drawPiece(self, row, col, color, piece):
        BPiece(self, row, col, color, piece)

    def getBRect(self):
        return self.bRect


class BoardElement(QtGui.QGraphicsItem):
    #TODO make abstract - how can I do this and keep inheritance from QGraphicsItem?
    def __init__(self, board, row, col):
        super(BoardElement, self).__init__(None)
        self.board = board
        x, y = self._rowCol2Pos(row, col)
        self.setPos(x,y)
        board.scene.addItem(self)

    def _rowCol2Pos(self, row, col):
        x = col * SQHT
        y = row * SQHT
        return x, y

    def _updatePos(self, x, y):
        self.setPos(x,y)
        self.board.scene.update()

    def _getXYOnBoardCentered(self, mx, my):
        rect = self.board.getBRect()
        dh = int(SQHT/2)
        left = mx - dh
        right = mx + dh
        top = my - dh
        bottom = my + dh
        if left < rect.left():
            x = rect.left()
        elif right > rect.right():
            x = rect.right() - SQHT
        else:
            x = mx - dh
        if top < rect.top():
            y = rect.top()
        elif bottom > rect.bottom():
            y = rect.bottom() - SQHT
        else:
            y = my - dh
        return x,y

    def _getXYOnBoard(self, mx, my):
        rect = self.board.getBRect()
        dh = int(SQHT/2)
        left = mx - dh
        right = mx + dh
        top = my - dh
        bottom = my + dh
        if left < rect.left():
            x = rect.left()
        elif right > rect.right():
            x = rect.right() - SQHT
        else:
            x = mx
        if top < rect.top():
            y = rect.top()
        elif bottom > rect.bottom():
            y = rect.bottom() - SQHT
        else:
            y = my
        return x,y


class BTile(BoardElement):
    def __init__(self, board, row, col, sqColor):
        super(BTile, self).__init__(board, row, col)
        self.sqColor = sqColor
        x, y = self._rowCol2Pos(row, col)
        self.bRect = QtCore.QRectF(x, y, SQHT, SQHT)

    def boundingRect(self):
        return self.bRect

    def paint(self, painter, option, widget):
        painter.setPen(self.sqColor)
        painter.setBrush(self.sqColor)
        painter.drawRect(self.bRect)


class BPiece(BoardElement):
    def __init__(self, board, row, col, color, piece):
        super(BPiece, self).__init__(board, row, col)
        self.color = color
        self.piece = piece
        self.svg = piece
        self.pixmap = QtSvg.QSvgRenderer(QtCore.QByteArray(self.svg))
        self._updateBRect()
        self.movable = False
        self.setAcceptHoverEvents(True)
        self.setZValue(2)
        x, y = self._rowCol2Pos(row, col)
        self.setPos(x,y)
        board.pieces.append(self)

    def _updateBRect(self):
        self.bRect = QtCore.QRectF(self.pos().x(), self.pos().y(), SQHT, SQHT)

    def boundingRect(self):
        self._updateBRect()
        return self.bRect

    def paint(self, painter, option, widget):
        self._updateBRect()
        self.pixmap.render(painter, self.bRect)

    def setMovable(self, movable):
        self.movable = movable
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, self.movable)

    def hoverMoveEvent(self, event):
        if self.movable:
            self.setCursor(QtCore.Qt.OpenHandCursor)
            self.setFocus()

    def mousePressEvent(self, event):
        QtGui.QGraphicsItem.mousePressEvent(self, event)
        self.setCursor(QtCore.Qt.ClosedHandCursor)
        self.setZValue(3)

    def mouseMoveEvent(self, event):
        pos = event.scenePos()
        x,y = self._getXYOnBoardCentered(pos.x(), pos.y())
        self._updatePos(x,y)

    def mouseReleaseEvent(self, event):
        self.setZValue(2)
        p = event.pos()
        bx,by = self._getXYOnBoard(p.x(), p.y())
        x = (bx // SQHT) * SQHT
        y = (by // SQHT) * SQHT
        self._updatePos(x,y)

0 个答案:

没有答案