如何通过拖动多边形的角来调整其大小?

2024-05-14 16:05:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我在QGraphicscene上单击鼠标保存点,将其附加到列表中,并通过循环列表创建QGraphicsPolygonItem

我使用一个定制的QGraphicscene,每当出现鼠标按下事件时,它都会发出位置信息。代码如下。(学分为SignalHelper class

class SignalHelper(QObject):
    messageSignal = QtCore.Signal(object)

class Scene(QGraphicsScene):
    def __init__(self, parent=None):
        super(Scene, self).__init__(parent)
        self.helper = SignalHelper()

    def mousePressEvent(self, event):
        self.helper.messageSignal.emit(event.scenePos())

这是我的主窗口的代码

class main_window(QWidget):
    def __init__(self):
        super().__init__()

        self.setGeometry(100, 100, 500, 500)
        self.pen = QtGui.QPen(QtGui.QColor(0,0,0))                     
        self.pen.setWidth(5)                                             

        self.view = QGraphicsView(self)
        self.scene = Scene()
        self.btn_record_points = QPushButton("Record")
        self.btn_finished = QPushButton("Finished")
        
        self.view.setSceneRect(0, 0, 500,500)
        self.view.setScene(self.scene)

        vbox = QVBoxLayout(self)
        vbox.addWidget(self.view)
        vbox.addWidget(self.btn_record_points)
        vbox.addWidget(self.btn_finished)

        self.setLayout(vbox)

        self.point_list = []
        self.record_points = False

        #Signals
        self.btn_record_points.clicked.connect(self.enable_record_points)
        self.btn_finished.clicked.connect(self.create_polygon)
        self.scene.helper.messageSignal.connect(self.draw_points)
        
    def create_polygon(self):
        # Remove ellipses
        drawn_points = self.scene.items()
        for i in drawn_points:
            self.scene.removeItem(i)

        polygon = QGraphicsPolygonItem(QtGui.QPolygonF(self.point_list))
        polygon.setFlag(QGraphicsItem.ItemIsMovable, True)
        self.scene.addItem(polygon)
        self.record_points = False
        self.point_list.clear()

    QtCore.Slot(QtCore.QPointF)
    def draw_points(self, point):
        if self.record_points == True:
            self.point_list.append(point)
            self.scene.addEllipse(point.toTuple()[0], point.toTuple()[1], 1, 1) 

    QtCore.Slot(bool)
    def enable_record_points(self):
        self.record_points = True

以下是随机多边形的示例:

GUI

关于如何使用的说明:

  1. 按“记录”按钮
  2. 在场景中单击多次
  3. 按“Finsihed”按钮

现在多边形已经创建,有没有办法通过拖动其角点来调整多边形的大小


Tags: selfviewinitdefscenerecordpointslist
1条回答
网友
1楼 · 发布于 2024-05-14 16:05:33

通过“拖动多边形的角来调整多边形的大小”我想象您想要移动多边形的点

因此,这里有一种方法

因此,首先使多边形可选择,一旦选定多边形,就在多边形的点上迭代并在每个点上绘制一个椭圆。存储椭圆、多边形、点和索引映射

现在,通过迭代映射列表来检查选择了哪个椭圆,然后使用此椭圆、多边形索引映射来更新多边形的特定点

以下是一个示例(您可以改进):

import sys
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore


class Scene(QtWidgets.QGraphicsScene):

    def __init__(self, *args, **kwargs):
        super(Scene, self).__init__(*args, **kwargs)
        self.record_points = True
        self.selected = None  # the selected polygon
        self.points_lst = []  # points that are stored when recording
        self.corner_points = []  # This contains corner point and control point mapping
        self.selected_corner = None
        self.poly_points = [] # points that are stored when resizing (You could instead reuse points_lst)

    def record(self):
        self.record_points = True

    def removeControlPoints(self):
        """ removes the control points (i,e the ellipse)"""
        for ellipse, _ in self.corner_points:
            self.removeItem(ellipse)

        self.corner_points = []

    def mousePressEvent(self, event):
        super(Scene, self).mousePressEvent(event)

        if self.record_points:
            self.points_lst.append(event.scenePos())
            return

        for point in self.corner_points:
            if point[0].contains(event.scenePos()):
                self.selected_corner = point
                return

        if self.selectedItems():

            self.removeControlPoints()

            self.selected = self.selectedItems()[0]
            self.poly_points = [self.selected.mapToScene(x) for x in self.selected.polygon()]

            for index, point in enumerate(self.poly_points):
                x, y = point.x(), point.y()
                ellipse = self.addEllipse(QtCore.QRectF(x - 5, y - 5, 10, 10), brush=QtGui.QBrush(QtGui.QColor("red")))
                ellipse.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable)

                self.corner_points.append((ellipse, index))

        else:
            self.selected = None
            self.removeControlPoints()
            self.corner_points = []
            self.poly_points = []
            self.selected_corner = None

    def mouseMoveEvent(self, event) -> None:
        super(Scene, self).mouseMoveEvent(event)

        if self.selected_corner:
            self.poly_points[self.selected_corner[1]] = QtCore.QPointF(event.scenePos())
            self.selected.setPolygon(QtGui.QPolygonF(self.poly_points))

    def mouseReleaseEvent(self, event) -> None:
        super(Scene, self).mouseReleaseEvent(event)
        self.selected_corner = None

    def addPoints(self):  # adds the polygon to the scene
        self.record_points = False
        polygon = self.addPolygon(QtGui.QPolygonF(self.points_lst))
        polygon.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable)
        self.points_lst = []


class MainWindow(QtWidgets.QWidget):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.setLayout(QtWidgets.QVBoxLayout())

        view = QtWidgets.QGraphicsView()
        scene = Scene()
        view.setScene(scene)

        record_btn = QtWidgets.QPushButton(text="Record", clicked=scene.record)
        finish_btn = QtWidgets.QPushButton(text="Finish", clicked=scene.addPoints)

        self.layout().addWidget(view)
        self.layout().addWidget(record_btn)
        self.layout().addWidget(finish_btn)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    win = MainWindow()
    win.show()

    sys.exit(app.exec_())

输出:

enter image description here

相关问题 更多 >

    热门问题