废话
害,放弃了500 lines or less的项目学习,一方面是里面语言并不只是python,另一方面是预备的基础知识要求比较多。
但是经过上一次的探索,现在特别想自己写一个小应用来给朋友用。
早晨打开电脑突发奇想,打算动手做一个极简笔记本。
极简笔记本
预备软件
pip
PyCharm
Python3
pip 可以在Pycharm的Terminal中用指令pip install Module
安装模块
将pip源改成国内镜像会加快下载速度
这篇文章可以快速教学如何改源CSDN找到的教程(https://blog.csdn.net/sinat_21591675/article/details/82770360)
需要安装tkinter模块
pip install tkinter
前期需求分析
- 开机自动启动
- 记录笔记,自动加时间戳
- 界面干净整洁
问了一圈朋友,普遍认为这个想法不错,但是大多数人不喜欢开机自动启动这个功能,于是删除了第一条需求
基础设计
框架代码是这样的:
from SomeModule import Something
class Main_Function():
def __init__(self,master):
pass
def functions(self):
pass
def other_functions(self):
pass
def main():
root = Tk()
app = Main_Function(root)
root.mainloop()
if __name__ == '__main__':
main()
import
开头import
应该都懂
class
用class
是面向对象编程的范式,这样写更清楚,写功能更加清晰,不会一股脑杂在一起。
并且在网上看到有一个叫monkey patch的方法可以利用class直接打补丁,没仔细研究,这里也用不到,说错了还请指正
def main & if __name__ == ‘__main__’
def main()
也是一种编程范式,看看别的人写的代码也能看到。
每一个文件其实都是一个模块,它可以调比如用其他模块,就像开头from SomeModule import Something
一样,同时其他的文件也可以调用这个模块里的函数。
我的文件命名为SimpleDiary.py
,所以可以import SimpleDiary
,或者from SimpleDiary import Main_Function
。
我们日常import的模块都是别人写好的py文件,就很方便
每一个模块其实都有一个__name__
属性,直接运行这个模块__name__
的缺省值就是__main__
,这句也就是说,直接运行这个模块才会执行main()
函数里面的内容。如果是别的文件调用这个模块,那么就不执行main()
函数里的内容,而是根据具体需要调用模块内具体函数
Tk & mainloop
这是Tkinter模块里的内容,我只是暂时写在这里,使用这个框架代码跑不出任何结果。
功能设计
设计功能和需求分析不一样,这个我自己也体会到了。
自己做项目开发会遇到这几种情况:
- 想到一个很牛逼的功能,研究了好久发现没看懂,搞不起来。这个是实力限制。
- 当时就这么写了,现在发现能再加一点,加个按钮吧!加个菜单吧!太好玩了,菜单改成下拉菜单吧!这个是实践出真知。
- 丢给朋友用,朋友说:“这里用着不舒服。”这个是需要满足易用性。易用性只能给别人试验求反馈,或者经过专业的训练了解到用户的实际操作能力和痛点才能把握好。
我是为了写文章,所以在完成这个小项目后梳理了一下。实际的操作中不可避免地磕磕绊绊,我这次是因为没有具体规划好功能,但我可以料想到实际的工业开发中也会遇到类似的问题。(对美工:“这个风格我觉得不好看,修修图下班前给我。”对建筑师:“这个房子能不能改个造型,明天交图吧!”所有的乙方:“淦!”)
功能:
GUI设计
# get the height and width of the screen
ws=master.winfo_screenwidth()
hs=master.winfo_screenheight()
# calculate the position of x & y
x=(ws/2)-300
y=(hs/2)-200
master.geometry('600x450+%d+%d' % (x,y))
master.resizable(False,False)
上面这一小部分代码是为了实现整体窗口居中,ws 和hs记录屏幕的大小,后面xy就是简单的数学了
下拉菜单栏的实现比较繁琐,具体看我的代码,文后我也会给出我找的参考资料
下面clear和finish为了并排放置,用了Frame控件来帮助布局
其他都是很简单的控件
代码实现
我其实已经根据朋友不同的需求迭代了三版了,我直接放0.2.0版本的代码出来。
给自己的程序归档的时候想标识版本号,在网上查了资料,简单地标注法就是:
修bug、加补丁---->最后一位加一
功能添加,小部分改动---->中间一位加一
大规模改动导致整体结构变化---->第一位加一
# -*- coding: UTF-8 -*-
# Name: Simple diary
# Version: 0.2.0 2020-2-2
# Autuor: ColourfulWhite
# QQ: 2742622317
"""
更新功能:
打开文件的功能(!标题不能带空格
"""
from time import strftime
from time import localtime
from time import time
from tkinter import *
import tkinter.messagebox
from tkinter import filedialog
import os
# # 程序主要功能
class Main_Function():
def __init__(self,master):
# master
self.master=master
master.title("极简日记 v0.2.0")
master.geometry("600x500") # 可以加窗口居中
# get the height and width of the screen
ws=master.winfo_screenwidth()
hs=master.winfo_screenheight()
# calculate the position of x & y
x=(ws/2)-300
y=(hs/2)-200
master.geometry('600x450+%d+%d' % (x,y))
master.resizable(False,False)
#some words
'''
self.label=Label(master,text='记下你的日记吧')
self.label.pack()
'''
# Menu
self.menubar=Menu(master)
# # file menu
self.file_menu=Menu(self.menubar,tearoff=0)
self.file_menu.add_command(label='open',command=self.open_file)
self.file_menu.add_command(label='choose path',command=self.choose_path)
self.file_menu.add_separator() # add a separate line
self.file_menu.add_command(label='exit',command=self.exit)
self.menubar.add_cascade(label='File',menu=self.file_menu) # create the menu
# # help menu
self.help_menu=Menu(self.menubar,tearoff=0)
self.help_menu.add_command(label='Contact author',command=self.contact_author)
self.help_menu.add_command(label='Help',command=self.how)
self.help_menu.add_separator()
self.help_menu.add_command(label='Buy vip',command=self.buy)
self.menubar.add_cascade(label='Help',menu=self.help_menu)
# diary's title
self.label=Label(master,text='Title')
self.label.pack()
self.title=Entry(master,width=50,)
self.title.pack()
# 可以加心情选择
pass
# diary's content
self.label2=Label(master,text='Content')
self.label2.pack()
self.content=Text(master)
self.content.pack()
# control buttons
self.fm=Frame(master)
self.clear=Button(self.fm,text='Clear',command=self.clear_all)
self.save=Button(self.fm,text='Finish',command=self.save)
self.clear.pack(side=LEFT)
self.save.pack(side=RIGHT)
self.fm.pack()
master.config(menu=self.menubar)
def open_file(self):
self.title.delete(0,'end')
self.content.delete(1.0,'end')
self.infilename=filedialog.askopenfilename() # record path and filename
self.infile=open(self.infilename) # use path to open file
# insert the title
self.infilename=self.infilename.split('/')[2] # fine the basename of the file
self.infilename=self.infilename.split(' ')[0]
self.title.insert(0,self.infilename)
# insert the content
self.input=self.infile.read() # read the file
self.content.insert(1.0,self.input)
self.infile.close()
def choose_path(self):
self.mes3=tkinter.messagebox.showinfo('Choose path','功能未完成')
def exit(self):
self.master.destroy()
def clear_all(self):
self.title.delete(0,'end')
self.content.delete(1.0,'end')
def save(self):
save_title=self.title.get()
if save_title=='':
save_title='Untitled'
save_content=self.content.get(1.0,'end')
now=strftime("%Y-%m-%d",localtime(time()))
save_path="/Users/libingfan/Desktop/Diary/"+save_title+" "+now+".txt"
save_file=open(save_path,'w')
save_file.write(save_content)
save_file.close()
self.exit()
def contact_author(self):
self.mes=tkinter.messagebox.showinfo('Author:','QQ:2742622317')
def how(self):
self.mes5=tkinter.messagebox.showinfo('Tips','在D盘创建一个Diary文件夹,日记会自动存进去')
def buy(self):
self.mes2=tkinter.messagebox.showinfo('Buy vip:','功能还未实现')
# # 主控函数
def main():
root=Tk()
app=Main_Function(root)
root.mainloop()
if __name__ == '__main__':
main()
待补充的功能
choose path功能没有完成,这个等我有时间再做
buy vip功能没有完成,因为还没有学习怎么让在别人电脑跑的脚本给我发信息
希望能搞个更新程序的功能,这样每次改了代码就不用发给朋友才能更新了。估计得整一个服务器
后续
为了让朋友用着方便,我想把脚本打包成exe格式使用。
搜索到可以用pyinstaller来进行打包
pyinstaller -F SimpleDiary.py
可以进行打包,但是打包会有黑色运行框
pyinstaller -F -w SimpleDiary.py
可以进行无黑框的打包
pyinstaller -F -w -i icon.ico SimpleDiary.py
在网上下载.ico格式的图标放在dist文件夹里就可以给打包的exe改变图标
打包后会产生几个文件,但是exe文件可以直接拎出来用,把exe发给朋友就可以跑了
python的打包是把库一起打包了,所以它的程序打开会比较慢。
参考资料
Tkinter知乎简介https://www.zhihu.com/search?type=content&q=tkinter
菜单及下拉菜单https://www.cnblogs.com/kongzhagen/p/6148737.html
用文件对话框打开文件路径https://blog.csdn.net/zjiang1994/article/details/53513377