用于在 librecad 中无限调整大小的绘画的小部件
Widget used for infinitely resizable painting in librecad
Librecad 使用了一个可以无限调整大小的小部件,您可以尽可能地放大和缩小。它使用哪个小部件?
当我绘制到一个普通的widget 时,绘制是在widget 的特定坐标处完成的。但是,我想在小部件的浮动坐标处绘制并使用固定到视口某些像素的线宽。
调整大小前:
调整大小后:
哪个小部件提供此功能?
您必须使用 QGraphicsView 和 QGraphicsScene(参见 Graphics View Framework):
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.factor = 1.2
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self.setRenderHints(
QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform
)
self.setMouseTracking(True)
self.setScene(
QtWidgets.QGraphicsScene(QtCore.QRectF(-400, -400, 800, 800), self)
)
QtWidgets.QShortcut(QtGui.QKeySequence.ZoomIn, self, activated=self.zoomIn) # Ctrl + +
QtWidgets.QShortcut(QtGui.QKeySequence.ZoomOut, self, activated=self.zoomOut) # Ctrl + -
@QtCore.pyqtSlot()
def zoomIn(self):
self.zoom(self.factor)
@QtCore.pyqtSlot()
def zoomOut(self):
self.zoom(1 / self.factor)
def zoom(self, f):
self.scale(f, f)
def drawForeground(self, painter, rect):
super(GraphicsView, self).drawForeground(painter, rect)
if not hasattr(self, "cursor_position"):
return
painter.save()
painter.setTransform(QtGui.QTransform())
pen = QtGui.QPen(QtGui.QColor("yellow"))
pen.setWidth(4)
painter.setPen(pen)
r = self.mapFromScene(rect).boundingRect()
linex = QtCore.QLine(
r.left(), self.cursor_position.y(), r.right(), self.cursor_position.y(),
)
liney = QtCore.QLine(
self.cursor_position.x(), r.top(), self.cursor_position.x(), r.bottom(),
)
for line in (linex, liney):
painter.drawLine(line)
painter.restore()
def mouseMoveEvent(self, event):
self.cursor_position = event.pos()
self.scene().update()
super(GraphicsView, self).mouseMoveEvent(event)
def wheelEvent(self, event):
angle = event.angleDelta().y()
if angle < 0:
self.zoomIn()
else:
self.zoomOut()
super(GraphicsView, self).wheelEvent(event)
if __name__ == "__main__":
import sys
import random
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
for _ in range(4):
r = QtCore.QLineF(
*random.sample(range(-200, 200), 2), *random.sample(range(50, 150), 2)
)
it = w.scene().addLine(r)
pen = QtGui.QPen(QtGui.QColor(*random.sample(range(255), 3)))
pen.setWidthF(5.0)
pen.setCosmetic(True)
it.setPen(pen)
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
Librecad 使用了一个可以无限调整大小的小部件,您可以尽可能地放大和缩小。它使用哪个小部件?
当我绘制到一个普通的widget 时,绘制是在widget 的特定坐标处完成的。但是,我想在小部件的浮动坐标处绘制并使用固定到视口某些像素的线宽。
调整大小前:
调整大小后:
哪个小部件提供此功能?
您必须使用 QGraphicsView 和 QGraphicsScene(参见 Graphics View Framework):
from PyQt5 import QtCore, QtGui, QtWidgets
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.factor = 1.2
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self.setRenderHints(
QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform
)
self.setMouseTracking(True)
self.setScene(
QtWidgets.QGraphicsScene(QtCore.QRectF(-400, -400, 800, 800), self)
)
QtWidgets.QShortcut(QtGui.QKeySequence.ZoomIn, self, activated=self.zoomIn) # Ctrl + +
QtWidgets.QShortcut(QtGui.QKeySequence.ZoomOut, self, activated=self.zoomOut) # Ctrl + -
@QtCore.pyqtSlot()
def zoomIn(self):
self.zoom(self.factor)
@QtCore.pyqtSlot()
def zoomOut(self):
self.zoom(1 / self.factor)
def zoom(self, f):
self.scale(f, f)
def drawForeground(self, painter, rect):
super(GraphicsView, self).drawForeground(painter, rect)
if not hasattr(self, "cursor_position"):
return
painter.save()
painter.setTransform(QtGui.QTransform())
pen = QtGui.QPen(QtGui.QColor("yellow"))
pen.setWidth(4)
painter.setPen(pen)
r = self.mapFromScene(rect).boundingRect()
linex = QtCore.QLine(
r.left(), self.cursor_position.y(), r.right(), self.cursor_position.y(),
)
liney = QtCore.QLine(
self.cursor_position.x(), r.top(), self.cursor_position.x(), r.bottom(),
)
for line in (linex, liney):
painter.drawLine(line)
painter.restore()
def mouseMoveEvent(self, event):
self.cursor_position = event.pos()
self.scene().update()
super(GraphicsView, self).mouseMoveEvent(event)
def wheelEvent(self, event):
angle = event.angleDelta().y()
if angle < 0:
self.zoomIn()
else:
self.zoomOut()
super(GraphicsView, self).wheelEvent(event)
if __name__ == "__main__":
import sys
import random
app = QtWidgets.QApplication(sys.argv)
w = GraphicsView()
for _ in range(4):
r = QtCore.QLineF(
*random.sample(range(-200, 200), 2), *random.sample(range(50, 150), 2)
)
it = w.scene().addLine(r)
pen = QtGui.QPen(QtGui.QColor(*random.sample(range(255), 3)))
pen.setWidthF(5.0)
pen.setCosmetic(True)
it.setPen(pen)
w.resize(640, 480)
w.show()
sys.exit(app.exec_())