python

超轻量级php框架startmvc

python3+PyQt5实现自定义分数滑块部件

更新时间:2020-05-30 06:48 作者:startmvc
本文通过Python3+PyQt5实现自定义部件–分数滑块。它既能支持键盘也支持鼠标,使用物理(

本文通过Python3+PyQt5实现自定义部件–分数滑块。它既能支持键盘也支持鼠标,使用物理(视口)坐标通过绘制方式显示。


#!/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_()

运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。