发布于2021-01-17 16:47 阅读(892) 评论(0) 点赞(0) 收藏(2)
0
1
2
3
4
我正在使用节点编辑器,目前正在使用QGraphicsWidget
和创建自己的系统QGraphicsScene
。我发现QGraphicsGridLayout
在Node
课堂上使用a非常灵活,只需将诸如文本/数字输入,标签等子组件添加到布局中即可。现在,我的问题是我想在输入旁边创建一个套接字,该套接字应该看起来像一个可以连接边的小圆圈。当前看起来像这样:
但是,我无法将套接字放置在Node之外的中间位置。我尝试用类的paint()
方法绘画它Node
,但是当节点移动时,它留下了外部部分的痕迹,并且失去了一些灵活性。实现以下外观的最佳方法是什么?
以下是我的Node
班级和我的Socket
班级。
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QPainterPath, QBrush, QFont, QColor, QPalette
from PyQt5.QtWidgets import QGraphicsItem, QGraphicsTextItem, QGraphicsWidget, QGraphicsGridLayout, QLabel, \
QLineEdit, QSizePolicy
from src.gui.widgets.graphics.node_scene import NodeScene
from src.gui.widgets.graphics.socket import Socket, SOCKET_TYPE_FLOAT, SOCKET_TYPE_RGB
class Node(QGraphicsWidget):
def __init__(self, scene: NodeScene, title: str = "", parent=None):
super().__init__(parent)
# define data properties
self._input_sockets = []
# define Node properties
self._scene = scene
self._width = 200
self._height = 200
self._rounding = 5
self._padding = 8
self._bg_color = QColor(80, 80, 100, 200)
self._title_color = Qt.white
self._title_font = QFont("Corbel", 8)
self._title_font.setBold(True)
self._title = title
self._title_item = None
# Define socket properties
self._socket_label_font = QFont("Corbel", 7)
self._socket_label_palette = QPalette()
self._socket_label_palette.setColor(QPalette.Background, QColor(0, 0, 0, 0))
self._socket_label_palette.setColor(QPalette.Foreground, self._title_color)
# Define layout
self._layout = QGraphicsGridLayout()
self._layout.setColumnAlignment(0, Qt.AlignLeft)
#self._layout.setContentsMargins(*[self._padding] * 4)
self._layout.setHorizontalSpacing(2.0)
self._layout.setRowSpacing(0, 16)
self.setLayout(self._layout)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
# Try adding an input
self.add_input(SOCKET_TYPE_FLOAT, "Test input")
# Initialize title
self._create_title()
self.title = self._title
@property
def title(self):
return self._title
@title.setter
def title(self, value):
self._title = value
self._title_item.setPlainText(self._title)
def _create_title(self):
self._title_item = QGraphicsTextItem(self)
self._title_item.setDefaultTextColor(self._title_color)
self._title_item.setFont(self._title_font)
self._title_item.setPos(self._padding, 0)
self._title_item.setTextWidth(self._width - self._padding)
def boundingRect(self) -> QtCore.QRectF:
return QRectF(0, 0, self._width, self._height).normalized()
def paint(self, painter, option, widget=None):
path_bg = QPainterPath()
path_bg.addRoundedRect(0, 0, self._width, self._height, self._rounding, 1)
painter.setPen(Qt.NoPen) # Disables the border
painter.setBrush(QBrush(self._bg_color))
painter.drawPath(path_bg)
def add_input(self, input_type: str, input_name: str, input_range=(0, 1)):
if input_type == SOCKET_TYPE_FLOAT:
socket = Socket()
self._layout.addItem(Socket(), 1, 0)
if input_type == SOCKET_TYPE_RGB:
socket = Socket()
self._layout.addItem(Socket(), 1, 0)
和Socket
课
from PyQt5.QtCore import Qt, QRectF, QPoint
from PyQt5.QtGui import QPainterPath, QColor, QBrush
from PyQt5.QtWidgets import QGraphicsWidget
SOCKET_TYPE_FLOAT = "type_float"
SOCKET_TYPE_RGB = "type_rgb"
class Socket(QGraphicsWidget):
def __init__(self, *args):
super().__init__(*args)
self._circle_color = QColor(255, 130, 0, 255)
self._bbox = QRectF(0, 0, 10, 10)
self._current_edge = None
def boundingRect(self):
return self._bbox
def paint(self, painter, option, widget=None):
path = QPainterPath()
path.addEllipse(self._bbox)
painter.setPen(Qt.black)
painter.setBrush(QBrush(self._circle_color))
painter.drawPath(path)
您需要为布局设置负边距,但不能使用setContentsMargins()
负值,因为QGraphicsLayout会自动将边距归一化为0。
我想出的解决方案是对布局进行子类化,并覆盖getContentsMargins()
来返回负边距:
class NegativeMarginsLayout(QGraphicsGridLayout):
def __init__(self, *margins):
super().__init__()
self._margins = margins
def setContentsMargins(self, *margins):
self._margins = margins
self.invalidate()
self.activate()
def getContentsMargins(self):
return self._margins
class Node(QGraphicsWidget):
def __init__(self, scene: QGraphicsScene, title: str = "", parent=None):
# ...
self._layout = NegativeMarginsLayout(-20, 0, 20, 0)
请注意,使用QGraphicsLayout可能会导致鼠标事件的碰撞函数出现问题,因此您可能应该重写shape()
并返回boundingRect的QPainterPath(可能会使用布局边距进行调整)。另外,您无需创建QPainterPath即可绘制圆角矩形的形状,只需使用即可QPainter.drawRoundedRect
。
0
1
2
3
4
5
6
7
8
作者:黑洞官方问答小能手
链接: https://www.pythonheidong.com/blog/article/777277/2e7b5f3912e70f089e6d/
来源: python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系z452as@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!