【问题标题】:Part-filled Ellipse部分填充椭圆
【发布时间】:2018-11-24 11:21:19
【问题描述】:

我目前正在 GraphicScene 上绘制椭圆:

pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.lightGray).darker(50))
for id, light in arrLights.iteritems():
    angle = i*delta
    circX = (w + x) * math.cos(angle)
    circY = (h + y) * math.sin(angle)
    item = callbackEllipse(light, hiveLight, circX, circY, w, h)
    item.setAcceptHoverEvents(True)
    item.setPen(pen)

    if (light["status"]):
        brush = QtGui.QBrush(QtGui.QColor(QtCore.Qt.lightGray))
    else:
        brush = QtGui.QBrush(QtGui.QColor(QtCore.Qt.lightGray).darker(150))

    item.setBrush(brush)
    self.scene().addItem(item)
    self.writeText(light['name'], circX , circY, w, h)
    i = i + 1

(callbackEllipse是一个类,父类QGraphicsEllipseItem用于鼠标点击事件)

我正在尝试研究如何部分填充这些椭圆(基于百分比),如下图所示:

椭圆

椭圆

椭圆

我已经搜索并尝试了一些东西,例如多个椭圆和绘制的路径,但这会影响点击事件,并且我丢失了“未填充”椭圆部分的边框。

谁能帮忙?

【问题讨论】:

    标签: python pyqt pyqt5 ellipse


    【解决方案1】:

    对于这些情况,有必要实现一个自定义项并覆盖paint方法,使用QGraphicsEllipseItem作为基础,因为添加百分比属性和填充颜色就足够了,如果你想重新绘制它,你必须调用@ 987654323@。为绘画创建 2 个 QPixmap,第一个绘制矩形,第二个绘制椭圆,然后使用 compositionMode 连接它们

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class CallbackEllipse(QtWidgets.QGraphicsEllipseItem):
        def __init__(self, light, *args, **kwargs):
            super(CallbackEllipse, self).__init__(*args, **kwargs)
            self._fill_brush = QtGui.QBrush(QtCore.Qt.NoBrush)
            self._percentage = 0
            self._light = light
    
        def setFillBrush(self, brush):
            self._fill_brush = brush
            self.update()
    
        def fillBrush(self):
            return self._fill_brush
    
        def setPercentage(self, percentage):
            self._percentage = percentage
            self.update()
    
        def percentage(self):
            return self._percentage
    
        def paint(self, painter, option, widget=None):
            painter.setPen(self.pen())
            r_in = QtCore.QRectF(QtCore.QPointF(), self.rect().size())
            r_out = QtCore.QRectF(r_in)
            r_out.setTop((1-self.percentage())*r_in.height())
    
            p1 = QtGui.QPixmap(r_in.size().toSize())
            p1.fill(QtCore.Qt.transparent)
            p_1 = QtGui.QPainter(p1)
            p_1.setRenderHints(painter.renderHints())
            p_1.fillRect(r_out, self.fillBrush())
            p_1.end()
    
            p2 = QtGui.QPixmap(r_in.size().toSize())
            p2.fill(QtCore.Qt.transparent)
            p_2 = QtGui.QPainter(p2)
            p_2.setRenderHints(painter.renderHints())
            p_2.setPen(painter.pen())
            p_2.setBrush(self.brush())
            p_2.drawEllipse(r_in)
            p_2.end()
    
            pixmap = QtGui.QPixmap(r_in.size().toSize())
            pixmap.fill(QtCore.Qt.transparent)
            p = QtGui.QPainter(pixmap)
            p.setRenderHints(painter.renderHints())
            p.drawPixmap(QtCore.QPointF(), p1)
            p.setCompositionMode(QtGui.QPainter.CompositionMode_DestinationAtop)
            p.drawPixmap(QtCore.QPointF(), p2)
            p.end()
    
            painter.drawPixmap(option.rect.topLeft(), pixmap)
            painter.setPen(self.pen())
            painter.drawEllipse(option.rect)
    
    class GraphicsView(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super(GraphicsView, self).__init__(parent)
            self.setScene(QtWidgets.QGraphicsScene(self))
            self.setRenderHints(self.renderHints() | QtGui.QPainter.Antialiasing)
            light = {"status": True, "name": "myname"}
            it = CallbackEllipse(light, 100, 100, 100, 100)
            it.setPercentage(0.4)
            it.setPen(QtGui.QPen(QtGui.QColor(QtCore.Qt.lightGray).darker(150)))
            it.setBrush(QtGui.QBrush(QtGui.QColor(QtCore.Qt.white)))
            it.setFillBrush(QtGui.QBrush(QtGui.QColor("#4471C4")))
            self.scene().addItem(it)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = GraphicsView()
        w.resize(640, 480)
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 现象级的。我不知道你怎么让它看起来这么简单。工作一种享受。再次感谢 eyllanesc :)
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2011-03-17
    • 1970-01-01
    • 2013-07-11
    相关资源
    最近更新 更多