Fraction Slider.py的qt4代码修改后的qt5版本
import platform
import PyQt5
from PyQt5.QtCore import QPointF,QRectF,QSize,Qt,QObject,pyqtSignal
from PyQt5.QtGui import QColor,QFont,QFontMetricsF,QPainter,QPalette,QPolygonF,QKeyEvent
from PyQt5.QtWidgets import (QApplication,QDialog,QGridLayout,QLCDNumber,
QLabel,QSizePolicy,QSpinBox,QWidget)
X11=hasattr(PyQt5.QtGui,"qt_x11_wait_for_window_manager")
X11 = True
try:
from PyQt5.QtGui import qt_x11_wait_for_window_manager
except ImportError:
X11 = False
class FractionSlider(QWidget):
XMARGIN=12
YMARGIN=9
WSTRING='999'
valueChanged=pyqtSignal(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()-2*FractionSlider.XMARGIN
offset=span-x+FractionSlider.XMARGIN
numerator=int(round(self.__denominator*(1-offset/span)))
numerator=max(0,min(numerator,self.__denominator))
if numerator!=self.__numerator:
self.__numerator=numerator
self.valueChanged.emit(self.__numerator)
self.update()
def KeyPressEvent(self, event: QKeyEvent):
change=0
key=None
if key==Qt.Key_Home:
change=-self.__denominator
elif key in (Qt.Key_Up,Qt.Key_Right):
change=1
elif key in (Qt.Key_Down,Qt.Key_Right):
change=-1
elif key==Qt.Key_PageDown:
change=-(self.__denominator//10+1)
elif key==Qt.Key_PageUp:
change=self.__denominator//10+1
elif key==Qt.Key_End:
change=self.__denominator
if change:
numerator=self.__numerator+change
numerator=max(0,min(numerator,self.__denominator))
if numerator!=self.__numerator:
self.__numerator=numerator
self.valueChanged.emit(self.__numerator)
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()-self.XMARGIN*2
value=self.decimal()
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
ymargin=FractionSlider.YMARGIN
yOffeset=segHeight+fm.height()
for i in range(self.__denominator+1):
painter.setPen(segLineColor)
painter.drawLine(x,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,str(i))
y=yOffeset
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
x=FractionSlider.XMARGIN+value*span
trianglewidth=segWidth-indent
triangle=[QPointF(x-trianglewidth,y),QPointF(x+trianglewidth,y),QPointF(x,y+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()
denominatorSpinBox.setRange(3,30)
denominatorSpinBox.setValue(slider.fraction()[1])
denominatorSpinBox.setAlignment(Qt.AlignRight|Qt.AlignCenter)
denominatorLabel.setBuddy(denominatorSpinBox)
numeratorLabel=QLabel('&Numberator')
numeratorLCD=QLCDNumber()
numeratorLCD.setSegmentStyle(QLCDNumber.Flat)
numeratorLabel.setBuddy(numeratorLCD)
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(denominitor):
numerator=slider.decimal()*denominitor
slider.setFraction(numerator,denominitor)
numeratorLCD.display(numerator)
def dsp(num):
numeratorLCD.display(num)
denominatorSpinBox.valueChanged.connect(valueChanged)
slider.valueChanged.connect(dsp)
form.setWindowTitle('Fraction Slider')
form.show()
app.exec_()