简体   繁体   中英

Is there a drawing/canvas widget in enaml?

I'd like to make UI that's basically an image that a user can trace out a path on with points connected by lines. I'd like it to be cross platform so I'm considering trying out enaml. I'm not sure how to accomplish this though.

I've looked through the documentation and examples and I can't find anything like a canvas widget. Is it possible to do arbitrary drawing (points, lines, etc) on a surface with enaml?

enaml doesn't have a canvas widget, but you can use the RawWidget along with a custom QWidget and a QPainter to draw whatever you need.

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()

And wala

画画

You don't have to push the paint event to enaml it just makes it easier to interact with other widgets. See QtPainter docs and http://zetcode.com/gui/pyqt5/painting/ for more on drawing in Qt.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM