我一直在使用绘画事件自定义PyQt小部件。我一直在尝试自定义QSlider小部件,并取得了一些成功,主要是使用CSS样式。但是,我很难用QPainterPath使它弯曲,因为它看起来总是平坦的。这是否超出了此小部件的功能(这会让我感到惊讶)?以下是我最近的许多尝试的成功尝试。我尝试使用路径点,而不是cubicTo()。谁能帮助我或指出正确的方向?
from PyQt5 import QtGui, QtWidgets, QtCore
class slider(QtWidgets.QSlider):
def __init__(self, parent=None):
super(slider, self).__init__(parent)
self.parent = parent
self.setMinimum(10)
self.setMaximum(30)
self.setValue(20)
self.setTickPosition(QtWidgets.QSlider.TicksBelow)
self.setTickInterval(5)
def paintEvent(self, event):
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing)
self.drawCurve(qp)
qp.end()
def drawCurve(self, qp):
path = QtGui.QPainterPath()
path.moveTo(30, 30)
path.cubicTo(30, 30, 200, 350, 200, 30)
qp.drawPath(path)
最佳答案
要获得深度感,只需选择正确的颜色,因为此QPainterPathStroker也被使用。另一方面,我添加了QPainterPath缩放功能:
from PyQt5 import QtCore, QtGui, QtWidgets
class PathSlider(QtWidgets.QAbstractSlider):
def __init__(self, path=QtGui.QPainterPath(), *args, **kwargs):
super(PathSlider, self).__init__(*args, **kwargs)
self._path = path
self.stroke_path = self._path
self.scale_path = self._path
def setPath(self, path):
path.translate(-path.boundingRect().topLeft())
self._path = path
self.update()
def path(self):
return self._path
path = QtCore.pyqtProperty(QtGui.QPainterPath, fget=path, fset=setPath)
def paintEvent(self, event):
border = 10
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
sx, sy = (self.rect().width() -2*border)/self.path.boundingRect().width(), \
(self.rect().height() -2*border)/self.path.boundingRect().height()
tr = QtGui.QTransform()
tr.translate(border, border)
tr.scale(sx, sy)
self.scale_path = tr.map(self.path)
stroker = QtGui.QPainterPathStroker()
stroker.setCapStyle(QtCore.Qt.RoundCap)
stroker.setWidth(4)
stroke_path = stroker.createStroke(self.scale_path).simplified()
painter.setPen(QtGui.QPen(self.palette().color(QtGui.QPalette.Shadow), 1))
painter.setBrush(QtGui.QBrush(self.palette().color(QtGui.QPalette.Midlight)))
painter.drawPath(stroke_path)
stroker.setWidth(20)
self.stroke_path = stroker.createStroke(self.scale_path).simplified()
percentage = (self.value() - self.minimum())/(self.maximum() - self.minimum())
highlight_path = QtGui.QPainterPath()
highlight_path.moveTo(self.scale_path.pointAtPercent(0))
n_p = int((self.maximum() + 1 - self.minimum())/self.singleStep())
for i in range(n_p+1):
d = i*percentage/n_p
p = self.scale_path.pointAtPercent(d)
highlight_path.lineTo(p)
stroker.setWidth(3)
new_phighlight_path = stroker.createStroke(highlight_path).simplified()
activeHighlight = self.palette().color(QtGui.QPalette.Highlight)
painter.setPen(activeHighlight)
painter.setBrush(QtGui.QBrush(QtGui.QColor(activeHighlight)))
painter.drawPath(new_phighlight_path)
opt = QtWidgets.QStyleOptionSlider()
r = self.style().subControlRect(QtWidgets.QStyle.CC_Slider, opt, QtWidgets.QStyle.SC_SliderHandle, self)
pixmap = QtGui.QPixmap(r.width() + 2*2, r.height() + 2*2)
pixmap.fill(QtCore.Qt.transparent)
r = pixmap.rect().adjusted(2, 2, -2, -2)
pixmap_painter = QtGui.QPainter(pixmap)
pixmap_painter.setRenderHint(QtGui.QPainter.Antialiasing)
pixmap_painter.setPen(QtGui.QPen(self.palette().color(QtGui.QPalette.Shadow), 2))
pixmap_painter.setBrush(self.palette().color(QtGui.QPalette.Base))
pixmap_painter.drawRoundedRect(r, 4, 4)
pixmap_painter.end()
r.moveCenter(p.toPoint())
painter.drawPixmap(r, pixmap)
def minimumSizeHint(self):
return QtCore.QSize(15, 15)
def sizeHint(self):
return QtCore.QSize(336, 336)
def mousePressEvent(self, event):
self.update_pos(event.pos())
super(PathSlider, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
self.update_pos(event.pos())
super(PathSlider, self).mouseMoveEvent(event)
def update_pos(self, point):
if self.stroke_path.contains(point):
n_p = int((self.maximum() + 1 - self.minimum())/self.singleStep())
ls = []
for i in range(n_p):
p = self.scale_path.pointAtPercent(i*1.0/n_p)
ls.append(QtCore.QLineF(point, p).length())
j = ls.index(min(ls))
val = int(j*(self.maximum() + 1 - self.minimum())/n_p)
self.setValue(val)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QWidget()
s1 = PathSlider(minimum=0, maximum=100)
s2 = PathSlider(minimum=0, maximum=100)
s = QtWidgets.QSlider(minimum=0, maximum=100)
s.valueChanged.connect(s1.setValue)
s.valueChanged.connect(s2.setValue)
s1.valueChanged.connect(s.setValue)
s2.valueChanged.connect(s.setValue)
c1 = QtCore.QPointF(5, -15)
c2 = QtCore.QPointF(220, -15)
path = QtGui.QPainterPath(QtCore.QPointF(5, 100))
path.cubicTo(c1, c2, QtCore.QPointF(235, 100))
s1.setPath(path)
c1 = QtCore.QPointF(5, 15)
c2 = QtCore.QPointF(220, 15)
path = QtGui.QPainterPath(QtCore.QPointF(5, -100))
path.cubicTo(c1, c2, QtCore.QPointF(235, -100))
s2.setPath(path)
lay = QtWidgets.QHBoxLayout(w)
lay.addWidget(s1)
lay.addWidget(s2)
lay.addWidget(s)
w.show()
sys.exit(app.exec_())
关于python - PyQt5弯曲QSlider,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53603537/