如何一天做出新闻搜索引擎(3)——GUI(图形用户界面)的制作
写在前面
大家好!这一章主要讲解搜索引擎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出新闻搜索引擎!????