这一篇教程,我们在之前已编写模块的基础上,通过wxPython实现GUI图形界面的客户端。
一、导入模块
我们需要导入之前server模块和client模块中实现的一些类和方法,另外还需要导入wx模块。
示例代码:
from pclient import random_string # 导入获取随机密钥的方法 from pserver import Node, UNHANDLED # 导入节点类和请求状态变量 from xmlrpc.client import ServerProxy, Fault from threading import Thread from time import sleep import wx # 导入wxPython模块 import sys
二、创建变量
变量与CMD客户端是一样的。
示例代码:
HEAD_START = 0.1 SECRET_LENGTH = 10
三、定义客户端类(Client)
在这个类中,我们需要完成以下三个方面:
- 服务器、服务器代理以及GUI界面初始化。
- 定义GUI图形界面。
- 定义下载事件的处理方法。
示例代码:
class Client(wx.App): # 定义客户端类 def __init__(self, url_file, dir_name, url): # 定义构造方法 pass def OnInit(self): # 重写超类初始化界面的方法 pass def fetchHandler(self, event): # 定义下载事件的处理方法 pass
接下来,就逐一完成这些内容。
1、定义构造方法。
在构造方法中主要是启动GUI图形界面、启动服务器以及创建服务器代理对象。
这里需要注意的是,通过超类对象启动GUI界面。
示例代码:
class Client(wx.App): # 定义客户端类 def __init__(self, url_file, dir_name, url): # 定义构造方法 super(Client, self).__init__() # 将Clint类的对象转换为超类的对象,能够运行OnInit()方法。 self.secret = random_string(SECRET_LENGTH) node = Node(url, dir_name, self.secret) thread = Thread(target=node._start) thread.setDaemon(1) thread.start() sleep(HEAD_START) self.server = ServerProxy(url) for line in open(url_file): self.server.hello(line.strip())
2、重写初始化GUI界面的方法。
这一部分内容大家可以参考之前我们讲过的wxPython部分。
示例代码:
def OnInit(self): # 重写超类初始化界面的方法 window = wx.Frame(None, title='文件下载器', size=(400, 85)) # 创建程序主窗口 background = wx.Panel(window) # 创建功能面板 self.user_input = user_input = wx.TextCtrl(background) # 添加文本框控件 submit = wx.Button(background, label='下载', size=(80, 25)) # 添加下载按钮控件 submit.Bind(wx.EVT_BUTTON, self.fetchHandler) # 绑定下载事件处理方法 hbox = wx.BoxSizer() # 创建尺寸器 hbox.Add(user_input, proportion=1, flag=wx.ALL | wx.EXPAND, border=10) # 水平容器中添加文本框 hbox.Add(submit, flag=wx.TOP | wx.BOTTOM | wx.RIGHT, border=10) # 水平容器中添加下载按钮 vbox = wx.BoxSizer(wx.VERTICAL) # 创建垂直容器 vbox.Add(hbox, proportion=0, flag=wx.EXPAND) # 将水平容器添加到垂直容器 background.SetSizer(vbox) # 将垂直容器添加到尺寸器 window.Show() # 显示程序窗口 return True
3、定义下载事件的处理方法。
点击下载按钮时的事件由这个方法进行处理,主要是调用服务器代理对象的fetch()方法。
示例代码:
def fetchHandler(self, event): # 定义下载事件的处理方法 filename = self.user_input.GetValue() try: self.server.fetch(filename, self.secret) except Fault as f: if f.faultCode != UNHANDLED: raise print('没有找到文件:', filename)
四、定义与启动主程序
主程序依然通过命令行启动。
示例代码:
def main(): # 定义主程序函数 url_file, dir_name, url = sys.argv[1:] client = Client(url_file, dir_name, url) client.MainLoop() if __name__ == '__main__': main()
到这里我们就完成了一个简单的GUI客户端的编写。
同样通过命令行启动多个客户端,然后尝试通过文件名下载文件。
本节练习源代码:【点此下载】
转载请注明:魔力Python » 练习项目17:P2P在线文件共享(三)