用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 26进制计算实现方法
May 28 Python
Python设置Socket代理及实现远程摄像头控制的例子
Nov 13 Python
Python数据库的连接实现方法与注意事项
Feb 27 Python
解决matplotlib库show()方法不显示图片的问题
May 24 Python
Python 使用类写装饰器的小技巧
Sep 30 Python
python简单实现AES加密和解密
Mar 28 Python
python语言元素知识点详解
May 15 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
Aug 05 Python
用Python写一个自动木马程序
Sep 17 Python
pycharm 配置svn的图文教程(手把手教你)
Jan 15 Python
Pandas||过滤缺失数据||pd.dropna()函数的用法说明
May 14 Python
python模拟浏览器 使用selenium进入好友QQ空间并留言
Apr 12 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
php缩放图片(根据宽高的等比例缩放)实例介绍
2013/06/09 PHP
phpstrom使用xdebug配置方法
2013/12/17 PHP
php图片添加文字水印实现代码
2016/03/15 PHP
ThinkPHP3.2.3框架实现执行原生SQL语句的方法示例
2019/04/03 PHP
Packer 3.0 JS压缩及混淆工具 下载
2007/05/03 Javascript
Extjs列表详细信息窗口新建后自动加载解决方法
2010/04/02 Javascript
再论Javascript的类继承
2011/03/05 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
JS正则表达式大全(整理详细且实用)
2013/11/14 Javascript
jQuery中queue()方法用法实例
2014/12/29 Javascript
浅谈JavaScript字符串拼接
2015/06/25 Javascript
javascript实现拖放效果
2015/12/16 Javascript
JS、jQuery中select的用法详解
2016/04/21 Javascript
jquery 将当前时间转换成yyyymmdd格式的实现方法
2016/06/01 Javascript
深入浅析JavaScript中的Function类型
2016/07/09 Javascript
ES6学习笔记之Set和Map数据结构详解
2017/04/07 Javascript
vue写一个组件
2018/04/09 Javascript
原生实现一个react-redux的代码示例
2018/06/08 Javascript
NodeJS 实现多语言的示例代码
2018/09/11 NodeJs
JS大坑之19位数的Number型精度丢失问题详解
2019/04/22 Javascript
vue 兄弟组件的信息传递的方法实例详解
2019/08/30 Javascript
微信小程序 动态修改页面数据及参数传递过程详解
2019/09/27 Javascript
jQuery列表动态增加和删除的实现方法
2020/11/05 jQuery
Element-ui 自带的两种远程搜索(模糊查询)用法讲解
2021/01/29 Javascript
[33:19]完美世界DOTA2联赛PWL S2 PXG vs InkIce 第一场 11.26
2020/11/30 DOTA
Python实现登录接口的示例代码
2017/07/21 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
2018/03/15 Python
500行代码使用python写个微信小游戏飞机大战游戏
2019/10/16 Python
在django中使用apscheduler 执行计划任务的实现方法
2020/02/11 Python
Windows+Anaconda3+PyTorch+PyCharm的安装教程图文详解
2020/04/03 Python
司机职责范本
2014/03/08 职场文书
班组建设经验交流材料
2014/05/12 职场文书
小学课外活动总结
2014/07/09 职场文书
党员个人公开承诺书
2014/08/29 职场文书
为什么在foreach循环中JAVA集合不能添加或删除元素
2021/06/11 Java/Android
Win11局域网共享权限在哪里设置? Win11高级共享的设置技巧
2022/04/05 数码科技