Helping ordinary people create extraordinary websites!
HOME TUTORIALS SCRIPTS WEB HOSTING BLOG FORUM
Get Our Newsletter
Email:

wxHTML for Beginners

By Abhijit Belapurkar
2004-10-30


The World's Most Basic Browser


The first step is to assemble the minimum code necessary to support an application using the wxHtml widget. The following code implements a basic wxPython application with an wxHtml widget as the contents of the main window.

Listing 1. Bare-bones example browser code

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()
Assuming you have wxPython correctly installed, running the above code in your Python interpreter will result in a single large window with an empty white panel (the wxHtml widget). If you get any syntax errors, check for whitespace issues -- especially if you cut-and-pasted the code into your interpreter or editor. If your Python interpreter complains about not being able to import wxPython, check your installation to make sure that it is set up properly.

Of course, as soon as you launch the browser, it becomes immediately evident that we're missing something... such as a mechanism by which to load pages. For some applications, this very basic setup may actually be enough -- the user doesn't need to choose his own pages if you already know what you want to deliver. A simple change would be to pass an extra argument to exHtmlPanel, which would be the page you want to access:

Listing 2. Modifying exHtmlPanel to load page

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)
In the interest of making something a little more standalone and browser-like, we'll expand the ttHtmlPanel class to add some buttons to do standard browser tasks. Of course, if you're actually planning to build a real browser application, you might want to put some more thought into GUI design and usability than we did here.

Listing 3. Modifying ttHtmlPanel to add buttons

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!")
If you've previously used wxPython, or any other Python graphics toolkit, you can see that all we've done is add another container to the panel and put four buttons in it, with callbacks to the added methods in the exHtmlPanel class. The base wxHtml class handily manages the history for us, so OnBack and OnForward are simply calls to the base methods.

Assuming you've been playing along in your Python interpreter as you read this, you may have noticed that the application never returns control back to the console if you close it. This is a simple thing to fix, but maybe we should add a menu bar to provide a file menu with an exit option:

Listing 4. Modifying exFrame to add file menu with exit

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)
While we're off trying to turn this into a real browser, there are a couple of finishing touches that we're missing: most browsers have a status bar, and you may have noticed that no images are being drawn. The following modifications to exApp, exFrame, and exHtmlPanel add a status bar and all built-in image support from wxPython:

Listing 5. Adding a status bar and image support

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")
...
Now your basic browser should be fully functional. Advanced features of wxPython allow you to create your own tags that are handled by custom code to do any action of your choice. Having control of your own customizable embedded browser provides an endless array of possibilities for enhanced reporting and online help.

This code could easily provide the foundation for any number of apps entirely on its own, as well -- there is no reason to limit yourself just to providing online help. Feel free to play around with these classes and see what interesting behavior you can whip up. :-)

Tutorial Pages:
» Building Basic Browser Functionality with wxPython
» The World's Most Basic Browser
» Resources


First published by IBM DeveloperWorks


 | Bookmark
Related Tutorials:
» Python and Java - A Side by Side Comparison
» Learn Python in 10 Minutes
» Python 201 - (Slightly) Advanced Python Topics
» Python 101 - Introduction to Python
» Google Sitemaps
» Python 101