更改矩形的 X 值实际上不会在 GUI 中移动它

Posted

技术标签:

【中文标题】更改矩形的 X 值实际上不会在 GUI 中移动它【英文标题】:Changing a rectangle's X value does not actually move it in the GUI 【发布时间】:2020-01-29 02:42:47 【问题描述】:

我正在使用 PySide2 在 Python 中开发 GUI。我有一个 GraphicsView,我将在其中放置一个图像,并且我想在该图像上绘制和移动一个多边形。我在 Python 中的 PySide、PySide2 或 PyQt 4/5 中找到了许多简单地绘制多边形、圆形等的示例。但是,我无法弄清楚为什么我的图形项目在不删除和重绘的情况下不会在事件上移动。

我正在使用键盘更改 PySide2 QRectF 上的 X 值。 X 的值明显在变化,但矩形实际上并没有移动。

这是一个最小的例子:

from PySide2 import QtCore, QtGui, QtWidgets
from functools import partial

class DebuggingDrawing(QtWidgets.QGraphicsView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # initialize the scene and set the size
        self._scene = QtWidgets.QGraphicsScene(self)
        self._scene.setSceneRect(0,0,500,500)
        self.setScene(self._scene)

        # make a green pen and draw a 10 wide, 20 high rectangle at x=20, y=30
        self.pen = QtGui.QPen(QtCore.Qt.green, 0)
        self.draw_rect = QtCore.QRectF(20, 30, 10, 20)
        # add the rectangle to our scene
        self._scene.addRect(self.draw_rect, self.pen)

    def move_rect(self, dx: int):
        # method for moving the existing rectangle
        # get the x value
        x = self.draw_rect.x()
        print('x:  dx: '.format(x, dx))
        # use the moveLeft method of QRectF to change the rectangle's left side x value
        self.draw_rect.moveLeft(x + dx)
        self.update()


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.labelImg = DebuggingDrawing()

        # Get a keyboard shortcut and hook it up to the move_rect method
        next_shortcut = QtWidgets.QShortcut(QtGui.QKeySequence('Right'), self)
        next_shortcut.activated.connect(partial(self.labelImg.move_rect, 1))

        # get the left key shortcut, move_rect one pixel left
        back_shortcut = QtWidgets.QShortcut(QtGui.QKeySequence('Left'), self)
        back_shortcut.activated.connect(partial(self.labelImg.move_rect, -1))

        self.setCentralWidget(self.labelImg)

        self.setMaximumHeight(480)
        self.update()

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    testing = MainWindow()
    testing.show()
    app.exec_()

这是输出的样子:

您显然无法在图像中看到,但即使矩形的 x 值根据我们的打印调用发生变化,图像中也没有任何移动。我已经确认这不仅仅是我的眼睛,因为如果我在move_rect 中绘制新的矩形,它们就会清楚地显示出来。

【问题讨论】:

【参考方案1】:

draw_rect 是一个QRectF 是一个输入来创建一个项目(QGraphicsRectItem),它由类似于penaddRect() 方法返回,即它获取了信息但不再使用它。这个想法是使用setPos()移动项目:

class DebuggingDrawing(QtWidgets.QGraphicsView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # initialize the scene and set the size
        self._scene = QtWidgets.QGraphicsScene(self)
        self._scene.setSceneRect(0, 0, 500, 500)
        self.setScene(self._scene)

        # make a green pen and draw a 10 wide, 20 high rectangle at x=20, y=30
        pen = QtGui.QPen(QtCore.Qt.green, 0)
        draw_rect = QtCore.QRectF(20, 30, 10, 20)
        # add the rectangle to our scene
        self.item_rect = self._scene.addRect(draw_rect, pen)

    def move_rect(self, dx: int):
        p = self.item_rect.pos()
        p += QtCore.QPointF(dx, 0)
        self.item_rect.setPos(p)

如果你仍然想使用draw_rect,那么你必须在item中重新设置它:

    self.pen = QtGui.QPen(QtCore.Qt.green, 0)
    self.draw_rect = QtCore.QRectF(20, 30, 10, 20)
    # add the rectangle to our scene
    self.item_rect = self._scene.addRect(self.draw_rect, self.pen)

def move_rect(self, dx: int):
    # method for moving the existing rectangle
    # get the x value
    x = self.draw_rect.x()
    print('x:  dx: '.format(x, dx))
    # use the moveLeft method of QRectF to change the rectangle's left side x value
    self.draw_rect.moveLeft(x + dx)
    self.item_rect.setRect(self.draw_rect)

建议阅读"Graphics View Framework" 以便QGraphicsItems、QGraphicsView 和QGraphicsScene 工作。

【讨论】:

以上是关于更改矩形的 X 值实际上不会在 GUI 中移动它的主要内容,如果未能解决你的问题,请参考以下文章

html5 canvas键盘左右移动矩形的问题

Angular 2 - 在 Promise 中更改模型时 GUI 不会更新

移动节点后,SKSpriteNode的X,Y坐标不会更改

在 PyQt 窗口中无延迟地绘制 matplotlib 矩形

使用 mouseMoveEvent 约束 QGraphicsItem 移动

重金悬赏,C#中如何更改坐标系X, Y的变化方向