Home > Article > Backend Development > python3+PyQt5 implements custom score slider component
This article mainly introduces python3 PyQt5 to implement custom score slider components in detail. It has certain reference value. Interested friends can refer to it.
This article implements customization through Python3 PyQt5 Widget – Score slider. It supports both keyboard and mouse and is displayed via drawing using physical (viewport) coordinates.
#!/usr/bin/env python3 import platform from PyQt5.QtCore import (QPointF, QRectF, QSize, Qt,pyqtSignal) from PyQt5.QtWidgets import (QApplication, QDialog,QSizePolicy, QGridLayout, QLCDNumber, QLabel, QSpinBox, QWidget) from PyQt5.QtGui import QColor,QFont,QPainter,QFontMetricsF,QPalette, QPolygonF X11 = True try: from PyQt5.QtGui import qt_x11_wait_for_window_manager except ImportError: X11 = False class FractionSlider(QWidget): XMARGIN = 12.0 YMARGIN = 5.0 WSTRING = "999" valueChanged = pyqtSignal(int,int) def __init__(self, numerator=0, denominator=10, parent=None): super(FractionSlider, self).__init__(parent) self.__numerator = numerator self.__denominator = denominator self.setFocusPolicy(Qt.WheelFocus) self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)) def decimal(self): return self.__numerator / float(self.__denominator) def fraction(self): return self.__numerator, self.__denominator def sizeHint(self): return self.minimumSizeHint() def minimumSizeHint(self): font = QFont(self.font()) font.setPointSize(font.pointSize() - 1) fm = QFontMetricsF(font) return QSize(fm.width(FractionSlider.WSTRING) * self.__denominator, (fm.height() * 4) + FractionSlider.YMARGIN) def setFraction(self, numerator, denominator=None): if denominator is not None: if 3 <= denominator <= 60: self.__denominator = denominator else: raise ValueError("denominator out of range") if 0 <= numerator <= self.__denominator: self.__numerator = numerator else: raise ValueError("numerator out of range") self.update() self.updateGeometry() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.moveSlider(event.x()) event.accept() else: QWidget.mousePressEvent(self, event) def mouseMoveEvent(self, event): self.moveSlider(event.x()) def moveSlider(self, x): span = self.width() - (FractionSlider.XMARGIN * 2) offset = span - x + FractionSlider.XMARGIN numerator = int(round(self.__denominator * (1.0 - (offset / span)))) numerator = max(0, min(numerator, self.__denominator)) if numerator != self.__numerator: self.__numerator = numerator #self.emit(SIGNAL("valueChanged(int,int)"), # self.__numerator, self.__denominator) self.valueChanged.emit(self.__numerator, self.__denominator) self.update() def keyPressEvent(self, event): change = 0 if event.key() == Qt.Key_Home: change = -self.__denominator elif event.key() in (Qt.Key_Up, Qt.Key_Right): change = 1 elif event.key() == Qt.Key_PageUp: change = (self.__denominator // 10) + 1 elif event.key() in (Qt.Key_Down, Qt.Key_Left): change = -1 elif event.key() == Qt.Key_PageDown: change = -((self.__denominator // 10) + 1) elif event.key() == Qt.Key_End: change = self.__denominator if change: numerator = self.__numerator numerator += change numerator = max(0, min(numerator, self.__denominator)) if numerator != self.__numerator: self.__numerator = numerator #self.emit(SIGNAL("valueChanged(int,int)"), # self.__numerator, self.__denominator) self.valueChanged.emit(self.__numerator, self.__denominator) self.update() event.accept() else: QWidget.keyPressEvent(self, event) def paintEvent(self, event=None): font = QFont(self.font()) font.setPointSize(font.pointSize() - 1) fm = QFontMetricsF(font) fracWidth = fm.width(FractionSlider.WSTRING) indent = fm.boundingRect("9").width() / 2.0 if not X11: fracWidth *= 1.5 span = self.width() - (FractionSlider.XMARGIN * 2) value = self.__numerator / float(self.__denominator) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) painter.setPen(self.palette().color(QPalette.Mid)) painter.setBrush(self.palette().brush( QPalette.AlternateBase)) painter.drawRect(self.rect()) segColor = QColor(Qt.green).darker(120) segLineColor = segColor.darker() painter.setPen(segLineColor) painter.setBrush(segColor) painter.drawRect(FractionSlider.XMARGIN, FractionSlider.YMARGIN, span, fm.height()) textColor = self.palette().color(QPalette.Text) segWidth = span / self.__denominator segHeight = fm.height() * 2 nRect = fm.boundingRect(FractionSlider.WSTRING) x = FractionSlider.XMARGIN yOffset = segHeight + fm.height() for i in range(self.__denominator + 1): painter.setPen(segLineColor) painter.drawLine(x, FractionSlider.YMARGIN, x, segHeight) painter.setPen(textColor) y = segHeight rect = QRectF(nRect) rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) #painter.drawText(rect, Qt.AlignCenter, #QString.number(i)) painter.drawText(rect, Qt.AlignCenter,str(i)) y = yOffset rect.moveCenter(QPointF(x, y + fm.height() / 2.0)) painter.drawText(rect, Qt.AlignCenter, str(self.__denominator)) painter.drawLine(QPointF(rect.left() + indent, y), QPointF(rect.right() - indent, y)) x += segWidth span = int(span) y = FractionSlider.YMARGIN - 0.5 triangle = [QPointF(value * span, y), QPointF((value * span) + (2 * FractionSlider.XMARGIN), y), QPointF((value * span) + FractionSlider.XMARGIN, fm.height())] painter.setPen(Qt.yellow) painter.setBrush(Qt.darkYellow) painter.drawPolygon(QPolygonF(triangle)) if __name__ == "__main__": import sys app = QApplication(sys.argv) form = QDialog() sliderLabel = QLabel("&Fraction") slider = FractionSlider(denominator=12) sliderLabel.setBuddy(slider) denominatorLabel = QLabel("&Denominator") denominatorSpinBox = QSpinBox() denominatorLabel.setBuddy(denominatorSpinBox) denominatorSpinBox.setRange(3, 60) denominatorSpinBox.setValue(slider.fraction()[1]) denominatorSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) numeratorLabel = QLabel("Numerator") numeratorLCD = QLCDNumber() numeratorLCD.setSegmentStyle(QLCDNumber.Flat) layout = QGridLayout() layout.addWidget(sliderLabel, 0, 0) layout.addWidget(slider, 0, 1, 1, 5) layout.addWidget(numeratorLabel, 1, 0) layout.addWidget(numeratorLCD, 1, 1) layout.addWidget(denominatorLabel, 1, 2) layout.addWidget(denominatorSpinBox, 1, 3) form.setLayout(layout) def valueChanged(denominator): numerator = int(slider.decimal() * denominator) slider.setFraction(numerator, denominator) numeratorLCD.display(numerator) #form.connect(slider, SIGNAL("valueChanged(int,int)"), #numeratorLCD, SLOT("display(int)")) slider.valueChanged[int,int].connect(numeratorLCD.display) #form.connect(denominatorSpinBox, SIGNAL("valueChanged(int)"), #valueChanged) denominatorSpinBox.valueChanged[int].connect(valueChanged) form.setWindowTitle("Fraction Slider") form.show() app.exec_()
Run results:
python3 PyQt5 implements custom fluid mixing widget
python3 PyQt5 uses database table view
python3 PyQt5 implements drag and drop function
The above is the detailed content of python3+PyQt5 implements custom score slider component. For more information, please follow other related articles on the PHP Chinese website!