花费了两天时间做了一个课堂记分程序,界面如上,有几个技巧记录下,免得忘了
(1)时间控件的即时更新
参考了文档:https://www.jb51.net/article/148640.htm
写一个类,是一个Frame控件:
from tkinter import * import time class Watch(Frame): msec = 1000 def __init__(self, parent=None, **kw): Frame.__init__(self, parent, kw) self._running = False self.timestr1 = StringVar() self.timestr2 = StringVar() self.makeWidgets() self.flag = True def makeWidgets(self): l0= Label(self, text='时间:') l1 = Label(self, textvariable=self.timestr1) l2 = Label(self, textvariable=self.timestr2) l0.pack(side=LEFT) l1.pack(side=LEFT) l2.pack(side=RIGHT) def _update(self): self._settime() self.timer = self.after(self.msec, self._update) def _settime(self): self.localtime=time.localtime(time.time()) today1 = str(time.strftime('%Y年%m月%d日', self.localtime)) time1 = str(time.strftime('%H:%M:%S', self.localtime)) self.timestr1.set(today1) self.timestr2.set(time1) def getlocaltime(self): self.localtime = time.localtime(time.time()) return self.localtime def start(self): self._update() self.pack(side=TOP)
(2)控件布局,界面是三个Frame,最上面是时间控件,中间是选择信息Frame,把各个控件都加到这里了,最下面是一个绘图Frame,
win = tkinter.Tk() frma=Watch(win) #时间控件,上面定义的类 frmb=tkinter.Frame()#所有combox,label,button都在这里,利用grid布局 frmc=tkinter.Frame() mat=MatplotFrame(frmc,win=win)#绘图控件,下面将要讲到 frma.pack() frmb.pack() frmc.pack() frma.start() #时间控件开始每秒更新
(3)绘图控件
参考了:matplotlib教程——matplotlib与tkinter的集成_MIss-Y的博客-CSDN博客
写了一个类:
from tkinter import * #绘制图形 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2Tk class MatplotFrame(Frame): def __init__(self, parent=None,win=None, **kw): Frame.__init__(self, parent, kw) self.canvas = Canvas() # 创建一块显示图形的画布 self.root=parent self.subplot=None self.win=win self.figure = self.create_matplotlib() # 返回matplotlib所画图形的figure对象 self.create_form(self.figure) # 将figure显示在tkinter窗体上面 def create_matplotlib(self): # 创建绘图对象f f = plt.figure(num=2, figsize=(16, 12), dpi=80, facecolor="pink", edgecolor='green', frameon=True) # 创建一副子图 fig1 = plt.subplot(1, 1, 1) fig1.set_xlabel('日期') # 确定坐标轴标题 fig1.set_ylabel("分数") self.subplot=fig1 return f def drawinfor(self,stu,df):#外部调用更新当前显示内容,我这里传入学生的信息和当前DataFrame表格 ''' 绘制图形信息 :param stu: 类型:serias :param df:类型:DataFrame :return: ''' if self.figure: #can get here fig1 = self.subplot #具体绘图不写了 self.canvas.draw() def create_form(self, figure): # 把绘制的图形显示到tkinter窗口上 self.canvas = FigureCanvasTkAgg(figure, self.root) self.canvas.draw() # 以前的版本使用show()方法,matplotlib 2.2之后不再推荐show()用draw代替,但是用show不会报错,会显示警告 self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) # 把matplotlib绘制图形的导航工具栏显示到tkinter窗口上 if self.win:#在外部把最原始的窗口传进来,如果不这样,绘图工具栏不显示 toolbar = NavigationToolbar2Tk(self.canvas, self.win) # matplotlib 2.2版本之后推荐使用NavigationToolbar2Tk,若使用NavigationToolbar2TkAgg会警告 toolbar.update() self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1) (4)点击抽签按钮会更新绘图控件
def randomselect(): global SELECTINDEX SELECTINDEX=-1 (stu,df) = doselect(comclass.get()) stu_str = "学号:{0} 姓名:{1}".format(stu[0], stu[1]) label2.config(text=stu_str) #根据学生信息绘制图形 mat.drawinfor(stu,df) #mat在main函数中定义
抽签控件:
btn1 = tkinter.Button(frmb, text="抽签")#在第二个frame中 btn1.config(command=randomselect)#点击调用选择函数,更新label和绘图 btn1.grid(row=1, column=2, columnspan=2,padx=2)#grid布局
学生信息来自excel表,读写excel都用pandas,这里不细说。值得注意的是对于多个sheet,pandas 的写入方式如下:
with pd.ExcelWriter(filename) as writer: df1.to_excel(writer, sheet_name='1,2班名册', index=False) df2.to_excel(writer, sheet_name='3,4班名册',index=False) df3.to_excel(writer, sheet_name='1,2班名册-图像处理', index=False)
总结:代码还得多写,一个小程序弄了很长时间。