用Python中的wxPython实现最基本的浏览器功能


Posted in Python onApril 14, 2015

通常,大多数应用程序通过保持 HTML 简单来解决大多数浏览器问题 ? 或者说,根据最低共同特性来编写。然而,即便如此,也仍然存在字体和布局的问题,发行新浏览器和升级现有浏览器时,也免不了测试应用程序的痛苦。替代方案 ? 只支持一种浏览器 ? 通常不是一种用户友好的解决方案。

明显的解决方案是在应用程序中嵌入自己的表现 HTML 的窗口构件。当然,从头开始编写这样的窗口构件工作量很大,因此,求助于预先封装的解决方案好象是合理的。

商界有许多选择及几个开放源码软件包。本文将向您显示如何以 Python 作为绑定的语言选择(也支持 C++、Perl 和其它语言)使用作为 wxWindows 软件包一部分分发的 wxHtml 窗口构件。

虽然没有任何 wxPython 经验而熟谙 Python 的开发人员应该能够从头开始,但本文还是假定您具有基本的 wxPython 知识。在本文中,我们将创建一个独立的浏览器应用程序,同时,保持体系结构足够简单以致将浏览器功能迁移到现有的应用程序中是一项简单的任务。
世界上最基本的浏览器

第一步是组装支持使用 wxHtml 窗口构件的应用程序所必需的最少代码。下列代码实现用 wxHtml 窗口构件作为其主窗口内容的基本 wxPython 应用程序。
清单 1. 基本示例浏览器代码

from wxPython.wx import *
from wxPython.html import *
import os,sys
class exHtmlWindow(wxHtmlWindow):
  def __init__(self, parent, id, frame):
   wxHtmlWindow.__init__(self,parent,id)
class exHtmlPanel(wxPanel):
  def __init__(self, parent, id, frame):
   wxPanel.__init__(self,parent,-1)
   self.html = exHtmlWindow(self, -1, frame)
   self.box = wxBoxSizer(wxVERTICAL)
   self.box.Add(self.html, 1, wxGROW)
   self.SetSizer(self.box)
   self.SetAutoLayout(true)
class exFrame (wxFrame):
  def __init__(self, parent, ID, title):
   wxFrame.__init__(self,parent,ID,title,wxDefaultPosition,wxSize(600,750))
   panel = exHtmlPanel(self, -1, self)
class exApp(wxApp):
  def OnInit(self):
   frame = exFrame(NULL, -1, "Example Browser")
   frame.Show(true)
   self.SetTopWindow(frame)
   return true
app = exApp(0)
app.MainLoop()

假定您已正确安装 wxPython,那么在 Python 解释器中运行上述代码将产生一个具有空的白面板(wxHtml 窗口构件)的大窗口。如果出现任何语法错误,请检查空格问题 ? 尤其是如果您将代码剪切粘贴到解释器或编辑器的情况。如果 Python 解释器显示无法导入 wxPython,请检查安装以确保安装正确。

当然,一启动该浏览器,立刻出现的是:我们缺少某些东西 ... 例如装入页面的机制。对于某些应用程序,这一非常基本的设置实际上可能已经够了 — 如果您已知道您要交付什么,那么用户就无需选择自己的页面。简单的更改是向 exHtmlPanel 传递额外的参数,那就是您想访问的页面:
清单 2. 修改 exHtmlPanel 以装入页面

class exHtmlPanel(wxPanel):
+  def __init__(self, parent, id, frame, file):
   wxPanel.__init__(self, parent, -1)
   self.html = exHtmlWindow(self, -1, frame)
   self.box = wxBoxSizer(wxVERTICAL)
   self.box.Add(self.html, 1, wxGROW)
   self.SetSizer(self.box)
   self.SetAutoLayout(true)
+   self.html.LoadPage(file)

为了使之更独立也为了使之更象浏览器,我们将扩展 ttHtmlPanel 类以添加一些执行标准浏览器任务的按钮。当然,如果您实际上是计划构建一个真正的浏览器应用程序,那么在 GUI 设计和可用性方面您可能要考虑的比我们这里做的更多。
清单 3. 修改 ttHtmlPanel 以添加按钮

