我想让 UI 基本上是一个图像,用户可以通过线连接的点来追踪路径。我希望它是跨平台的,所以我正在考虑尝试 enaml。我不确定如何做到这一点。
我浏览了文档和示例,但找不到像画布小部件这样的东西。是否可以使用搪瓷在表面上进行任意绘图(点、线等)?
enaml 没有画布小部件,但您可以使用RawWidget以及自定义 QWidget 和 QPainter 来绘制您需要的任何内容。
from atom.api import Typed, Event
from enaml.widgets.api import Window, Container, RawWidget
from enaml.core.declarative import d_
from enaml.qt.QtCore import Qt
from enaml.qt.QtGui import QPainter, QPainterPath, QMouseEvent
from enaml.qt.QtWidgets import QWidget
class QtPaintWidget(QWidget):
""" A widget that delegates drawing to enaml """
def __init__(self, parent, widget):
super(QtPaintWidget, self).__init__(parent)
self.widget = widget
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
# Trigger the 'paint' event on th PaintWidget
self.widget.paint(qp)
qp.end()
def mouseReleaseEvent(self, e):
super(QtPaintWidget, self).mouseReleaseEvent(e)
self.widget.mouse_event(e)
class PaintWidget(RawWidget):
#: Push the paint event up to enaml
paint = d_(Event(QPainter))
#: Handle mouse event in enaml
mouse_event = d_(Event(QMouseEvent))
def create_widget(self, parent):
return QtPaintWidget(parent, self)
def update(self):
self.proxy.widget.update()
enamldef Main(Window):
Container:
padding = 0
PaintWidget: canvas:
attr points = []
minimum_size = (500, 500)
paint ::
# See https://doc.qt.io/qt-5/qpainter.html
# for how to use the QPainter
qp = change['value']
qp.setBrush(Qt.white)
qp.drawRect(0, 0, 500, 500)
qp.setBrush(Qt.NoBrush)
qp.setPen(Qt.blue)
for p in points:
qp.drawPoint(p)
qp.setPen(Qt.red)
path = QPainterPath()
if len(points) > 1:
for i, p in enumerate(points):
if i==0:
path.moveTo(p)
else:
path.lineTo(p)
qp.drawPath(path)
mouse_event ::
# Save the position
e = change['value']
print(e)
if e.button() == Qt.RightButton:
del points[:]
else:
points.append(e.pos())
canvas.update()
和瓦拉
您不必将绘制事件推送到 enaml,它只是使与其他小部件的交互更容易。有关在 Qt 中绘图的更多信息,请参阅QtPainter 文档和http://zetcode.com/gui/pyqt5/painting/。