1. 背景
又到了写毕业论文的时节。之前写过一篇利用Python爬虫,批量抓取CHI Proceeding中的摘要来批量找灵感,辅助开题的文。如果开题顺利,下一步就进入到实验的设计与执行。
使用计算机程序实施心理学实验的过程中会有这样的一个小问题。不同被试使用同一程序实验的时候,程序在当前文件夹下生成的实验数据会有互相覆盖的可能。所以安全的做法是给不同的被试以不同的存有实验材料的文件夹,被试所有的操作都在此文件夹中进行。这样,被试之间的数据不会相互影响。有点类似于iOS中软件的沙盒机制。
但是手动复制很费时,被试越多越费时。之前 @蒋挺 老师在课上介绍 E-prime + Matlab 工作流的时候是使用 Matlab 语句来完成批量的文件复制的。但是 Matlab 即庞大又昂贵,如果实验中的其他部分没有用到就没有必要为此安装 Matlab 。本文试图使用Python编写一个可独立运行的应用程序来实现这一功能。
所以。
目标用户:使用计算机程序以人类为被试的主试
用户需求:根据被试的个数批量生成带有编号的文件夹,并将已有的实验材料放置其中
产品形态:目前心理学实验软件以Windows平台为主,所以目标形态是Windows中的GUI应用程序。
2. 原型
因为功能单一,所以流程图极其简单。
因为流程图是线性,所以UI的控件以线性排列最为合适。
3. 开发
作为一个UXer,一般情况下完成上述工作就可以把交付物甩给开发了,但是这个项目我要把线框图甩给我自己……
开发环境:Windows 10,Python 3.6,Pycharm 2017.1
接下来就 Shut up,Show Code
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilenames
import tkinter.messagebox as mbox
import os
import shutil
# 导入tkinter模块以及其中会用到的打开文件窗口和消息提示,ttk用来让控件风格与系统一致
class FoldersMaker():
def __init__(self):
# 初始化时,制作一个窗口,然后调用生成组件的方法
self.win = tk.Tk()
self.win.title('Folders Maker')
self.win.resizable(0,0)
self.create_widgets()
def create_widgets(self):
# 添加第一个标签,文字是第一步操作指令
label_1 = tk.Label(self.win, text='STEP 1: Input the name of your experiment', height=2,font=(12))
label_1.pack()
# 添加文字输入框来获取实验名称
name = tk.StringVar()
nameEntered = ttk.Entry(self.win, width=16, textvariable=name)
nameEntered.pack()
# 添加第二个标签,文字是第二步操作指令
label_2 = tk.Label(self.win, text='STEP 2: How many participants do you have?', height=2,font=(12))
label_2.pack()
# 添加一个Spinbox来获取被试个数,个数少的时候可以用鼠标微调
spin = tk.Spinbox(self.win, from_=2, to=300, width=5)
spin.pack()
# 添加第三个标签,文字是第三步操作指令
label_3 = tk.Label(self.win, text='STEP 3: Choose the materials of your experiment', height=2,font=(12))
label_3.pack()
# put_files是按钮调用的指令
def put_files():
fnames = askopenfilenames()
num = int(spin.get())
if fnames:
for i in range(1, num+1):
folder = os.getcwd()+'\\{}_'.format(name.get())+'{:0>3}'.format(i) # 拼接出文件夹的名字
if not os.path.exists(folder):
os.mkdir(folder) # 如果文件夹不存在就生成
for item in fnames:
shutil.copy(item, folder) # 将文件一个个放进去
response = mbox.askyesno(title='Good Job', message='mission completed!\nClose the software') # 循环执行完之后弹出消息提醒
if response:
exit() # 点确定之后直接退出应用,但是打包exe后无法点击退出,原因暂时未知
# 添加选择文件的按钮
choose = ttk.Button(self.win, text='Put Files', command=put_files,)
choose.pack()
if __name__ == '__main__':
maker = FoldersMaker()
maker.win.mainloop()
运行结束后,会在程序所在文件夹中批量生成指定个数的文件夹,每个文件夹中都有选择的文件。功能运行正常,但是UI简直就是买家秀啊。这就是Tkinter的缺点之一,丑。
接下来使用Pyinstaller打包成exe,再加个小图标就大功告成了。FoldersMaker.zip
> pyinstaller -F -w -i test.ico FoldersMaker.py
从此,再也不用担心被试的数据被覆盖了。但是新的问题来了,实验全部做完之后怎样批量回收数据呢?直接在父文件夹搜索数据后缀就好了。
4. 参考资料