class ttHtmlPanel(wxPanel):
  def __init__(self, parent, id, frame):
   wxPanel.__init__(self, parent, -1)
   self.frame = frame
   self.cwd = os.path.split(sys.argv[0])[0]
   if not self.cwd:
     self.cwd = os.getcwd
   self.html = ttHtmlWindow(self, -1, self.frame)
   self.box = wxBoxSizer(wxVERTICAL)
   self.box.Add(self.html, 1, wxGROW)
   subbox = wxBoxSizer(wxHORIZONTAL)
   btn = wxButton(self, 1202, "Load File")
   EVT_BUTTON(self, 1202, self.OnLoadFile)
   subbox.Add(btn, 1, wxGROW | wxALL, 2)
   btn = wxButton(self, 1203, "Load Page")
   EVT_BUTTON(self, 1203, self.OnLoadPage)
   subbox.Add(btn, 1, wxGROW | wxALL, 2)
   btn = wxButton(self, 1204, "Back")
   EVT_BUTTON(self, 1204, self.OnBack)
   subbox.Add(btn, 1, wxGROW | wxALL, 2)
   btn = wxButton(self, 1205, "Forward")
   EVT_BUTTON(self, 1205, self.OnForward)
   subbox.Add(btn, 1, wxGROW | wxALL, 2)
   self.box.Add(subbox, 0, wxGROW)
   self.SetSizer(self.box)
   self.SetAutoLayout(true)
  def OnLoadPage(self, event):
   dlg = wxTextEntryDialog(self, 'Location:')
   if dlg.ShowModal() == wxID_OK:
     self.destination = dlg.GetValue()
   dlg.Destroy()
   self.html.LoadPage(self.destination)
  def OnLoadFile(self, event):
   dlg = wxFileDialog(self, wildcard = '*.htm*', style=wxOPEN)
   if dlg.ShowModal():
     path = dlg.GetPath()
     self.html.LoadPage(path)
   dlg.Destroy()
  def OnBack(self, event):
   if not self.html.HistoryBack():
     wxMessageBox("No more items in history!")
  def OnForward(self, event):
   if not self.html.HistoryForward():
     wxMessageBox("No more items in history!")

如果您以前使用过 wxPython 或任何其它 Python 图形工具箱,那么您可以发现我们做的所有事情就是向面板添加另一个容器并将四个按钮置于其中,带有对 exHtmlPanel 类中所添加的方法的回调函数。基础 wxHtml 类巧妙地为我们管理历史,因此, OnBack 和 OnForward 仅仅是对基础方法的调用。

假定读到这些时您已一直在使用 Python 解释器,那么您可能注意到:如果关闭应用程序,它从不将控制返回给控制台。这个问题解决起来很简单,但我们可能应该添加一个菜单栏来提供具有退出选项的文件菜单:
清单 4. 修改 exFrame 以添加带有退出的文件菜单

class exFrame(wxFrame):
  def __init__(self, parent, ID, title):
   wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(600,750))
   panel = exHtmlPanel (self, -1, self)
   mnu_file = wxMenu()
   mnu_file.Append(101, "E&xit", "Exit the browser")
   menuBar = wxMenuBar()
   menuBar.Append(mnu_file, "F&ile")
   self.SetMenuBar(menuBar)
   EVT_MENU(self, 101, self.Exit)
  def Exit(self, event):
   self.Close(true)

当我们没有试图将它变为一个真正的浏览器的时候,我们在结尾处发现少了两个添加项:大多数浏览器都有状态栏,并且您可能注意到了没有绘制任何图像。下列对 exApp 、 exFrame 和 exHtmlPanel 的修改添加了一个状态栏以及所有来自 wxPython 的内置图像支持:
清单 5. 添加状态栏及图像支持

class exApp(wxApp):
  def OnInit(self):
+   wxInitAllImageHandlers()
   frame = exFrame(NULL, -1, "Example Browser")
   frame.Show(true)
   self.SetTopWindow(frame)
   return true
class exHtmlPanel(wxPanel):
  def __init__(self, parent, id, frame):
   wxPanel.__init__(self, parent, -1)
   self.frame = frame
   self.cwd = os.path.split(sys.argv[0])[0]
   if not self.cwd:
     self.cwd = os.getcwd
   self.html = exHtmlWindow(self, -1, self.frame)
+   self.html.SetRelatedFrame(self.frame, "%s")
+   self.html.SetRelatedStatusBar(0)
...
class exFrame(wxFrame):
  def __init__(self, parent, ID, title):
   wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(600,750))
   panel = exHtmlPanel (self, -1, self)
