部分填充的椭圆
Part-filled Ellipse
我目前正在 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 是一个 class,父级 class QGraphicsEllipseItem 用于鼠标点击事件)
我正在尝试找出如何部分填充这些省略号(基于百分比),如下图所示:
椭圆
椭圆
椭圆
我已经搜索并尝试了一些东西,例如多个椭圆和绘制路径,但这影响了点击事件并且我丢失了 'unfilled' 椭圆部分的边框。
有人能帮忙吗?
对于这些情况,有必要实现一个自定义项并覆盖 paint 方法,使用 QGraphicsEllipseItem 作为基础,因为添加百分比属性和填充颜色就足够了,如果你想重新绘制它,你必须呼叫 update()
。为绘画创建 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_())
我目前正在 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 是一个 class,父级 class QGraphicsEllipseItem 用于鼠标点击事件)
我正在尝试找出如何部分填充这些省略号(基于百分比),如下图所示:
椭圆
椭圆
椭圆
我已经搜索并尝试了一些东西,例如多个椭圆和绘制路径,但这影响了点击事件并且我丢失了 'unfilled' 椭圆部分的边框。
有人能帮忙吗?
对于这些情况,有必要实现一个自定义项并覆盖 paint 方法,使用 QGraphicsEllipseItem 作为基础,因为添加百分比属性和填充颜色就足够了,如果你想重新绘制它,你必须呼叫 update()
。为绘画创建 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_())