用鼠标画画活动策划
QPaint with mouse Event panning
我创建了一个绘画小部件,我想用手形图标工具实现一个平移事件,这在很多软件中都很常见。它是当用户按下鼠标按钮并按住它然后在 Qpainter canvas
范围内移动时,绘图会跟随鼠标移动。我找不到如何在 PyQt5 中执行此操作。
视觉示例
当前屏幕:
需要的屏幕事件:
代码:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 1200, 600))
self.paint = Paint()
self.sizeHint()
self.lay = QtWidgets.QVBoxLayout()
self.lay.addWidget(self.paint)
self.setLayout(self.lay)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self.rect().center())
painter.drawRect(r)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
感谢您的帮助并提前致谢。
代码更新:
可视化:
好吧,这就是我在中央代码中实施更新后的代码时发生的情况。
这是当用户单击并从圆形中选择部分然后在小部件中绘制时,单击后立即从矩形中选择 select 另一个部分。该小部件应更新并删除以前的绘图。但它不会那样做。在我之前的代码中,剖面图直接出现在小部件的中心,现在它粘在 canvas 的左上边缘。
部分代码:
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int,int)
def set_size_squares(self, w, h):
self._size = QtCore.QSizeF(w, h)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
self._size = QtCore.QSizeF(v, v)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
if self._type == QtGui.QRegion.Rectangle:
painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
painter.drawRect(self._rect)
elif self._type == QtGui.QRegion.Ellipse:
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.drawEllipse(self._rect)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
fm = QtGui.QFontMetrics(self.font())
r = QtCore.QRectF(QtCore.QPointF(), self._size)
r.moveCenter(QtCore.QPointF())
self._rect = QtCore.QRectF(r)
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(self._size.width()/2 + 75 ,0)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, -16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.lineTo(p)
self._path.addText(p + QtCore.QPoint(16, 0) , self.font(), "x")
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(0, -self._size.height()/2 - 75)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(16, 16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.addText(p + QtCore.QPoint(0, -16) , self.font(), "y")
if self._type == QtGui.QRegion.Rectangle:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -40))
self._path.lineTo(p+ QtCore.QPoint(0, 20))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
pt = r.topLeft() + QtCore.QPointF(-75, 0)
pb = r.bottomLeft() + QtCore.QPointF(-75, 0)
self._path.moveTo(pt)
self._path.lineTo(pb)
for p in (pt, pb):
self._path.moveTo(p+ QtCore.QPoint(40, 0))
self._path.lineTo(p+ QtCore.QPoint(-20, 0))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.height())
p = QtCore.QPointF(r.left() -80 - fm.width(word) , r.center().y() + 0.5*fm.height())
self._path.addText(p , self.font(), word)
if self._type == QtGui.QRegion.Ellipse:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -self._size.height()/2 - 20))
self._path.lineTo(p+ QtCore.QPoint(0, 10))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
要制作平底锅,您必须按照以下步骤操作:
获取mousePressEvent中的初始位置
在mouseMoveEvent中移动当前位置与初始位置的差值的矩形,并用当前位置更新初始位置。
实现如下:
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
self._rect = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
self._initial_flag = False
self._initial_pos = QtCore.QPoint()
def showEvent(self, event):
if not self._initial_flag:
# set initial pos
self._rect.moveCenter(self.rect().center())
self._initial_flag = True
super(Paint, self).showEvent(event)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
painter.drawRect(self._rect)
def mousePressEvent(self, event):
if self._rect.contains(event.pos()):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super(Paint, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self._rect.contains(event.pos()):
delta = event.pos() - self._initial_pos
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super(Paint, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(Paint, self).mouseReleaseEvent(event)
但是 Qt 已经提供了 类 允许您以简单的方式完成您指出的任务,而不是这样做,在这种情况下,它是将 QGraphicsView 与 QGraphicsItem 一起使用:
class GraphicsRectItem(QtWidgets.QGraphicsRectItem):
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
super(GraphicsRectItem, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(GraphicsRectItem, self).mouseReleaseEvent(event)
class Paint(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
rect_item = GraphicsRectItem(0, 0, 350, 250)
rect_item.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
rect_item.setPen(QtCore.Qt.darkCyan)
rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
self.scene().addItem(rect_item)
更新:
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
self._initial_flag = False
self._initial_pos = QtCore.QPoint()
self._pos = QtCore.QPoint()
def showEvent(self, event):
if not self._initial_flag:
# set initial pos
self._pos = self.rect().center()
self._initial_flag = True
super(Paint, self).showEvent(event)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
painter.drawRect(r)
def mousePressEvent(self, event):
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
if r.contains(event.pos()):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super(Paint, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
if r.contains(event.pos()):
delta = event.pos() - self._initial_pos
self._pos += delta
self._initial_pos = event.pos()
self.update()
super(Paint, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(Paint, self).mouseReleaseEvent(event)
更新:
实现任务的一种方法是有一个元素或集合连接的元素,在这种情况下它是一个 QPainterPath 加上一个 QRectF,第一个将绘制箭头、线条等,第二个绘制矩形或中心圆圈。之后,根据大小写移动那些元素就可以了。
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
if self._type == QtGui.QRegion.Rectangle:
painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
painter.drawRect(self._rect)
elif self._type == QtGui.QRegion.Ellipse:
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.drawEllipse(self._rect)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
fm = QtGui.QFontMetrics(self.font())
r = QtCore.QRectF(QtCore.QPointF(), self._size)
r.moveCenter(QtCore.QPointF())
self._rect = QtCore.QRectF(r)
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(self._size.width()/2 + 75 ,0)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, -16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.lineTo(p)
self._path.addText(p + QtCore.QPoint(16, 0) , self.font(), "x")
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(0, -self._size.height()/2 - 75)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(16, 16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.addText(p + QtCore.QPoint(0, -16) , self.font(), "y")
if self._type == QtGui.QRegion.Rectangle:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -40))
self._path.lineTo(p+ QtCore.QPoint(0, 20))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
pt = r.topLeft() + QtCore.QPointF(-75, 0)
pb = r.bottomLeft() + QtCore.QPointF(-75, 0)
self._path.moveTo(pt)
self._path.lineTo(pb)
for p in (pt, pb):
self._path.moveTo(p+ QtCore.QPoint(40, 0))
self._path.lineTo(p+ QtCore.QPoint(-20, 0))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.height())
p = QtCore.QPointF(r.left() -80 - fm.width(word) , r.center().y() + 0.5*fm.height())
self._path.addText(p , self.font(), word)
if self._type == QtGui.QRegion.Ellipse:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -self._size.height()/2 - 20))
self._path.lineTo(p+ QtCore.QPoint(0, 10))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
我创建了一个绘画小部件,我想用手形图标工具实现一个平移事件,这在很多软件中都很常见。它是当用户按下鼠标按钮并按住它然后在 Qpainter canvas
范围内移动时,绘图会跟随鼠标移动。我找不到如何在 PyQt5 中执行此操作。
视觉示例
当前屏幕:
需要的屏幕事件:
代码:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 1200, 600))
self.paint = Paint()
self.sizeHint()
self.lay = QtWidgets.QVBoxLayout()
self.lay.addWidget(self.paint)
self.setLayout(self.lay)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self.rect().center())
painter.drawRect(r)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
感谢您的帮助并提前致谢。
代码更新:
可视化:
好吧,这就是我在中央代码中实施更新后的代码时发生的情况。 这是当用户单击并从圆形中选择部分然后在小部件中绘制时,单击后立即从矩形中选择 select 另一个部分。该小部件应更新并删除以前的绘图。但它不会那样做。在我之前的代码中,剖面图直接出现在小部件的中心,现在它粘在 canvas 的左上边缘。
部分代码:
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int,int)
def set_size_squares(self, w, h):
self._size = QtCore.QSizeF(w, h)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
self._size = QtCore.QSizeF(v, v)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
if self._type == QtGui.QRegion.Rectangle:
painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
painter.drawRect(self._rect)
elif self._type == QtGui.QRegion.Ellipse:
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.drawEllipse(self._rect)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
fm = QtGui.QFontMetrics(self.font())
r = QtCore.QRectF(QtCore.QPointF(), self._size)
r.moveCenter(QtCore.QPointF())
self._rect = QtCore.QRectF(r)
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(self._size.width()/2 + 75 ,0)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, -16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.lineTo(p)
self._path.addText(p + QtCore.QPoint(16, 0) , self.font(), "x")
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(0, -self._size.height()/2 - 75)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(16, 16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.addText(p + QtCore.QPoint(0, -16) , self.font(), "y")
if self._type == QtGui.QRegion.Rectangle:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -40))
self._path.lineTo(p+ QtCore.QPoint(0, 20))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
pt = r.topLeft() + QtCore.QPointF(-75, 0)
pb = r.bottomLeft() + QtCore.QPointF(-75, 0)
self._path.moveTo(pt)
self._path.lineTo(pb)
for p in (pt, pb):
self._path.moveTo(p+ QtCore.QPoint(40, 0))
self._path.lineTo(p+ QtCore.QPoint(-20, 0))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.height())
p = QtCore.QPointF(r.left() -80 - fm.width(word) , r.center().y() + 0.5*fm.height())
self._path.addText(p , self.font(), word)
if self._type == QtGui.QRegion.Ellipse:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -self._size.height()/2 - 20))
self._path.lineTo(p+ QtCore.QPoint(0, 10))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
要制作平底锅,您必须按照以下步骤操作:
获取mousePressEvent中的初始位置
在mouseMoveEvent中移动当前位置与初始位置的差值的矩形,并用当前位置更新初始位置。
实现如下:
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
self._rect = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
self._initial_flag = False
self._initial_pos = QtCore.QPoint()
def showEvent(self, event):
if not self._initial_flag:
# set initial pos
self._rect.moveCenter(self.rect().center())
self._initial_flag = True
super(Paint, self).showEvent(event)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
painter.drawRect(self._rect)
def mousePressEvent(self, event):
if self._rect.contains(event.pos()):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super(Paint, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self._rect.contains(event.pos()):
delta = event.pos() - self._initial_pos
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super(Paint, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(Paint, self).mouseReleaseEvent(event)
但是 Qt 已经提供了 类 允许您以简单的方式完成您指出的任务,而不是这样做,在这种情况下,它是将 QGraphicsView 与 QGraphicsItem 一起使用:
class GraphicsRectItem(QtWidgets.QGraphicsRectItem):
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
super(GraphicsRectItem, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(GraphicsRectItem, self).mouseReleaseEvent(event)
class Paint(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
rect_item = GraphicsRectItem(0, 0, 350, 250)
rect_item.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
rect_item.setPen(QtCore.Qt.darkCyan)
rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
self.scene().addItem(rect_item)
更新:
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._width = 350
self._height = 250
self._initial_flag = False
self._initial_pos = QtCore.QPoint()
self._pos = QtCore.QPoint()
def showEvent(self, event):
if not self._initial_flag:
# set initial pos
self._pos = self.rect().center()
self._initial_flag = True
super(Paint, self).showEvent(event)
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setBrush(QtGui.QBrush( QtCore.Qt.cyan))
painter.setPen(QtCore.Qt.darkCyan)
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
painter.drawRect(r)
def mousePressEvent(self, event):
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
if r.contains(event.pos()):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super(Paint, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
r = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(self._width, self._height))
r.moveCenter(self._pos)
if r.contains(event.pos()):
delta = event.pos() - self._initial_pos
self._pos += delta
self._initial_pos = event.pos()
self.update()
super(Paint, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super(Paint, self).mouseReleaseEvent(event)
更新:
实现任务的一种方法是有一个元素或集合连接的元素,在这种情况下它是一个 QPainterPath 加上一个 QRectF,第一个将绘制箭头、线条等,第二个绘制矩形或中心圆圈。之后,根据大小写移动那些元素就可以了。
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
if self._type == QtGui.QRegion.Rectangle:
painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
painter.drawRect(self._rect)
elif self._type == QtGui.QRegion.Ellipse:
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
painter.drawEllipse(self._rect)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
fm = QtGui.QFontMetrics(self.font())
r = QtCore.QRectF(QtCore.QPointF(), self._size)
r.moveCenter(QtCore.QPointF())
self._rect = QtCore.QRectF(r)
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(self._size.width()/2 + 75 ,0)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, -16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.lineTo(p)
self._path.addText(p + QtCore.QPoint(16, 0) , self.font(), "x")
self._path.moveTo(QtCore.QPointF())
p = QtCore.QPointF(0, -self._size.height()/2 - 75)
self._path.lineTo(p)
self._path.lineTo(p + QtCore.QPoint(16, 16))
self._path.lineTo(p)
self._path.moveTo(p)
self._path.lineTo(p + QtCore.QPoint(-16, 16))
self._path.addText(p + QtCore.QPoint(0, -16) , self.font(), "y")
if self._type == QtGui.QRegion.Rectangle:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -40))
self._path.lineTo(p+ QtCore.QPoint(0, 20))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
pt = r.topLeft() + QtCore.QPointF(-75, 0)
pb = r.bottomLeft() + QtCore.QPointF(-75, 0)
self._path.moveTo(pt)
self._path.lineTo(pb)
for p in (pt, pb):
self._path.moveTo(p+ QtCore.QPoint(40, 0))
self._path.lineTo(p+ QtCore.QPoint(-20, 0))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.height())
p = QtCore.QPointF(r.left() -80 - fm.width(word) , r.center().y() + 0.5*fm.height())
self._path.addText(p , self.font(), word)
if self._type == QtGui.QRegion.Ellipse:
pl = r.bottomLeft() + QtCore.QPointF(0, 75)
pr = r.bottomRight() + QtCore.QPointF(0, 75)
self._path.moveTo(pl)
self._path.lineTo(pr)
for p in (pl, pr):
self._path.moveTo(p+ QtCore.QPoint(0, -self._size.height()/2 - 20))
self._path.lineTo(p+ QtCore.QPoint(0, 10))
self._path.moveTo(p+ QtCore.QPoint(10, -10))
self._path.lineTo(p+ QtCore.QPoint(-10, 10))
word = "{}".format(self._size.width())
p = QtCore.QPointF(r.center().x() - 0.5*fm.width(word) , r.bottom() + 100)
self._path.addText(p , self.font(), word)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)