【上期回顾:Tkinter模块GUI界面化编程实战(三)——2048小游戏】
这篇博客介绍了如何用Python Tkinter模块编写一个界面化的随机点名小程序,在博客下面有完整的源码,源码中有超详细的注释,帮助大家理解代码(最后还有附件可以免费下载)
【注:下载文件100%可以运行,因为下载文件中包含打包了的Python程序(exe文件)!】
【2022/10/16 重制】


点击“选项设置”按钮,右侧会流畅地滑出一个选项设置菜单!



【功能说明】
- 点名时会同时显示学号与姓名
- 顶部有提示语句
- 选项设置页面是从右侧华丽地滑出的
- 支持点名的重复与否
- 支持随机点名与顺序点名
- 支持序号的显示与否(虽然好像没啥用)
- 支持文件打开(弹出文件打开的对话框)
- 支持文件预览
- 具有丰富的提示(以对话框的形式)
import random
import tkinter
import tkinter.filedialog
import tkinter.messagebox
import tkinter.scrolledtext
import tkinter.ttk
import webbrowser
__author__ = '小康2022'
# NOTE: 2022/10/16 重制
root = tkinter.Tk() # 创建窗口
root.title('点名小程序')
root.geometry('300x500+500+100')
root.resizable(False, False)
flag = True # 点名是否正在进行的标志
TIP = '温馨提示:\n支持的文件格式有txt和csv\n点击“解析文件”可再次加载文件\n文件格式如下:\n张三, 10001\n李四, 10002'
(_cb1 := tkinter.IntVar()).set(1) # 复选按钮1的值
(_cb2 := tkinter.IntVar()).set(0) # 复选按钮2的值
(_cb3 := tkinter.IntVar()).set(1) # 复选按钮3的值
(info := tkinter.StringVar()).set('开始点名吧!') # 开始点名按钮的显示值
path = tkinter.StringVar() # 文件路径
tkinter.ttk.Button(root, text='选项设置', command=lambda: slide(-1)).place(width=135, height=30, x=155, y=460)
launch = tkinter.ttk.Button(root, text='开始点名', command=lambda: start())
launch.place(width=135, height=30, x=10, y=460)
canvas = tkinter.Canvas(root, bg='white', highlightthickness=0)
canvas.create_text(152, 37, text='点名小程序', font=('方正舒体', 40), fill='#BBB')
canvas.create_text(150, 35, text='点名小程序', font=('方正舒体', 40))
canvas.place(width=300, height=450)
_canvas = tkinter.Canvas(root, bg='white', highlightthickness=0)
_canvas.create_rectangle(0, 450, 270, 500, fill='#EEE', width=0)
_canvas.create_rectangle(10, 45, 260, 115, fill='#EEE', width=0)
_canvas.create_rectangle(10, 330, 260, 440, fill='#EEE', width=0)
_canvas.create_text(10, 10, anchor='nw', font=('楷体', 15), text='选项设置')
_canvas.create_text(20, 340, anchor='nw', font=('楷体', 11), text=TIP)
_canvas.create_line(0, 35, 270, 35, fill='grey')
_canvas.create_line(0, 0, 0, 500, fill='grey')
_canvas.place(width=270, height=500, x=300)
tkinter.Label(canvas, textvariable=info, font=('楷体', 12)).place(width=280, height=30, x=10, y=80)
text = tkinter.scrolledtext.ScrolledText(canvas, bd=0, font=('楷体', 13), state='disabled',
highlightthickness=1,
highlightcolor='#4A9EE0',
highlightbackground='#C0C0C0')
text.place(width=280, height=200, x=10, y=240)
c1 = tkinter.Canvas(canvas, highlightbackground='#C0C0C0', highlightthickness=1)
c2 = tkinter.Canvas(canvas, highlightbackground='#C0C0C0', highlightthickness=1)
c1.place(width=280, height=50, x=10, y=120)
c2.place(width=280, height=50, x=10, y=180)
t1 = c1.create_text(140, 25, font=('华文行楷', 20))
t2 = c2.create_text(140, 25, font=('华文行楷', 20))
tkinter.ttk.Checkbutton(_canvas, text='重复点名', variable=_cb1).place(width=70, height=30, x=20, y=50)
tkinter.ttk.Checkbutton(_canvas, text='随机点名', variable=_cb2).place(width=70, height=30, x=150, y=50)
tkinter.ttk.Checkbutton(_canvas, text='显示序号', variable=_cb3).place(width=70, height=30, x=20, y=80)
combobox = tkinter.ttk.Combobox(_canvas, textvariable=path)
combobox.place(width=250, height=25, x=10, y=125)
tkinter.ttk.Button(_canvas, text='选择文件', command=lambda: openfile()).place(width=120, height=30, x=10, y=160)
tkinter.ttk.Button(_canvas, text='解析文件', command=lambda: analysis()).place(width=120, height=30, x=140, y=160)
_text = tkinter.Text(_canvas, bd=0, font=('楷体', 13), state='disabled',
highlightthickness=1,
highlightcolor='#4A9EE0',
highlightbackground='#C0C0C0')
_text.place(width=250, height=120, x=10, y=200)
tkinter.ttk.Button(_canvas, text='返回', command=lambda: slide(1)).place(width=120, height=30, x=10, y=460)
tkinter.ttk.Button(_canvas, text='点赞支持',
command=lambda: webbrowser.open(
'https://xiaokang2022.blog.csdn.net/article/details/123600462')
).place(width=120, height=30, x=140, y=460)
def openfile():
""" 打开文件 """
_path = tkinter.filedialog.askopenfilename(
filetypes=[('All Files', ['*.txt', '*.csv'])])
if _path:
path.set(_path) # 显示文件路径
def start():
""" 开始点名 """
if path.get():
if not _text.get(1.).isspace() or analysis():
launch.configure(text='停止', command=stop)
info.set('会选中谁呢?')
call()
else:
tkinter.messagebox.showinfo('温馨提示', '点名文件尚未添加!\n请单击“选项设置”以添加文件')
def stop():
""" 停止点名 """
global flag
flag = False
launch.configure(text='继续点名', command=start)
def analysis():
""" 解析文件 """
global data
if not path.get():
tkinter.messagebox.showinfo('温馨提示', '未选择文件!\n请单击“选择文件”以解析')
return
try:
with open(path.get(), 'r') as file:
data = [line.strip() for line in file.readlines() if line]
if len(data[0].split(',')) != 2:
tkinter.messagebox.showerror('解析失败', '文件路径错误或文件格式不正确!\n请重新检查文件是否正确!')
return
result = '文件名称:' + path.get().split('/')[-1] + '\n'
result += '点名人数:%d\n文件预览(前5项):\n--------------------\n' % len(data)
result += '\n'.join(data[:5])
_text.configure(state='normal')
_text.delete(1., 'end')
_text.insert(1., result)
_text.configure(state='disabled')
data = [line.split(',') for line in data]
if type(combobox['value']) == str:
combobox['value'] = (path.get(),)
elif path.get() not in combobox['value']:
combobox['value'] = list(combobox['value']) + [path.get()]
return True
except:
tkinter.messagebox.showerror('解析失败', '文件路径错误或文件格式不正确!\n请重新检查文件是否正确!')
def call(ind: list = [0, 0]):
""" 点名滚动 """
global flag
if ind[0] == len(data):
ind[0] = 0
try:
c1.itemconfigure(t1, text=data[ind[0]][0])
c2.itemconfigure(t2, text=data[ind[0]][1])
except:
tkinter.messagebox.showinfo('点名完毕', '当前为不重复点名模式!\n文件内所有名字均已点过!\n请点击“解析文件”以重新加载文件')
stop()
flag = True
return
if flag:
if _cb2.get():
ind[0] = random.randint(0, len(data) - 1)
else:
ind[0] += 1
root.after(30, call)
else:
ind[1] += 1
text.configure(state='normal')
if _cb3.get():
text.insert('end', '[%03d] %s %s\n' % (ind[1], data[ind[0]][1], data[ind[0]][0]))
else:
text.insert('end', '%s %s\n' % (data[ind[0]][1], data[ind[0]][0]))
text.configure(state='disabled')
if not _cb1.get():
del data[ind[0]]
info.set('就是你啦!')
flag = True
def slide(key: int, ind=0):
""" 设置页滑动 """
lib = [1, 2, 2, 3, 3, 5, 6, 7, 9, 12, 12, 9, 7, 6, 5, 3, 3, 2, 2, 1]
_canvas.place(x=int(_canvas.place_info()['x']) + int(lib[ind] * key * 2.8))
if ind < 19:
root.after(5, slide, key, ind + 1)
else:
launch.configure(state='normal' if key == 1 else 'disabled')
root.mainloop()
【 原创不易,大家都看到这里了,点个赞不难吧?】
完整程序及源码下载链接【蓝奏云】:随机点名小程序.zip
【下期预告:Python Tkinter编写大鱼吃小鱼游戏】【下期链接:大鱼吃小鱼】
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A