【发布时间】:2021-12-27 13:29:27
【问题描述】:
我对这个question 有同样的问题,我发现这个answer 对这个问题很有帮助。
我已尝试运行答案中提供的代码并且它有效。
提供的answer中包含的代码:
import random
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.rect = QtCore.QRect()
self.drag_position = QtCore.QPoint()
button = QtWidgets.QPushButton("Add", self)
button.clicked.connect(self.on_clicked)
self.resize(640, 480)
@QtCore.pyqtSlot()
def on_clicked(self):
if True:
self.rect = QtCore.QRect(
QtCore.QPoint(*random.sample(range(200), 2)), QtCore.QSize(100, 100)
)
self.update()
def paintEvent(self, event):
super().paintEvent(event)
if not self.rect.isNull():
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
painter.drawEllipse(self.rect)
def mousePressEvent(self, event):
print(1)
if (
2 * QtGui.QVector2D(event.pos() - self.rect.center()).length()
< self.rect.width()
):
self.drag_position = event.pos() - self.rect.topLeft()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
print(2)
if not self.drag_position.isNull():
self.rect.moveTopLeft(event.pos() - self.drag_position)
self.update()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
print(3)
self.drag_position = QtCore.QPoint()
super().mouseReleaseEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
Rect = Window()
Rect.show()
sys.exit(app.exec_())
我的问题:
拖动时如何移动这些“点”。我的第一个想法是将QPainter 子类化并在该类中调整事件,但是当我阅读文档时,我发现没有可以移动“点”的方法。我现在真的被困在这里,我找不到正确的实现。
【问题讨论】:
-
我相信你误解了什么是QPainter:它是一个只执行绘图操作的类。它不“存储”任何东西,也不能像鼠标事件那样与用户输入交互:它就像一个“素描艺术家”,你给他们一个画布(小部件)并告诉他们要画什么。如果你想“移动点”,你必须以某种方式存储它们的数据,以便你可以访问它并修改它,并最终绘制它(通常在调用
update()之后发生)。 -
@musicamante - Ahhh,在阅读了一些笔记和文档之后,我终于明白了 QPainter 是什么。正如您所说,我需要将这些“点”放在
QRect上,然后将其位置添加到列表中。我不清楚的一件事是我怎么知道QRect是否被点击? -
如果您要在任何鼠标事件处理程序中检查它,请使用
if event.pos() in someRect:。请注意,如果您使用 PySide(更严格一点)它不会实现__contains__魔术方法(if x in y对应于y.__contains__(x)),因此您需要使用 @ 987654324@:if someRect.contains(event.pos()):。对于不涉及直接鼠标事件的任何其他情况,您需要将 当前 光标位置映射到本地坐标:pos = self.mapFromGlobal(QCursor.pos()) -
澄清我在第一条评论中写的内容:在绘画完成后不重用 QPainter 是一种很好的做法,如 docs also suggests:“记得销毁 QPainter绘制后的对象”,所以无论如何你都不应该在其中“存储”任何东西(并且使用类属性来做这件事不是一个好主意,除非你真的知道什么你正在做的)。可以“保留”并最终重用 QPainter 的特定情况很少(但根据我的经验,我并不直接需要),但对于一般用途,这是一个基本的“不要”。
-
@musicamante - 感谢您的指导!我会努力追随并记住这一点。我将尝试在上面的示例中实现这一点,看看它是否有效。谢谢!