一、为何而写
pygame中并没有滑动条,但滑动条的应用确实很广泛,为此我仿照tkinter中的slider写了一个在pygame中实现的滑动条,与大家共同交流。
二、程序运行结果
程序运行后结果如图:
可以用鼠标拖动滑动改变其值,当前值会根据滑块位置在左侧或右侧显示,并返回到对应变量中,方便程序中引用。
三、参数说明
滑动条以class的方式定义,设定了一些参数,在使用时直接定义就行,有些有默认值。
下面代码为初始化及关参数:
class 滑动条():
def __init__(self,scr,坐标x,坐标y,宽度,高度,初始值=0,最小值=0,最大值=100,步长=1,bg=(28,28,255),滑块颜色=(128,128,128),fg=(255,255,0),active_bg=(76,155,226),active_滑块颜色=(255,128,255),fontsize=16,取整=True,显示数据=True,小数位数=2,无限大=False,无限大值=sys.maxsize,无限大提示='无限大') -> None:
程序定义了一个横向的条形滑动条,参数如下:(有些参数用了中文哦,不习惯的可以自己改)
scr:输出到的surface
坐标x,坐标y:在scr中的左上角坐标
宽度,高度:滑动条的宽度和高度,宽度不能小于30,高度要大于字体大小!!!
初始值:初始值 初始值一定要在最大值和最小值之间!!!
最小值,最大值:定义按钮取值区间,默认值是0 和 100 ,值太小时请把 取整 = False
步长:每次调整量,必须 > 0
bg:主颜色,即滑动条的颜色
滑块颜色:按滑块可以滑动的滑块颜色
fg:显示实际值的字体颜色
active_bg:光标移动到其上面时的背景颜色
active_滑块颜色:光标移动到滑块上面时的滑块颜色
fontsize:字大小
取整:显示的数值是否取整
显示数据:是否显示数据
小数位数: 在非取整条件时,保留小数点后几位。在取整状态下无效
无限大:为False时,没无限大;为True时,当数值>=最大值 时,则无限大,并提示 无限大提示
无限大值:当处于无限大时,无限大的值,如果没有指定,默认为系统最大值sys.maxsize,即系统支持的最大值
无限大提示:当处于无限大时,显示的内容,如果没有指定,默认为 “无限大”
返回值:滑块对应的实际值;当 无限大 为True时,返回 无限大值 指定的值
以上值均在初始化时定义。
四、完整代码
复制代码就可以运行,每个滑动条应带一个说明,这个版本没有写,以后有时间我会改写一下,说明就需要你自己先写了哦。
# encoding:utf-8
# Copyright (C) 2021-2024 Liu Qinghao
#下面是一个使用pygame库实现的简单滑动条(slider)程序的例子。这个程序创建了一个窗口,并在其中放置了几个滑动条。滑动条的位置和值可以通过鼠标拖动来改变。
__author__ = 'Liu Qinghao' # csdn.net 学习交流文章
import pygame
import sys
class 滑动条():
def __init__(self,scr,坐标x,坐标y,宽度,高度,初始值=0,最小值=0,最大值=100,步长=1,bg=(28,28,255),滑块颜色=(128,128,128),\
fg=(255,255,0),active_bg=(76,155,226),active_滑块颜色=(255,128,255),fontsize=16,取整=True,显示数据=True,\
小数位数=2,无限大=False,无限大值=sys.maxsize,无限大提示='无限大') -> None:
'''定义长条形 滑动条
scr:输出到的surface
坐标x,坐标y:在scr中的左上角坐标
宽度,高度:滑动条的宽度和高度,宽度不能小于30,高度要大于字体大小!!!
初始值:初始值 初始值一定要在最大值和最小值之间!!!
最小值,最大值:定义按钮取值区间,默认值是0 和 100 ,值太小时请把 取整 = False
步长:每次调整量,必须 > 0
bg:主颜色,即滑动条的颜色
滑块颜色:按滑块可以滑动的滑块颜色
fg:显示实际值的字体颜色
active_bg:光标移动到其上面时的背景颜色
active_滑块颜色:光标移动到滑块上面时的滑块颜色
fontsize:字大小
取整:显示的数值是否取整
显示数据:是否显示数据
小数位数: 在非取整条件时,保留小数点后几位。在取整状态下无效
无限大:为False时,没无限大;为True时,当数值>=最大值 时,则无限大,并提示 无限大提示
无限大值:当处于无限大时,无限大的值,如果没有指定,默认为系统最大值sys.maxsize,即系统支持的最大值
无限大提示:当处于无限大时,显示的内容,如果没有指定,默认为 “无限大”
返回值:滑块对应的实际值;当 无限大 为True时,返回 无限大值 指定的值
'''
self.screen = scr
self.display_w = scr.get_rect()[2]
self.坐标x,self.坐标y = 坐标x,坐标y
self.宽度,self.高度 = 宽度,高度
self.刻度外间隔 = 5 # 像素
self.滑块宽度 = 30 # 像素
self.滑块有效宽度 = self.宽度 - self.滑块宽度 # 像素
self.滑块起始x = self.滑块宽度/2 # 像素
self.滑块终止x = self.宽度-self.滑块宽度/2 # 像素
self.实际值 = 初始值
self.最小值 = 最小值
self.最大值 = 最大值 # 当达到最大值时,显示为最小值,即可以循环
self.步长 = 步长
self.每单位值 = (最大值 - 最小值)/self.滑块有效宽度
self.取整 = 取整
self.显示数据 = 显示数据
self.小数位数 = 小数位数
self.无限大 = 无限大
self.无限大值 = 无限大值
self.无限大提示 = 无限大提示
self.bg = bg # 滑块槽颜色
self.active_bg = active_bg # 光标移动到其上面时的背景颜色
self.滑块颜色 = 滑块颜色
self.滑块标线颜色 = (200,0,0)
self.active_滑块颜色 = active_滑块颜色
self.fg = fg
self.fontsize = fontsize
self.控件surface = pygame.Surface((self.宽度,self.高度), pygame.SRCALPHA)
self.update()
def update(self):
pos=pygame.mouse.get_pos()
if self.无限大 and self.实际值 == self.无限大值:
self.滑块当前x = (self.最大值-self.最小值) / self.每单位值
else:
self.滑块当前x = (self.实际值-self.最小值) / self.每单位值 # 像素
if self.坐标x <= pos[0] <= self.坐标x + self.宽度 and self.坐标y <= pos[1] <= self.坐标y + self.高度 : # 鼠标在该控件上方
butt=pygame.mouse.get_pressed()
if butt[0] : # 鼠标左键按下
self.滑块当前x = pos[0] - self.坐标x
if self.滑块当前x <= self.滑块起始x :self.滑块当前x = self.滑块起始x
if self.滑块当前x >= self.滑块终止x :self.滑块当前x = self.滑块终止x+1
self.实际值 = (self.滑块当前x - self.滑块起始x) * self.每单位值 + self.最小值
self.滑块当前x -= self.滑块宽度/2
self.实际值 = self.步长 * ((self.实际值 + self.步长/2) // self.步长)
if self.取整:
self.实际值 = int(round(self.实际值,0)) # 四舍五入取整
else:
self.实际值 = round(self.实际值,self.小数位数) # 四舍五入取整
if self.实际值 >= self.最大值 : self.实际值 = self.最大值
if self.实际值 <= self.最小值 : self.实际值 = self.最小值
if self.无限大 and self.实际值 == self.最大值 :
self.实际值 = self.无限大值
pygame.draw.rect(self.控件surface,self.active_bg, (0,0,self.宽度,self.高度)) # 滑块槽
pygame.draw.rect(self.控件surface,(64,64,64), (self.滑块当前x-1,0,self.滑块宽度+2,self.高度),1) # 滑块阴影,根据值显示到相应位置
pygame.draw.rect(self.控件surface,self.active_滑块颜色, (self.滑块当前x,0,self.滑块宽度,self.高度)) # 滑块,根据值显示到相应位置
else:
pygame.draw.rect(self.控件surface,self.bg, (0,0,self.宽度,self.高度)) # 滑块槽
pygame.draw.rect(self.控件surface,self.滑块颜色, (self.滑块当前x,0,self.滑块宽度,self.高度)) # 滑块,根据值显示到相应位置
pygame.draw.line(self.控件surface,self.滑块标线颜色,(self.滑块当前x+self.滑块起始x-1,0),\
(self.滑块当前x+self.滑块起始x-1,self.高度),2) # 滑块中间的标识线
if self.显示数据:
if self.滑块当前x > self.宽度/2:
self.写((f' {self.无限大提示} ' if self.实际值 == self.无限大值 else f' {self.实际值} '),2,(self.高度-self.fontsize)//2,self.fontsize,self.fg,bg=(255,0,0)) # 显示值
else:
self.写((f' {self.无限大提示} ' if self.实际值 == self.无限大值 else f' {self.实际值} '),self.宽度-2,(self.高度-self.fontsize)//2,self.fontsize,self.fg,'右',(255,0,0)) # 显示值
self.screen.blit(self.控件surface, (self.坐标x,self.坐标y)) # 绘制
return self.实际值
def 写(self,string,x,y,fontsize,color,对齐方式='左',bg=None):
'''参数说明:(显示的内容,坐标x y,字体大小,字颜色,居中显示) 显示的内容:可以接收数字(int ,float)和字符类型(str)
对齐方式:'左','中','右',默认为左对齐
'''
if isinstance(string,(int,float)): # 判断数据类型
string=str(string) # 把数据转换成字符串
cur_font = pygame.font.SysFont('simhei', fontsize)
textSurf = cur_font.render(string[:self.宽度*4//fontsize-2], True, color,bg)
if 对齐方式=='左':
TextRect = (x,y)
elif 对齐方式=='中':
rect=textSurf.get_rect()
TextRect = (x-rect[2]/2,y)
else: # 右对齐
rect=textSurf.get_rect()
TextRect = (x-rect[2],y)
self.控件surface.blit(textSurf,TextRect)
def 滑动条演示():
# 初始化 Pygame
pygame.init()
# 设置窗口尺寸
window_width = 400
window_height = 300
# 创建窗口
screen = pygame.display.set_mode((window_width, window_height))
# 初始化滑动条,并定义其相关量
滑动条1 = 滑动条(screen,50, 50,280,20,100,0,255,1)
滑动条2 = 滑动条(screen,50,150,280,20,0,100,30000,100,无限大=True)
滑动条3 = 滑动条(screen,50,250,280,20,10,2,300,1,无限大=True,无限大值=0,无限大提示='系统最快',滑块颜色=(0,128,0),active_滑块颜色=(0,255,0))
# 填充背景
screen.fill((255, 255, 255))
# 游戏主循环
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 更新滑动条并将其值返回到变量中
a = 滑动条1.update()
b = 滑动条2.update()
c = 滑动条3.update()
print('滑动条的值分别为:',a,b,c)
# 更新显示
pygame.display.flip()
if __name__ == '__main__':
滑动条演示()
pygame.quit()