+   self.CreateStatusBar()
+   self.SetStatusText("Default status bar")
...

现在,基本浏览器的功能应该齐全了。wxPython 的高级特性允许您创建自己的标记,可以通过定制代码来处理这些标记以执行您选择的任何操作。对您自己的可定制嵌入式浏览器的控制为增强的报表生成及联机帮助提供了无限的可能性。

这些代码本身就可以轻易为任意数目的应用程序提供基础,并且 ? 没有理由将您限制在仅仅提供联机帮助上。请自由使用这些类,看看能让它们发生什么有趣的行为。:-)

Python 相关文章推荐
Python实现简单字典树的方法
Apr 29 Python
Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
May 17 Python
python数据结构链表之单向链表(实例讲解)
Jul 25 Python
python实现验证码识别功能
Jun 07 Python
python实现键盘控制鼠标移动
Nov 27 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
Aug 20 Python
深入了解Python在HDA中的应用
Sep 05 Python
在python中做正态性检验示例
Dec 09 Python
Transpose 数组行列转置的限制方式
Feb 11 Python
详解python中groupby函数通俗易懂
May 14 Python
为什么是 Python -m
Jun 19 Python
Django路由层如何获取正确的url
Jul 15 Python
Python中SOAP项目的介绍及其在web开发中的应用
Apr 14 #Python
Python中的XML库4Suite Server的介绍
Apr 14 #Python
Python pickle模块用法实例
Apr 14 #Python
使用Python的PEAK来适配协议的教程
Apr 14 #Python
Python全局变量操作详解
Apr 14 #Python
Python and、or以及and-or语法总结
Apr 14 #Python
Python线程的两种编程方式
Apr 14 #Python
You might like
ThinkPHP空模块和空操作详解
2014/06/30 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
thinkPHP实现基于ajax的评论回复功能
2018/06/22 PHP
php curl优化下载微信头像的方法总结
2018/09/07 PHP
ThinkPHP5 的简单搭建和使用详解
2018/11/15 PHP
PHP进阶学习之命名空间基本用法分析
2019/06/18 PHP
理解Javascript闭包
2013/11/01 Javascript
jquery ajax对特殊字符进行转义防止js注入使用示例
2013/11/21 Javascript
JavaScript中匿名、命名函数的性能测试
2014/09/04 Javascript
ionic在开发ios系统微信时键盘挡住输入框的解决方法(键盘弹出问题)
2016/09/06 Javascript
javascript比较语义化版本号的实现代码
2016/09/09 Javascript
js移动焦点到最后位置的简单方法
2016/11/25 Javascript
详解ES6中的let命令
2020/04/05 Javascript
jQuery插件DataTables分页开发心得体会
2017/08/22 jQuery
Javascript中的作用域及块级作用域
2017/12/08 Javascript
node实现分片下载的示例代码
2018/10/17 Javascript
angular中两种表单的区别(响应式和模板驱动表单)
2018/12/06 Javascript
es6基础学习之解构赋值
2018/12/10 Javascript
Node.js Stream ondata触发时机与顺序的探索
2019/03/08 Javascript
深入学习Python中的装饰器使用
2016/06/20 Python
python3 shelve模块的详解
2017/07/08 Python
Anaconda2下实现Python2.7和Python3.5的共存方法
2018/06/11 Python
详解python:time模块用法
2019/03/25 Python
我用Python抓取了7000 多本电子书案例详解
2019/03/25 Python
python+selenium 鼠标事件操作方法
2019/08/24 Python
最小二乘法及其python实现详解
2020/02/24 Python
python 如何把docker-compose.yaml导入到数据库相关条目里
2021/01/15 Python
廉价连衣裙和婚纱礼服在线销售:Tbdress
2019/02/28 全球购物
日本最大的彩色隐形眼镜销售网站:CharmColor
2020/09/09 全球购物
大学生毕业求职找工作的自我评价
2013/09/29 职场文书
货物运输服务质量承诺书
2014/05/29 职场文书
公司委托书怎么写
2014/08/02 职场文书
交心谈心活动总结
2015/05/11 职场文书
2016教师学习党章心得体会
2016/01/15 职场文书
laravel ajax curd 搜索登录判断功能的实现
2021/04/17 PHP
Python 发送SMTP邮件的简单教程
2021/06/24 Python