不会虚化的渐变线

import random
import sys

from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QLinearGradient, QPainter, QPainterPath
from PySide6.QtWidgets import QApplication, QGraphicsItem, QGraphicsPathItem, QGraphicsScene, QGraphicsView

app = QApplication(sys.argv)

scene = QGraphicsScene()
D_CON = 33
S_CON = 30

color10 = [
  "#FF6B6B",  # 珊瑚红
  "#4ECDC4",  # 青绿色
  "#FFEAA7",  # 暖黄色
  "#45B7D1",  # 天蓝色
  "#DDA0DD",  # 梅花色
  "#98D8C8",  # 薄荷蓝
  "#F7DC6F",  # 金黄色
  "#96CEB4",  # 薄荷绿
  "#BB8FCE",  # 淡紫色
  "#85C1E9",  # 浅蓝色
]


def hothue():
  c = color10
  return QColor(random.choice(c))


def topline(*, 起点, 终点, 延长x, isright=True):
  '''画顶层线'''
  起点x, 起点y = 起点
  终点x, 终点y = 终点
  # 贝塞尔曲线路径, 2条
  path1 = QPainterPath()
  path1.moveTo(起点x, 起点y - 4)
  # 控制点让曲线自然弯曲
  控制x1 = 起点x + D_CON if isright else 起点x - D_CON
  控制x2 = 终点x - S_CON if isright else 终点x + S_CON
  path1.cubicTo(控制x1, 起点y - 4, 控制x2, 终点y, 终点x, 终点y)
  path1.lineTo(延长x, 终点y)

  path2 = QPainterPath()
  path2.moveTo(起点x, 起点y + 4)
  path2.cubicTo(控制x1, 起点y + 4, 控制x2, 终点y + 1, 终点x, 终点y + 1)
  path2.lineTo(延长x, 终点y + 1)

  # 合并为闭合区域
  combined_path = QPainterPath()
  combined_path.addPath(path1)
  combined_path.connectPath(path2.toReversed())
  combined_path.closeSubpath()

  return combined_path


def getgrad(*, did, color):
  # 创建渐变
  grad = QLinearGradient()
  # 设置相对坐标模式
  grad.setCoordinateMode(QLinearGradient.CoordinateMode.ObjectMode)
  # 使用相对坐标 (0,0) 到 (1,0) 表示从左到右
  if did == "right":
    grad.setStart(0.0, 0.5)  # 左边中点
    grad.setFinalStop(1.0, 0.5)  # 右边中点
  else:
    grad.setStart(1.0, 0.5)  # 右边中点
    grad.setFinalStop(0.0, 0.5)  # 左边中点
  grad.setColorAt(0, QColor("gray"))
  grad.setColorAt(1, color)
  return grad


起点x, 起点y = 0, 0
终点x, 终点y = 60, 1500
延长x = 150
isright = True
line = QGraphicsPathItem()
line.setZValue(-1)
line.setFlag(QGraphicsItem.GraphicsItemFlag.ItemUsesExtendedStyleOption, True)
line.setFlag(QGraphicsItem.GraphicsItemFlag.ItemClipsToShape, False)
line.setFlag(QGraphicsItem.GraphicsItemFlag.ItemClipsChildrenToShape, False)
line.setPen(Qt.PenStyle.NoPen)  # 主节点线不显示边框


combined_path = topline(起点=(起点x, 起点y), 终点=(终点x, 终点y), 延长x=延长x, isright=isright)
line.setPath(combined_path)
clr = hothue()
grad = getgrad(color=clr, did='right')
line.setBrush(grad)


scene.addItem(line)

view = QGraphicsView(scene)
view.setRenderHint(QPainter.RenderHint.Antialiasing, True)
view.setWindowTitle('EllipseItem 点我试试')
view.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
view.centerOn(0, 0)
view.setFocusPolicy(Qt.FocusPolicy.ClickFocus)
# view.resize(600, 600)
view.showMaximized()
sys.exit(app.exec())

解释


📚 常用 GraphicsItemFlag 速查表

标志 作用
ItemIsMovable 可以用鼠标拖动。
ItemIsSelectable 可以选中(出现虚线框,触发 itemSelectionChanged)。
ItemIsFocusable 能接受键盘焦点(setFocus() / 键入事件)。
ItemIgnoresTransformations 项保持原始大小,不受视图缩放/旋转影响(适合做固定尺寸的文字标签)。
ItemContainsChildrenInShape 把子孙全部算进自己的 shape(),用于碰撞检测。
ItemDoesntPropagateOpacityToChildren 自身透明不影响子项。
ItemNegativeZStacksBehindParent 负 Z 值自动排在父项后面,用于图层管理。
ItemSendsGeometryChanges 移动/旋转时会发送 ItemPositionChange 等事件,可拦截做限制。
ItemSendsScenePositionChanges 只要场景坐标变就发事件,比上面更频繁。
ItemUsesExtendedStyleOption paint() 送更多状态信息,对本次无影响。
ItemClipsToShape 关闭后 不再简化/虚线,大路径也能完整渲染。
ItemClipsChildrenToShape 关闭后 子项不会被裁掉,目前无子项,防患于未然。

🎯 实战

  • 只想 画大渐变条 → 记住 关闭 ItemClipsToShape 即可解决“虚线”问题。
  • 想让用户 拖/选/缩放 → 再加 ItemIsMovableItemIsSelectable
  • 固定尺寸文字 → 加 ItemIgnoresTransformations

边框(形状的描边)

  • 这个边框的线形是不能直接做渐变的
常量 数值 预览效果
Qt.NoPen 0 不描边, 只剩下填充
Qt.SolidLine 1 实线
Qt.DashLine 2 短虚线 ‑ ‑ ‑
DotLine 3 点线 · · ·
DashDotLine 4 点划线 ‑ · ‑ ·
DashDotDotLine 5 双点划线 ‑ · · ‑ · ·
line.setPen(Qt.GlobalColor.red)          # 默认 1 px 实线红
line.setPen(QPen(QColor("#4ECDC4"), 3))  # 3 px 自定义颜色实线
line.setPen(QPen(Qt.DashLine))           # 黑色虚线,默认 1 px

pen = QPen() # 定制一个描边
pen.setStyle(Qt.DashDotDotLine)   # 线型
pen.setWidthF(2.5)                # 线宽(浮点)
pen.setColor(QColor(255, 107, 107, 180))  # RGB + 透明度
pen.setCapStyle(Qt.RoundCap)      # 端点圆角
pen.setJoinStyle(Qt.RoundJoin)    # 转角圆角
line.setPen(pen)