五笔打字通主页
上上一篇文章,我用一个多行文本框做了一个答题系统,我发现有一个问题,应该跟我的代码没有什么关系,就是文本框滚动起来,用单选框按钮,复选框按钮做的答题选项,显示起来不是很流畅;另外,在滚动时,如果鼠标是在答案的4个选项上,那就滚动不起来,因为我没有为这个4选项做绑定鼠标滚动事件的代码。
我决定用画布也用一个答题系统,再加上题目及答案组件的鼠标滚动事件绑定代码,现在做好了,测试结果,在鼠标滚动起来时,题目,答案选项都显示得很流畅,在画布上任何位置都可以用上鼠标滚动题目查看。
只是在画布上插入显示各组件的方法跟多行文本框还是有区别,所以在显示方法花了不少时间,至少导入题库,核对答案就跟上上篇文章写的差不多了,有不理解的,可以查看上上一篇文章。
为了在循环中动态生成各组件及变量,我采用的是先创建相关字典的办法。
全部代码如下:
from tkinter import *
import webbrowser
def wb98():
webbrowser.open('http://www.wb98.com',new=1)
def Wheel_y(event):
a= int(-(event.delta)/60)
can1.yview('scroll',a,'units')
root=Tk() # 源码来自wb98.com
root.title('用画布做一个答题系统 wb98.com')
scr1=Scrollbar(root) # 垂直滚动条
scr1.pack(side=RIGHT,fill=Y)
can1=Canvas(root,bg='lightblue',width=10,height=10) # 画面设置一个浅蓝色,便于你看清各组件的位置
can1.pack(side=LEFT,expand=True,fill=BOTH) # 画布定位
with open('car3.txt', 'r', encoding='utf-8') as file: # 只读方式打开编码为utf-8的文本文件
number = 0 # 文本文件中的行号,即
line = file.readlines() # 以读取一行为列表方法读取全部行,line为分解好的列表内容
str1 = line[0].split(',') # 以英文,号来分解第1行,获取题目,答案1,答案2......
# str1[0]:题目 str1[1]:选项1 str1[2]:选项2 str1[3]:选项3 str1[4]:选项4
# str1[5]:答案 str1[6]:图片名
la=dict() # 题目字典
img = dict() # 生成一个空字典,用于下面循环地创建变量
# 以下设各变量为字典,便于循环时生成各组件插入Text组件
option1 = dict() # 生成答案选项1组件字典
option2 = dict() # 生成答案选项2字典
option3 = dict() # 生成答案选项3字典
option4 = dict() # 生成答案选项4字典
# 以下设各变量为字典,便于循环时生成各组件插入Text组件
var_ra = dict()
var_ch1 = dict()
var_ch2 = dict()
var_ch3 = dict()
var_ch4 = dict()
str_daan = '' # 答案字符串初始化
x,y=10,10 # 坐标初始化
ff1=15 # 字体大小
ff2=10 # 字体大小
font1=('黑体',-ff1) # 字体大小前加- 表示是像素大小
font2=('宋体',-ff2)
hh=10 # 上下间距
bmp_h=200 # 图片的高度
# 以下是循环出题的代码 ------- 源码作者:湖南·长沙·何云峰 网站: www.wb98.com
for i in range(1, 11):
id = str(number+1)+":" # 题目序号 来自wb98.com何老师的济亨网
# can1.create_text( x,y, text=str1[0], width=300 , font=font1 ,anchor=NW) # 题目--无法掌握高度,放弃
la[i]=Label(can1,text=id+str1[0],justify=LEFT, font=font1)
can1.create_window(x,y,window=la[i],anchor=NW)
la[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff1+hh # 下一组件的起始位置为当前位置+字体高+间隔
if str1[6] == '':
img[i] = PhotoImage() # 没有相关图片
else:
img[i] = PhotoImage(file='.\\image\\'+str1[6]) # 图片是在安装目录下的image文件夹里
can1.create_image(x,y,image=img[i],anchor=NW)
y=y+bmp_h+hh
str_daan = str_daan + str1[5]+',' # 把答案记下来,交卷用于核对
if len(str1[5]) == 1: # 单选题
var_ra[i] = IntVar(value=0)
option1[i] = Radiobutton(can1, text='A. '+str1[1], bg='white',
activebackground='white', variable=var_ra[i], value=1)
can1.create_window(x,y,window=option1[i],anchor=NW)
option1[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option2[i] = Radiobutton(can1, text='B. '+str1[2], bg='white',
activebackground='white', variable=var_ra[i], value=2)
can1.create_window(x,y,window=option2[i],anchor=NW)
option2[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option3[i] = Radiobutton(can1, text='C. '+str1[3], bg='white',
activebackground='white', variable=var_ra[i], value=3)
can1.create_window(x,y,window=option3[i],anchor=NW)
option3[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option4[i] = Radiobutton(can1, text='D. '+str1[4], bg='white',
activebackground='white', variable=var_ra[i], value=4)
can1.create_window(x,y,window=option4[i],anchor=NW)
option4[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
y=y+10
else:
var_ch1[i] = BooleanVar(value=False)
var_ch2[i] = BooleanVar(value=False)
var_ch3[i] = BooleanVar(value=False)
var_ch4[i] = BooleanVar(value=False)
option1[i] = Checkbutton(
can1, text='A. '+str1[1], bg='white', activebackground='white', variable=var_ch1[i])
can1.create_window(x,y,window=option1[i],anchor=NW)
option1[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option2[i] = Checkbutton(
can1, text='B. '+str1[2], bg='white', activebackground='white', variable=var_ch2[i])
can1.create_window(x,y,window=option2[i],anchor=NW)
option2[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option3[i] = Checkbutton(
can1, text='C. '+str1[3], bg='white', activebackground='white', variable=var_ch3[i])
can1.create_window(x,y,window=option3[i],anchor=NW)
option3[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
option4[i] = Checkbutton(
can1, text='D. '+str1[4], bg='white', activebackground='white', variable=var_ch4[i])
can1.create_window(x,y,window=option4[i],anchor=NW)
option4[i].bind("<MouseWheel>", Wheel_y) # 为组件绑定鼠标滚动事件
y=y+ff2+4+hh # 下一个组件起始坐标:当前位置+字体大小+4个像素间距
y=y+10
number = number+1
str1 = line[number].split(',') # 读取新一行记录
# 以上是循环出题的代码----------------------
def dafei():
daan = str_daan.split(',') # 把答案字符串分解
for i in range(1, 11): # 单选题
if len(daan[i-1]) == 1: # 单选题
if daan[i-1] == str(var_ra[i].get()):
print('第'+str(i)+"题回答正确")
else:
print('第'+str(i)+"题回答错误")
print(" 正确答案:" + daan[i-1])
print(" 你的答案:" + str(var_ra[i].get()))
else: # 多选题
duo = ''
if var_ch1[i].get() == True:
duo = '1'
if var_ch2[i].get() == True:
duo = duo+'2'
if var_ch3[i].get() == True:
duo = duo+'3'
if var_ch4[i].get() == True:
duo = duo+'4'
if daan[i-1] == duo:
print('第'+str(i)+"题回答正确")
else:
print('第'+str(i)+"题回答错误")
print(" 正确答案:" + daan[i-1])
print(" 你的答案:" + duo)
y=y+hh*2 # 再加2个间隔,插入按钮
but1 = Button(can1, text=" 立 即 交 卷 ", command=dafei) # 交卷打分
can1.create_window(x,y,window=but1,anchor=NW)
but1 = Button(can1, text=" 访 问 官 网 ", command=wb98) # 交卷打分
can1.create_window(x+200,y,window=but1,anchor=NW)
can1.config(yscrollcommand = scr1.set) # 绑定垂直滚动条
scr1.config(command = can1.yview)
can1.config(scrollregion=(0,0,650,y+100)) # 保证滚动范围正好是图片的宽高
can1.bind("<MouseWheel>", Wheel_y) # 为画布绑定鼠标滚动事件
root.geometry('700x650+588+224')
# root.wm_deiconify() # 让窗体显现
root.mainloop()运行结果: 丶丌皛

在代码中,我用字体大小,各组件间隔,组件的Y坐标都采取像素的单位,便于操作;上述代码为了让大家看到各组件的位置,各组件的颜色跟画布不同,所以,你只要把组件的背景颜色,活动颜色改成跟背景颜色一致,就可以为你所用。
此文章来自:wb98.com 网站还有相关的系列课程文章,感兴趣的可以前往。
来源:济亨网
本文链接:https://wb98.com/post/346.html