目录
- 写在前面
- 开始制作GUI!
- 1. 它长什么样?
- 2. 如何实现?
- 3. 还有什么可以改进的地方?
- 写在后面
@
写在前面
大家好!这一章主要讲解搜索引擎GUI的设计与实现。还记得我在《如何一天做出新闻搜索引擎(0)》中放的几张镇楼的图片吗?我们在前几章已经完成的搜索引擎的所有后台的程序,接下来就是制作与用户交互的界面啦!
个人觉得,这一部分才是最有成就感的部分,因为GUI可以给我们一种“我们写的程序终于可以用了”的感觉。这酸爽,只有自己写完才能感受得到(??)。
这篇文章只是讲解思路,代码的展示也是为了配合讲解。如果大家要查看源码,请移步我的github,这篇文章所讲内容在GUI(运行该程序使用搜索引擎).py
中。
开始制作GUI!
想要做出GUI,请回答以下“人生三大问”:
1. 它长什么样?
这一部分就见仁见智了,我只能给出我的设计作为参考:
我把我的GUI分为三个界面:输入界面,新闻显示界面和刷新提示界面(分别对应上面的三张图)。其中输入界面是运行程序之后就弹出来的,新闻显示界面是点击“千度一下”后弹出的界面,而刷新提示界面是点击“刷新”后弹出的界面。
其中输入界面和新闻显示界面的作用不言而喻,而刷新提示界面的作用是告诉用户“现在数据库正在刷新”。由于采用了多线程的设计,刷新的时候并不会影响用户的查询,但是因为此时新数据还没有写进数据库,所以用户查询所用的数据仍然是旧数据,所以这个刷新提示界面的作用就是提示用户“此时的数据仍然是旧数据”。当刷新结束,新数据写入数据库后,刷新提示界面就会自动地消失。
2. 如何实现?
鉴于我们的目标是“一天实现搜索引擎”,所以我们采用最容易上手的tkinter
库作为实现方式。这里推荐一个免费的视频网课,我就是通过这个网课一小时入门的(??)。
由于第一步的设计不同,在这里的实现当然也不同。我在制作GUI的时候最大的体会是,GUI制作是一个“艺术”过程,需要不断地去调整参数、看效果、再调整参数,才能达到自己心目中的理想效果。
就我的设计而言,因为输入界面是最先弹出的,所以我首先实现的是输入界面。代码供参考:
if __name__ == '__main__': window = tk.Tk() window.geometry('3000x650') canvas = tk.Canvas(window, bg = 'white',height = 750,width = 3200) #欢迎图片 welcome_file = tk.PhotoImage(file = 'welcome.gif') welcome_img = canvas.create_image(500,10,anchor = 'nw', image = welcome_file) #词云 ciyun_file = tk.PhotoImage(file = "wordcloud.gif") ciyun_img = canvas.create_image(450,400,anchor = 'nw', image = ciyun_file) #广告 ad_file = tk.PhotoImage(file = "ad.png") ciyun_img = canvas.create_image(500,200,anchor = 'nw', image = ad_file) canvas.pack() #输入文本框 search_entry = tk.Entry(window, show = None, width = 50, bd = 3,font =('Arial',20)) search_entry.place(x=200,y=300) text = tk.Text() #搜索键 search_button = tk.Button(window, bg = 'SkyBlue', text = '千度一下' ,font =('bold Arial',16),command = search_mode) search_button.place(x=970,y=300) #刷新 refresh_button = tk.Button(window, bg = 'SkyBlue', text = '刷新' ,font =('bold Arial',16),command = refresh_mode) refresh_button.place(x=1100,y=300) text.pack() window.mainloop()
其中两个按钮:“千度一下”和“刷新”分别与search_mode和refresh_mode函数链接,当点击这两个按钮时,相应的函数就会被执行。而新闻展示界面和刷新提示界面也是分别在这两个函数中实现的。
其中search_mode函数定义如下:
def search_mode(): global search_entry global N, avg_l, allPages, minheap sentence = search_entry.get() #恢复N, avg_l paraF = open('parameter.txt','r') para = paraF.readline().split() N = int(para[0]) avg_l = int(para[1]) paraF.close() #恢复allPages db = sqlite3.connect('news.sqlite') df2 = pandas.read_sql_query('SELECT * FROM allPages', con = db) allPages_new = df2.to_dict() db.close() first_time = True index = None allPages = [] for x in allPages_new: if first_time: index = allPages_new[x] first_time = False else: newDict = dict() for i in allPages_new[x]: newDict[index[i]] = allPages_new[x][i] allPages.append(newDict)
首先,我们从数据库中提取出搜索时所必须的参数(N -- 数据库新闻数量,avg_l -- 文档平均长度,即平均每个新闻中有多少个有效词),当然,还有每条新闻的信息(allPages)。其实还要取出我们在如何一天做出新闻搜索引擎(1)中建立的新闻关键词字典TermDict,但我把它设计在search函数中了,也就是查询的时候才取出来。
接下来就是查询了:
(接上一段代码,同属于search_mode
函数)
#TermDict在search中取出 minheap = search(sentence, N, avg_l)
查询的结果通过一些全局变量传出来。然后就是弹出新闻显示窗口,把查询的结果可视化:
(接上一段代码,同属于search_mode
函数)
display_news()
search
与display_news()
函数的具体实现请参考我的github,这些函数都在GUI(运行该程序使用搜索引擎).py
文件里。
3. 还有什么可以改进的地方?
到此为止,我们的搜索引擎基本上是做完了。但是这么一个我们精心设计和实现的搜索引擎,我们肯定不希望它有任何的暇疵。所以在做完短暂的自得之后,我们不妨想想还有哪些值得改进的地方。
就我而言,当我的第一版写完的时候,刷新和搜索是在同一个线程中的,这就意味着在刷新的着10min左右的时间里,用户是不能使用搜索功能的。这显然很反人性。所以我就寻思着怎么解决这个问题...最后就加了一个多线程,用户体验立马就上来了(其实用户只有我一个人??)。
写在后面
因为这一章讲解的是偏“艺术”的东西,所以只是提供了我的思路和大体的实现过程,希望能对大家的设计有所启发。
如果大家要查看源码,请移步我的github,这篇文章所讲内容在GUI(运行该程序使用搜索引擎).py
中。
若想要查看本系列的其他文章,请移步如何一天做出新闻搜索引擎(0)。
希望大家能够实现我们一开始的小目标:一天solo出新闻搜索引擎!??