I am working on a GUI program which some parts are written in wxpython and some parts in css,html and javascript
The codes below is an example taken from http://wxpython.org/Phoenix/docs/html/MemoryFSHandler.html#memoryfshandler
def OnAbout(self, event):
bcur = wx.BeginBusyCursor()
wx.FileSystem.AddHandler(wx.MemoryFSHandler) #there is a bug here in this example wx.MemoryFSHandler should read wx.MemoryFSHandler()
wx.MemoryFSHandler.AddFile("logo.pcx", wx.Bitmap("logo.pcx", wx.BITMAP_TYPE_PCX))
wx.MemoryFSHandler.AddFile("about.htm",
"<html><body>About: "
"<img src=\"memory:logo.pcx\"></body></html>")
dlg = wx.Dialog(self, -1, _("About"))
topsizer = wx.BoxSizer(wx.VERTICAL)
html = wx.html.HtmlWindow(dlg, size=wx.Size(380, 160), style=wx.HW_SCROLLBAR_NEVER)
html.SetBorders(0)
html.LoadPage("memory:about.htm")
html.SetSize(html.GetInternalRepresentation().GetWidth(),
html.GetInternalRepresentation().GetHeight())
topsizer.Add(html, 1, wx.ALL, 10)
topsizer.Add(wx.StaticLine(dlg, -1), 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 10)
topsizer.Add(wx.Button(dlg, wx.ID_OK, "Ok"),
0, wx.ALL | wx.ALIGN_RIGHT, 15)
dlg.SetAutoLayout(True)
dlg.SetSizer(topsizer)
topsizer.Fit(dlg)
dlg.Centre()
dlg.ShowModal()
wx.MemoryFSHandler.RemoveFile("logo.pcx")
wx.MemoryFSHandler.RemoveFile("about.htm")
These codes shows how to:
to add a MemoryFSHandler and load an HTML string into the memory stream instead of placing html codes in a file and calling that file
Also this example is based on html widget and not webview widget
Below are my codes (trial and error)
class About(wx.Frame):
def __init__(self):
wx.Panel.__init__(self,None,-1,title="This is a working example",size=(700,700))
class Test(wx.Frame):
"""Contact author: contribute a word or send a occurences of bugs"""
def __init__(self,title,pos,size):
wx.Frame.__init__(self,None,-1,title,pos,size)
self.tester=wx.html2.WebView.New(self)
#self.tester.RegisterHandler(wx.html2.WebViewHandler())
wx.FileSystem.AddHandler(wx.MemoryFSHandler())
#self.tester.SetPage("""
wx.MemoryFSHandler().AddFile("about.js","""
document.write("IT is working")
""")
self.tester.LoadURL("memory:about.htm")
I have tried searching the web for some examples but was unfortunate
QUESTION
How can I create a handler for webview widget. This handler should load any html string in a memory stream/file (for example using a URI scheme "memory:.....") so that webview can load an html memory file
Can you post your complete code? Right now you are trying to load
self.tester.LoadURL("memory:about.htm")
But the only memory file you registered was about.js. If you want to reference about.htm you have to register it first:
wx.FileSystem.AddHandler(wx.MemoryFSHandler())
wx.MemoryFSHandler().AddFile("about.js", 'document.write("IT is working")')
wx.MemoryFSHandler().AddFile("about.htm",
"""<html>
<script src="memory:about.js"></script>
<body><h2>It lives!</h2></body>
</html>""")
self.tester.LoadURL("memory:about.htm")
What you need is wx.html2.WebViewFSHandler. I haven't tried this myself, so I'm basing this off the wxWidgets WebView example, but you should be able to do the following after creating your wx.MemoryFSHandler to register the memory handler with the WebView:
self.tester.RegisterHandler(wx.html2.WebViewFSHandler("memory"))
After this, your self.tester.LoadURL("memory:about.htm") call should work.
wx.html2.WebViewFSHandler only exists in Phoenix, though, so if you're not using Phoenix, then I'm afraid your best bet is probably to use WebView's SetPage method instead:
html_data = """<html>
<script>document.write("IT is working");</script>
<body><h2>It lives!</h2></body>
</html>"""
self.tester.SetPage(html_data, "")
EDIT:
I'm adding a complete working example for Phoenix to show how to make it work.
import wx
import wx.html2
class About(wx.Frame):
def __init__(self):
wx.Panel.__init__(self,None,-1,title="This is a working example",size=(700,700))
class Test(wx.Frame):
"""Contact author: contribute a word or send a occurences of bugs"""
def __init__(self,title,pos,size):
wx.Frame.__init__(self,None,-1,title,pos,size)
self.tester=wx.html2.WebView.New(self)
memoryfs = wx.MemoryFSHandler()
wx.FileSystem.AddHandler(memoryfs)
wx.MemoryFSHandler.AddFileWithMimeType("about.js", u'document.write("IT is working")', 'text/plain')
wx.MemoryFSHandler.AddFileWithMimeType("about.htm",
u"""<html>
<script src="memory:about.js"></script>
<body><h2>It lives!</h2></body>
</html>""", 'text/html')
self.tester.RegisterHandler(wx.html2.WebViewFSHandler("memory"))
self.tester.LoadURL("memory:about.htm")
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = Test("Hello", (20, 20), (800, 600))
frame.Show()
app.MainLoop()
Related
I'm trying to load an Html file with wx.html.HtmlWindow. The Html file is linked to an external style sheet (CSS) file.
The problem is the Html window only shows the plain Html file without styling (colors, fonts, etc.)
How can I solve this issue?
HTML code:
<html>
<head>
<title>Embedded Style Sample</title>
<link href="E:\pythonGUI\styles.css" rel="stylesheet" type="text/css"/></head>
<body>
<h1>Embedded Style Sample testing</h1>
<h2>Next Line</h2>
</body>
</html>
CSS code:
h1{
color: #0000FF;
}
h2{
color: #00CCFF;
}
Python code:
import wx
import wx.html
import wx.html2
class MyHtmlFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(
self,
parent,
-1,
title,
size = (600,400)
)
html = wx.html.HtmlWindow(self)
html.LoadPage("E:\\pythonGUI\\newtest.html")
app = wx.App()
frm = MyHtmlFrame(None, "Simple HTML File Viewer")
frm.Show()
app.MainLoop()
the Html file show on HTML window:
If you want complete HTML/CSS support as well as a Javascript engine, consider using wx.html2.WebView instead.
From wxpython docs:
wx.html doesn’t really have CSS support but it does support a few
simple styles: you can use "text-align", "width", "vertical-align" and
"background" with all elements and for SPAN elements a few other
styles are additionally recognized:
color
font-family
font-size (only in point units)
font-style (only “oblique”, “italic” and “normal” values are supported)
font-weight (only “bold” and “normal” values are supported)
text-decoration (only “underline” value is supported)
Using wx.html2.WebView instead of wx.html.HtmlWindow:
import wx
import wx.html2
class About(wx.Frame):
def __init__(self):
wx.Panel.__init__(self,None,-1,title="Title",size=(700,700))
class Test(wx.Frame):
def __init__(self,title,pos,size):
wx.Frame.__init__(self,None,-1,title,pos,size)
self.tester=wx.html2.WebView.New(self)
self.tester.LoadURL("E:\\pythonGUI\\newtest.html")
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = Test("html2 web view", (20, 20), (800, 600))
frame.Show()
app.MainLoop()
I want to load a Web page by wxhtml, and use the code to test.
from enter link description here
But I got a problem: Unknown image data format.
import wx
import wx.html
class MyHtmlFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, size=(600,400))
html = wx.html.HtmlWindow(self)
if "gtk2" in wx.PlatformInfo:
html.SetStandardFonts()
wx.CallAfter(html.LoadPage, "http://www.google.com")
app = wx.PySimpleApp()
frm = MyHtmlFrame(None, "Simple HTML Browser")
frm.Show()
app.MainLoop()
The code you posted worked for me on Xubuntu 14.04 with wxPython 2.8.12.1 and Python 2.7. However, I would highly recommend that you use a different widget. The HtmlWindow is only supposed to be used for basic HTML, not for loading websites. For that, I would recommend using webview, which I believe was added in wxPython 2.9. It would work much better for this sort of thing.
I'm kind of new with wxpython and python itself, sorry for the basic question.
I'm trying to organize my code in a more easy way to manage it. I created this simple example that kind of resume my problem. Basically it is just a window with a button that print a message. I separated it in three simple packages
ef_Main.py - This is the main packages it will import the UI and the application itself.
ef_Tool.py - it is the application that will run all the important code, right now it is just a print statment but will have all the application code.
ef_UI.py - a very basic interface using wxpython.
How it should work:
Run ef_Main.py it will import the interface (ef_UI.py) and the main code (ef_Tool.py). When something is click in the interface it will be ready by the ef_Main and send to ef_Tool to be executed.
My problem is:
I'm not sure how to use bind function to connect this three packages. I believe that it should be in the ef_Main but how it will get the info from the interface and send it to the ef_Tool.py.
And if I want to get some output from the ef_Tool and send it back to the interface. How should I do that.
Here is my code.
#ef_Main.py
import wx
import ef_UI as eU
import ef_Tool as eT
''' Here is where I don't know how to make it works,
if I should put a class here or not, and how to bind
this function with the impTool and impUI'''
#class MyMain(self):
def uiControls(self):
self.Bind(wx.EVT_BUTTON, eU.OnClick(self), eT.MyTools(self))
def main():
app = wx.App(False)
frame = eU.MyFrame()
frame.Show()
app.MainLoop()
if __name__ == "__main__":
main()
=======================
#ef_Tool.py
import wx
'''just a simple as possible function to be execute when it is called '''
class MyTools():
def OnClick(self, event):
#Value = self.MyTextCtrl.GetValue()
print "it is working! "
=======================
#ef_UI.py
import wx
''' very simple interface with only a button and a TextCtrl '''
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Menu Test")
self.panel = wx.Panel(self)
self.MyButton = wx.Button(self.panel, -1, "Button_test", (0, 0))
self.MyTextCtrl = wx.TextCtrl(self.panel, -1, value="just a test", pos=(100, 0))
Thanks in advance!
Emerson
Here is a simple example of fulfilling your requirements. Supposing all your application logic is done in ef_Tool.py and the input for these logic is from ef_UI and the output is also sent to ef_UI.py.
You need to call a method in ef_Tool.py when a button click event occurs in ef_UI. You can invoke this method from MyFrame's method. But you need an obj of MyTools to do this.
so first, create an obj for MyTools in ef_Main.py and pass this object to MyFrame
#ef_Main.py
import wx
import ef_UI as eU
import ef_Tool as eT
def main():
efToolObj = eT.MyTools() # object of MyTools class
app = wx.App(False)
frame = eU.MyFrame(efToolObj) # Pass this to MyFrame so that it can make use of it
frame.Show()
app.MainLoop()
if __name__ == "__main__":
main()
Store this MyTools's object in you MyFrame class. And then use this object to call the corresponding method inside MyTools
#ef_UI.py
import wx
''' very simple interface with only a button and a TextCtrl '''
class MyFrame(wx.Frame):
def __init__(self, efToolObj):
wx.Frame.__init__(self, None, title="Menu Test")
self.panel = wx.Panel(self)
self.efToolObj = efToolObj # save the MyTools object to be used later
self.MyButton = wx.Button(self.panel, -1, "Button_test", (0, 0))
self.MyButton.Bind(wx.EVT_BUTTON, self.onClickEvent) # Bind the click event to an event handling method
self.MyTextCtrl = wx.TextCtrl(self.panel, -1, value="just a test", pos=(100, 0))
def onClickEvent(self,event): #this is called when a button is clicked
res = self.efToolObj.OnClickPrinting(self.MyTextCtrl.GetValue()) #Use the mytools object to call its method to apply logic,also get result values
self.MyTextCtrl.SetValue(res) #use the result values in your UI
You can pass the info you want to send to the application logic in its arguments and get results as return values.
#ef_Tool.py
class MyTools:
def OnClickPrinting(self,textvalue):
#Value = self.MyTextCtrl.GetValue()
print "it is working! ",textvalue
resultstr = "test successful"
return resultstr
Hope this helped.
I'm implementing the help menu of an App done in wxPython. By now, I'm using a txt file opened in a frame. I would like to have hyperlinks in the help text in order to open other txt files in the same frame. However, I don't know how to do this. I don't even know if this is the most elegant way to implement a help menu. Any suggestion will be very useful.
Below you can find part of the code I'm using (you will need a txt file called "Help_Main_App.txt"):
import wx
class Help_Frame(wx.Frame):
title = "Help, I need somebody, help..."
def __init__(self):
wx.Frame.__init__(self, wx.GetApp().TopWindow, title=self.title, size=(450,500))
self.CreateStatusBar()
panel = wx.Panel(self, wx.ID_ANY)
panel.SetBackgroundColour('#ededed')
self.Centre()
vBox = wx.BoxSizer(wx.VERTICAL)
hBox = wx.BoxSizer(wx.HORIZONTAL)
self.textbox = wx.TextCtrl(panel, style=wx.TE_MULTILINE, size=(-1, 295))
hBox.Add(self.textbox, 1, flag=wx.EXPAND)
vBox.Add(hBox, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10)
panel.SetSizer(hBox)
defaultdir, filename = './', 'Help_Main_App.txt'
self.filePath = '/'.join((defaultdir, filename))
self.textbox.LoadFile(self.filePath)
self.textbox.Disable()
class Main_Window(wx.Frame):
def __init__(self, parent, title):
#wx.Frame.__init__(self, parent, title = title, pos = (0, 0), size = wx.DisplaySize())
wx.Frame.__init__(self, parent, title=title, size=(1000,780))
self.Center()
# Setting up the menu.
filemenu = wx.Menu()
helpmenu = wx.Menu()
menuExit = filemenu.Append(wx.ID_EXIT,"&Exit"," Close window and exit program")
menuHelp = helpmenu.Append(wx.ID_HELP, "&Help"," Help of this program")
# Creating the menubar.
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
menuBar.Append(helpmenu,"&Help") # Adding the "helpmenu" to the MenuBar
self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content.
# Set event handlers
self.Bind(wx.EVT_MENU, self.OnHelp, menuHelp)
self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
def OnHelp(self,e):
Help_Frame().Show()
def OnExit(self,e):
self.Close(True) # Close the frame.
def main():
app = wx.App(False)
frame = Main_Window(None, "Main App")
frame.Show()
app.MainLoop()
if __name__ == "__main__" :
main()
I recommend using an HTMLWindow for something simple like that. It can handle only simple HTML, so don't try to make a website with it as HTMLWindow doesn't support CSS or javascript.
I wrote a simple About box using it. You can read about it here:
http://www.blog.pythonlibrary.org/2008/06/11/wxpython-creating-an-about-box/
The basic idea is to subclass HTMLWindow and override its OnLinkClicked method. Then you can use Python's webbrowser to open the user's default browser. Or you can try using subprocess, although that will be a lot less likely to work unless you always know what is installed on your target machines.
Further to Mikes answer if you are able to use wxPython 2.9.4 or above you can consider using the more advanced html2 webview which does support CSS and javascript. Using this you could make the help as a simple website that can be viewed in program.
http://wxpython.org/Phoenix/docs/html/html2.WebView.html
Its also worth mentioning that if (for some strange reason) you don't want to work with you could achieve a similar outcome with a StyledTxtCtrl.
Late to the party but just for the sake of completeness (seeing that the OP's code was using wx.TextCtrl to show the help text), here is an example on how to add and launch hyperlinks using wx.TextCtrl (I have attached any explanations on the code comments):
class HelpDialog(wx.Dialog):
"""Help Dialog."""
def __init__(self, parent, title, style):
"""Init."""
wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY,
title=title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=style)
# We need the 'wx.TE_AUTO_URL' style set.
self.help = wx.TextCtrl(self, wx.ID_ANY, '', DPOS, DSIZE,
wx.TE_AUTO_URL|wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2|wx.TE_WORDWRAP)
# Events - this is the interesting part,
# we catch the mouse on hovering the hyperlink:
self.help.Bind(wx.EVT_TEXT_URL, self.openHlpUrl)
# Show dialog
self.ShowModal()
def openHlpUrl(self, event):
"""Open help URL."""
# We get the starting and ending points on
# the text stored in our ctrl from this event
# and we slice it:
url = self.help.GetValue()[event.GetURLStart():event.GetURLEnd()]
# We want to capture the left up mouse event
# when hovering on the hyperlink:
if event.MouseEvent.LeftDown():
# Let's be wxpythion native and launch the browser this way:
wx.LaunchDefaultBrowser(url)
i am trying to develop python GUI to access webpages. below example is working fine. but i need to pass user credentials(username/password) with in this code.
i dont want to click on that button. just i need to fill text boxes in login page
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
self.browser.LoadURL("http://wiki.python.org/moin/GuiProgramming?action=login")
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.Show()
app.MainLoop()
The "Use javascript" answer is certainly helpful, but with recent versions of wxPython anyway, it won't run unless wx.html2.EVT_WEB_VIEW_LOADED is changed to wx.html2.EVT_WEBVIEW_LOADED ("WEB_VIEW changed to "WEBVIEW").
Use javascript. Simple sample code below.
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
self.browser.LoadURL("http://wiki.python.org/moin/GuiProgramming?action=login")
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
# We have to bind an event so the javascript is only run once the page
# is loaded.
self.Bind(wx.html2.EVT_WEB_VIEW_LOADED, self.OnPageLoaded,
self.browser)
def OnPageLoaded(self, evt):
self.browser.RunScript("""
// There are probably better ways to get the elements you
// want, but this works.
document.getElementsByName('name')[0].value="hist";
document.getElementsByName('password')[0].value="bar";
document.getElementById('openididentifier').value="ident";
// If you want to submit the form you can use something like
//document.getElementsByName('login')[1].click()
""")
# And you probably want to unbind the event here
self.Bind(wx.html2.EVT_WEB_VIEW_LOADED, None,
self.browser)
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.Show()
app.MainLoop()
I would check out Selenium. It's an open source web navigating automation tool which has developed an awesome module for python. I've used it to automate logging into multiple different websites and you could easily slap a wx GUI on top of it.