我试图使用PyQt (PySide6)绘制一个管道网络,如本例中的gif 1:https://i.stack.imgur.com/uQsRg.gif
我知道我必须使用QGraphicsView类和QGraphicsScene在屏幕上绘制元素。
我不知道如何处理所有的鼠标点击和移动事件,以及有端口在管道的每一边,以便能够附加其他管道/元素到管道。
我还必须能够双击元素来配置它们。
有什么好的文档可以让我学习如何做到这一点吗?或者任何教程?
谢谢。
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
)
from PySide6.QtGui import QAction
from PySide6.QtCore import Qt
class GraphicsScene(QGraphicsScene):
def __init__(self):
super().__init__()
def mousePressEvent(self, event) -> None:
if event.button() == Qt.LeftButton:
print("Left button pressed")
pos_x = event.scenePos().x()
pos_y = event.scenePos().y()
print(f"Position: {pos_x}, {pos_y}")
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
编辑/更新:
这里有个解决办法。谢谢你的帮助
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
QGraphicsEllipseItem,
)
from PySide6.QtGui import QPainterPath, QTransform, QPen, QBrush, QColor, QPainter
from PySide6.QtCore import Qt
PORT_PEN_COLOR = "#000000"
PORT_BRUSH_COLOR = "#ebebeb"
EDGE_PEN_COLOR = "#474747"
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(0, 0, 800, 600)
self.setCentralWidget(GraphicsView())
self.show()
class GraphicsView(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setMouseTracking(True)
self.setScene(GraphicsScene())
self.setRenderHint(QPainter.RenderHint.Antialiasing)
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setSceneRect(-10000, -10000, 20000, 20000)
self._port_pen = QPen(QColor(PORT_PEN_COLOR))
self._port_brush = QBrush(QColor(PORT_BRUSH_COLOR))
self._edge_pen = QPen(QColor(EDGE_PEN_COLOR))
self._edge_pen.setWidth(4)
def mousePressEvent(self, event):
clicked_item = self.itemAt(event.scenePos(), QTransform())
if event.buttons() == Qt.MouseButton.LeftButton:
if clicked_item is not None:
# edge item
pos = clicked_item.scenePos()
pos.setX(pos.x() + 6)
pos.setY(pos.y() + 6)
self.edge = self.addPath(QPainterPath())
self.edge.setPen(self._edge_pen)
self.start_pos = pos
self.end_pos = self.start_pos
self.update_path()
else:
x = event.scenePos().x()
y = event.scenePos().y()
# port item
start_port = Ellipse()
start_port.setPos(x - 6, y - 6)
start_port.setPen(self._port_pen)
start_port.setBrush(self._port_brush)
start_port.setZValue(10000.0)
self.addItem(start_port)
# edge item
self.edge = self.addPath(QPainterPath())
self.edge.setPen(self._edge_pen)
self.start_pos = event.scenePos()
self.end_pos = self.start_pos
self.update_path()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.MouseButton.LeftButton:
print(f"moving, x : {event.scenePos().x()}, y : {event.scenePos().y()}")
self.end_pos = event.scenePos()
try:
self.update_path()
except AttributeError:
pass
def mouseReleaseEvent(self, event) -> None:
released_item = self.itemAt(event.scenePos(), QTransform())
if event.button() == Qt.MouseButton.LeftButton:
if released_item is not None and released_item.type() != 2:
self.end_pos = released_item.scenePos()
self.end_pos.setX(self.end_pos.x() + 6)
self.end_pos.setY(self.end_pos.y() + 6)
if not self.start_pos.isNull() and not self.end_pos.isNull():
path = QPainterPath()
path.moveTo(self.start_pos.x() - 1, self.start_pos.y() - 1)
path.lineTo(self.end_pos)
self.edge.setPath(path)
else:
x = event.scenePos().x() + 1
y = event.scenePos().y() + 1
end_port = QGraphicsEllipseItem(0, 0, 10, 10)
end_port.setPos(x - 6, y - 6)
end_port.setPen(self._port_pen)
end_port.setBrush(self._port_brush)
end_port.setZValue(10000.0)
self.addItem(end_port)
def update_path(self):
if not self.start_pos.isNull() and not self.end_pos.isNull():
path = QPainterPath()
path.moveTo(self.start_pos.x() - 1, self.start_pos.y() - 1)
path.lineTo(self.end_pos)
self.edge.setPath(path)
class Ellipse(QGraphicsEllipseItem):
def __init__(self):
super().__init__()
self.setRect(0, 0, 10, 10)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec())
发布于 2022-06-19 13:19:41
它可能需要自己编写所有代码
使用左键添加项(矩形)的最小代码,用右键删除项目的代码。
编辑:
我发现scene
有函数.items()
来访问所有项,并且我不必为此使用自己的list objects
。
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
QGraphicsRectItem,
)
from PySide6.QtGui import QAction
from PySide6.QtCore import Qt
#objects = []
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setSceneRect(-100, -100, 200, 200)
def mousePressEvent(self, event) -> None:
if event.button() == Qt.LeftButton:
#print("Left button pressed")
x = event.scenePos().x()
y = event.scenePos().y()
#print(f"Position: {x}, {y}")
rectitem = QGraphicsRectItem(0, 0, 10, 10)
# set center of rectangle in mouse position
rectitem.setPos(x-5, y-5)
self.addItem(rectitem)
#objects.append(rectitem)
elif event.button() == Qt.RightButton:
#print("Right button pressed")
x = event.scenePos().x()
y = event.scenePos().y()
#print(f"Position: {x}, {y}")
#for item in objects:
for item in self.items():
pos = item.pos()
if abs(x-pos.x()) < 10 and abs(y-pos.y()) < 10:
print('selected:', item)
self.removeItem(item)
#objects.remove(item)
break
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
编辑:
使用的示例
border)
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
QGraphicsRectItem,
)
from PySide6.QtGui import QAction
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QPen, QBrush
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setSceneRect(-100, -100, 200, 200)
self.selected = []
def mousePressEvent(self, event) -> None:
if event.button() == Qt.LeftButton:
#print("Left button pressed")
x = event.scenePos().x()
y = event.scenePos().y()
#print(f"Position: {x}, {y}")
rectitem = QGraphicsRectItem(0, 0, 10, 10)
# set center of rectangle in mouse position
rectitem.setPos(x-5, y-5)
rectitem.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
rectitem.setBrush(QBrush(QColor(255, 255, 255, 255)))
self.addItem(rectitem)
elif event.button() == Qt.RightButton:
#print("Right button pressed")
x = event.scenePos().x()
y = event.scenePos().y()
#print(f"Position: {x}, {y}")
if self.selected:
print('moved')
for item in self.selected:
item.setPos(x-5, y-5)
item.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
item.setBrush(QBrush(QColor(255, 255, 255, 255)))
self.selected.clear()
else:
for item in self.items():
pos = item.pos()
if abs(x-pos.x()) < 10 and abs(y-pos.y()) < 10:
print('selected:', item)
self.selected.append(item)
item.setPen(QPen(QColor(255, 0, 0), 1.0, Qt.SolidLine))
item.setBrush(QBrush(QColor(255, 0, 0, 255)))
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
编辑:
使用mouseMoveEvent
和mouseReleaseEvent
拖动rect的版本(保持右键单击)
基于响应pyqt add rectangle in Qgraphicsscene的代码
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
QGraphicsRectItem,
QGraphicsItem,
)
from PySide6.QtGui import QAction
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QPen, QBrush, QTransform
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setSceneRect(-100, -100, 200, 200)
self.selected = None
self.selected_offset_x = 0
self.selected_offset_y = 0
def mousePressEvent(self, event) -> None:
if event.button() == Qt.LeftButton:
x = event.scenePos().x()
y = event.scenePos().y()
rectitem = QGraphicsRectItem(0, 0, 10, 10)
rectitem.setPos(x-5, y-5)
rectitem.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
rectitem.setBrush(QBrush(QColor(255, 255, 255, 255)))
#rectitem.setFlag(QGraphicsItem.ItemIsMovable, True)
self.addItem(rectitem)
elif event.button() == Qt.RightButton:
x = event.scenePos().x()
y = event.scenePos().y()
if not self.selected:
item = self.itemAt(event.scenePos(), QTransform())
#print(item)
if item:
print('selected:', item)
self.selected = item
self.selected.setBrush(QBrush(QColor(255, 0, 0, 255)))
self.selected_offset_x = x - item.pos().x()
self.selected_offset_y = y - item.pos().y()
#self.selected_offset_x = 5 # rect_width/2 # to keep center of rect
#self.selected_offset_y = 5 # rect_height/2 # to keep center of rect
#super().mousePressEvent(event)
def mouseMoveEvent(self, event):
#print('move:', event.button())
#print('move:', event.buttons())
if event.buttons() == Qt.RightButton: # `buttons()` instead of `button()`
if self.selected:
print('moved')
x = event.scenePos().x()
y = event.scenePos().y()
self.selected.setPos(x-self.selected_offset_x, y-self.selected_offset_y)
#super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
#print('release:', event.button())
#print('release:', event.buttons())
if event.button() == Qt.RightButton:
if self.selected:
print('released')
self.selected.setBrush(QBrush(QColor(255, 255, 255, 255)))
self.selected = None
#super().mouseReleaseEvent(event)
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
当鼠标悬停时,我正在考虑改变颜色(使用mouseMoveEvent
),但此时我没有它。
发布于 2022-06-19 14:49:33
我在这里找到了以下代码:https://python.tutorialink.com/drawing-straight-line-between-two-points-using-qpainterpath/,它允许您使用mousePress创建一行并移动事件
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
)
from PySide6.QtGui import QAction, QPainterPath
from PySide6.QtCore import Qt, QPointF
class GraphicsScene(QGraphicsScene):
def __init__(self, *args, **kwargs):
super(GraphicsScene, self).__init__(*args, **kwargs)
self.path_item = self.addPath(QPainterPath())
self.start_point = QPointF()
self.end_point = QPointF()
def mousePressEvent(self, event):
self.start_point = event.scenePos()
self.end_point = self.start_point
self.update_path()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.end_point = event.scenePos()
self.update_path()
super(GraphicsScene, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self.end_point = event.scenePos()
self.update_path()
super(GraphicsScene, self).mouseReleaseEvent(event)
def update_path(self):
if not self.start_point.isNull() and not self.end_point.isNull():
path = QPainterPath()
path.moveTo(self.start_point)
path.lineTo(self.end_point)
self.path_item.setPath(path)
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
编辑:
我把它和Furas的代码组合在一起
import sys
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
QGraphicsView,
QGraphicsScene,
QGraphicsRectItem,
)
from PySide6.QtGui import QAction, QPainterPath
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QPen, QBrush, QTransform
class GraphicsScene(QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setSceneRect(-100, -100, 200, 200)
self.selected = None
self.selected_offset_x = 0
self.selected_offset_y = 0
def mousePressEvent(self, event) -> None:
if event.button() == Qt.LeftButton:
x = event.scenePos().x()
y = event.scenePos().y()
# rectangle
rectitem = QGraphicsRectItem(0, 0, 10, 10)
rectitem.setPos(x - 5, y - 5)
rectitem.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
rectitem.setBrush(QBrush(QColor(255, 255, 255, 255)))
# rectitem.setFlag(QGraphicsItem.ItemIsMovable, True)
# Line
self.path_item = self.addPath(QPainterPath())
self.start_point = event.scenePos()
self.end_point = self.start_point
self.update_path()
self.addItem(rectitem)
elif event.button() == Qt.RightButton:
x = event.scenePos().x()
y = event.scenePos().y()
if not self.selected:
item = self.itemAt(event.scenePos(), QTransform())
# print(item)
if item:
print("selected:", item)
self.selected = item
self.selected.setBrush(QBrush(QColor(255, 0, 0, 255)))
self.selected_offset_x = x - item.pos().x()
self.selected_offset_y = y - item.pos().y()
# self.selected_offset_x = 5 # rect_width/2 # to keep center of rect
# self.selected_offset_y = 5 # rect_height/2 # to keep center of rect
# super().mousePressEvent(event)
def mouseMoveEvent(self, event):
# print('move:', event.button())
# print('move:', event.buttons())
if event.buttons() == Qt.RightButton: # `buttons()` instead of `button()`
if self.selected:
print("moved")
x = event.scenePos().x()
y = event.scenePos().y()
self.selected.setPos(
x - self.selected_offset_x, y - self.selected_offset_y
)
elif event.buttons() == Qt.LeftButton:
self.end_point = event.scenePos()
self.update_path()
# super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
# print('release:', event.button())
# print('release:', event.buttons())
if event.button() == Qt.RightButton:
if self.selected:
print("released")
self.selected.setBrush(QBrush(QColor(255, 255, 255, 255)))
self.selected = None
elif event.button() == Qt.LeftButton:
self.end_point = event.scenePos()
x = event.scenePos().x()
y = event.scenePos().y()
rectitem = QGraphicsRectItem(0, 0, 10, 10)
rectitem.setPos(x - 5, y - 5)
rectitem.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
rectitem.setBrush(QBrush(QColor(255, 255, 255, 255)))
self.addItem(rectitem)
self.update_path()
# super().mouseReleaseEvent(event)
def update_path(self):
if not self.start_point.isNull() and not self.end_point.isNull():
path = QPainterPath()
path.moveTo(self.start_point)
path.lineTo(self.end_point)
self.path_item.setPath(path)
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = self.setScene(GraphicsScene())
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(450, 350)
self.setWindowTitle("Main Window")
self.setup_main_window()
self.create_actions()
self.create_menu()
self.show()
def setup_main_window(self):
"""Create and arrange widgets in the main window."""
self.setCentralWidget(GraphicsView())
def create_actions(self):
"""Create the application's menu actions."""
# Create actions for File menu
self.quit_act = QAction("&Quit")
self.quit_act.setShortcut("Ctrl+Q")
self.quit_act.triggered.connect(self.close)
def create_menu(self):
"""Create the application's menu bar."""
self.menuBar().setNativeMenuBar(False)
# Create file menu and add actions
file_menu = self.menuBar().addMenu("File")
file_menu.addAction(self.quit_act)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
https://stackoverflow.com/questions/72675596
复制相似问题