2024-09-30 20:31:25 发布
网友
这正是我试图重新创造的
我尝试过在QProgressBar下使用QLabels的4x4网格布局,但它看起来很糟糕,我想知道是否有任何可能的方法来创建它
该小部件必须使用自定义绘制创建,如下所示:
import os from PySide2 import QtCore, QtGui, QtWidgets CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) class CustomProgressBar(QtWidgets.QWidget): stepsChanged = QtCore.Signal(list) valueChanged = QtCore.Signal(int) def __init__(self, parent=None): super().__init__(parent) self._labels = [] self._value = 0 self._animation = QtCore.QVariantAnimation( startValue=0.0, endValue=1.0, duration=500 ) self._animation.valueChanged.connect(self.update) def get_labels(self): return self._labels def set_labels(self, labels): self._labels = labels[:] self.stepsChanged.emit(self._labels) labels = QtCore.Property( list, fget=get_labels, fset=set_labels, notify=stepsChanged ) def get_value(self): return self._value def set_value(self, value): if 0 <= value < len(self.labels) + 1: self._value = value self.valueChanged.emit(value) self.update() if self.value < len(self.labels): self._animation.start() value = QtCore.Property(int, fget=get_value, fset=set_value, notify=valueChanged) def sizeHint(self): return QtCore.QSize(320, 120) def paintEvent(self, event): grey = QtGui.QColor("#777") grey2 = QtGui.QColor("#dfe3e4") blue = QtGui.QColor("#2183dd") green = QtGui.QColor("#009900") white = QtGui.QColor("#fff") painter = QtGui.QPainter(self) painter.setRenderHints(QtGui.QPainter.Antialiasing) height = 5 offset = 10 painter.fillRect(self.rect(), white) busy_rect = QtCore.QRect(0, 0, self.width(), height) busy_rect.adjust(offset, 0, -offset, 0) busy_rect.moveCenter(self.rect().center()) painter.fillRect(busy_rect, grey2) number_of_steps = len(self.labels) if number_of_steps == 0: return step_width = busy_rect.width() / number_of_steps x = offset + step_width / 2 y = busy_rect.center().y() radius = 10 font_text = painter.font() font_icon = QtGui.QFont("Font Awesome 5 Free") font_icon.setPixelSize(radius) r = QtCore.QRect(0, 0, 1.5 * radius, 1.5 * radius) fm = QtGui.QFontMetrics(font_text) for i, text in enumerate(self.labels, 1): r.moveCenter(QtCore.QPoint(x, y)) if i <= self.value: w = ( step_width if i < self.value else self._animation.currentValue() * step_width ) r_busy = QtCore.QRect(0, 0, w, height) r_busy.moveCenter(busy_rect.center()) if i < number_of_steps: r_busy.moveLeft(x) painter.fillRect(r_busy, blue) pen = QtGui.QPen(green) pen.setWidth(3) painter.setPen(pen) painter.setBrush(green) painter.drawEllipse(r) painter.setFont(font_icon) painter.setPen(white) painter.drawText(r, QtCore.Qt.AlignCenter, chr(0xF00C)) painter.setPen(green) else: is_active = (self.value + 1) == i pen = QtGui.QPen(grey if is_active else grey2) pen.setWidth(3) painter.setPen(pen) painter.setBrush(white) painter.drawEllipse(r) painter.setPen(blue if is_active else QtGui.QColor("black")) rect = fm.boundingRect(text) rect.moveCenter(QtCore.QPoint(x, y + 2 * radius)) painter.setFont(font_text) painter.drawText(rect, QtCore.Qt.AlignCenter, text) x += step_width def main(): import sys app = QtWidgets.QApplication(sys.argv) _id = QtGui.QFontDatabase.addApplicationFont( os.path.join(CURRENT_DIR, "fa-solid-900.ttf") ) print(QtGui.QFontDatabase.applicationFontFamilies(_id)) progressbar = CustomProgressBar() progressbar.labels = ["Step One", "Step Two", "Step Three", "Complete"] button = QtWidgets.QPushButton("Next Step") def on_clicked(): progressbar.value = (progressbar.value + 1) % (len(progressbar.labels) + 1) button.clicked.connect(on_clicked) w = QtWidgets.QWidget() lay = QtWidgets.QVBoxLayout(w) lay.addWidget(progressbar) lay.addWidget(button, alignment=QtCore.Qt.AlignRight) w.show() sys.exit(app.exec_()) if __name__ == "__main__": main()
注意:要绘制复选图标,我使用了awesome字体,因此必须从here下载并将其放置在脚本旁边
PySide:
import os from PySide import QtCore, QtGui CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) class CustomVariantAnimation(QtCore.QVariantAnimation): def updateCurrentValue(self, value): pass class CustomProgressBar(QtGui.QWidget): stepsChanged = QtCore.Signal(list) valueChanged = QtCore.Signal(int) def __init__(self, parent=None): super().__init__(parent) self._labels = [] self._value = 0 self._percentage_width = 0 self._animation = CustomVariantAnimation(startValue=0.0, endValue=1.0) self._animation.setDuration(500) self._animation.valueChanged.connect(self.update) def get_labels(self): return self._labels def set_labels(self, labels): self._labels = labels[:] self.stepsChanged.emit(self._labels) labels = QtCore.Property( list, fget=get_labels, fset=set_labels, notify=stepsChanged ) def get_value(self): return self._value def set_value(self, value): if 0 <= value < len(self.labels) + 1: self._value = value self.valueChanged.emit(value) self.update() if self.value < len(self.labels): self._animation.start() value = QtCore.Property(int, fget=get_value, fset=set_value, notify=valueChanged) def sizeHint(self): return QtCore.QSize(320, 120) def paintEvent(self, event): grey = QtGui.QColor("#777") grey2 = QtGui.QColor("#dfe3e4") blue = QtGui.QColor("#2183dd") green = QtGui.QColor("#009900") white = QtGui.QColor("#fff") painter = QtGui.QPainter(self) painter.setRenderHints(QtGui.QPainter.Antialiasing) height = 5 offset = 10 painter.fillRect(self.rect(), white) busy_rect = QtCore.QRect(0, 0, self.width(), height) busy_rect.adjust(offset, 0, -offset, 0) busy_rect.moveCenter(self.rect().center()) painter.fillRect(busy_rect, grey2) number_of_steps = len(self.labels) if number_of_steps == 0: return step_width = busy_rect.width() / number_of_steps x = offset + step_width / 2 y = busy_rect.center().y() radius = 10 font_text = painter.font() font_icon = QtGui.QFont("Font Awesome 5 Free") font_icon.setPixelSize(radius) r = QtCore.QRect(0, 0, 1.5 * radius, 1.5 * radius) fm = QtGui.QFontMetrics(font_text) for i, text in enumerate(self.labels, 1): r.moveCenter(QtCore.QPoint(x, y)) if i <= self.value: w = ( step_width if i < self.value else self._animation.currentValue() * step_width ) r_busy = QtCore.QRect(0, 0, w, height) r_busy.moveCenter(busy_rect.center()) if i < number_of_steps: r_busy.moveLeft(x) painter.fillRect(r_busy, blue) pen = QtGui.QPen(green) pen.setWidth(3) painter.setPen(pen) painter.setBrush(green) painter.drawEllipse(r) painter.setFont(font_icon) painter.setPen(white) painter.drawText(r, QtCore.Qt.AlignCenter, chr(0xF00C)) painter.setPen(green) else: is_active = (self.value + 1) == i pen = QtGui.QPen(grey if is_active else grey2) pen.setWidth(3) painter.setPen(pen) painter.setBrush(white) painter.drawEllipse(r) painter.setPen(blue if is_active else QtGui.QColor("black")) rect = fm.boundingRect(text) rect.moveCenter(QtCore.QPoint(x, y + 2 * radius)) painter.setFont(font_text) painter.drawText(rect, QtCore.Qt.AlignCenter, text) x += step_width def main(): import sys app = QtGui.QApplication(sys.argv) _id = QtGui.QFontDatabase.addApplicationFont( os.path.join(CURRENT_DIR, "fa-solid-900.ttf") ) print(QtGui.QFontDatabase.applicationFontFamilies(_id)) progressbar = CustomProgressBar() progressbar.labels = ["Step One", "Step Two", "Step Three", "Complete"] button = QtGui.QPushButton("Next Step") def on_clicked(): progressbar.value = (progressbar.value + 1) % (len(progressbar.labels) + 1) button.clicked.connect(on_clicked) w = QtGui.QWidget() lay = QtGui.QVBoxLayout(w) lay.addWidget(progressbar) lay.addWidget(button, alignment=QtCore.Qt.AlignRight) w.show() sys.exit(app.exec_()) if __name__ == "__main__": main()
该小部件必须使用自定义绘制创建,如下所示:
注意:要绘制复选图标,我使用了awesome字体,因此必须从here下载并将其放置在脚本旁边
PySide:
相关问题 更多 >
编程相关推荐