<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Mouse Vs. The Python &#187; wxPython</title>
	<atom:link href="http://www.blog.pythonlibrary.org/tag/wxpython/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.blog.pythonlibrary.org</link>
	<description>Python Programming from the Frontlines</description>
	<lastBuildDate>Sun, 08 Jan 2012 12:45:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>January 2012 Pyowa Wrap Up</title>
		<link>http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/</link>
		<comments>http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 16:06:00 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Pyowa]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2183</guid>
		<description><![CDATA[Last Thursday (the 5th) I attended Pyowa, the local Iowa Python Users group I founded a few years ago. We had Scott Peterson from Principal Financial Group come and talk to us about Library Gadget, a cool Django-based website he created to track what library books his family has checked out. Now he has lots [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/" data-url="http://bit.ly/zjs7vA" data-text="January 2012 Pyowa Wrap Up" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/";
			reddit_title = "January 2012 Pyowa Wrap Up";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/"></g:plusone></div></div><p>Last Thursday (the 5th) I attended <a href="http://www.pyowa.org/" target="_blank">Pyowa</a>, the local Iowa Python Users group I founded a few years ago. We had Scott Peterson from Principal Financial Group come and talk to us about <a href="http://www.librarygadget.com/" target="_blank">Library Gadget</a>, a cool Django-based website he created to track what library books his family has checked out. Now he has lots of users using his website. It not only tracks the books you have borrowed, but it&#8217;ll auto-renew them if it can and let you know if you&#8217;re books are overdue.</p>
<p>He spent most of his time talking about the backend stuff behind the website though. Such as why he chose Amazon Web Services, how he uses <a href="http://projects.puppetlabs.com/projects/puppet" target="_blank">Puppet</a>, <a href="http://vagrantup.com/docs/getting-started/setup.html" target="_blank">Vagrant</a> and <a href="http://docs.fabfile.org/en/1.3.3/index.html" target="_blank">Fabric</a> to manage his server&#8217;s settings and back them up.</p>
<p>The second talk was done by myself and I spoke on my <a href="http://www.medialocker.pythonlibrary.org/" target="_blank">MediaLocker</a> project, an open source wxPython application that is supposed to help you track your media library. Most of my time was spent telling the story behind the project and showing a demo. Then I took some questions. </p>
<p>Overall, I&#8217;d say that we had a really good meeting with 10 people showing up. Next month, on February 2nd, we&#8217;re bringing in the BIG guns though. We have <a href="http://www.doughellmann.com/" target="_blank">Doug Hellman</a> and <a href="http://holdenweb.com/" target="_blank">Steve Holden</a> scheduled to Skype in and talk to us.</p>
<p>Doug Hellman is the author of <a href="http://www.amazon.com/gp/product/0321767349/ref=as_li_ss_tl?ie=UTF8&#038;tag=thmovsthpy-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321767349" target="_blank" rel="nofollow">The Python Standard Library By Example</a>, is a senior developer with Racemi, Inc., and communications director of the Python Software Foundation. He has programmed with Python since version 1.4, and has worked on multiple platforms in mapping, medical publishing, banking, and data center automation. Hellmann was previously columnist and editor-in-chief for Python Magazine and, since 2007, has blogged the popular Python Module of the Week</p>
<p>Steve Holden is chairman of the Python Software Foundation and author of <a href="http://www.amazon.com/gp/product/0735710902/ref=as_li_ss_tl?ie=UTF8&#038;tag=thmovsthpy-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0735710902" target="_blank" rel="nofollow">Python Web Programming</a>. He owns Python consulting business and does Python training.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2012/01/07/january-2012-pyowa-wrap-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wxPython Project Phoenix Documentation Beta Released</title>
		<link>http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 17:15:25 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2142</guid>
		<description><![CDATA[The wxPython project&#8217;s Phoenix release is slowly coming along. Phoenix is the codename for the new wxPython that will support both Python 2.x and 3.x. Anyway, Andrea Gavana has put together some autogenerated documentation using Sphinx on top of Doxygen. You can read about the announcement including any known issues on the wxPython mailing list. [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/" data-url="http://bit.ly/sphYsy" data-text="wxPython Project Phoenix Documentation Beta Released" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/";
			reddit_title = "wxPython Project Phoenix Documentation Beta Released";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/"></g:plusone></div></div><p>The wxPython project&#8217;s Phoenix release is slowly coming along. Phoenix is the codename for the new wxPython that will support both Python 2.x and 3.x. Anyway, Andrea Gavana has put together some <a href="http://xoomer.virgilio.it/infinity77/Phoenix/main.html" target="_blank">autogenerated documentation</a> using Sphinx on top of Doxygen. You can read about the announcement including any known issues on the wxPython <a href="https://groups.google.com/forum/#!topic/wxpython-users/kz2b6LY7A5I" target="_blank">mailing list</a>.</p>
<p>For those of you who are brave, you can also read about a snapshot build of Phoenix <a href=" https://groups.google.com/forum/#!topic/wxpython-dev/b_PfRG3LOXY" target="_blank">here</a> or download the a tarball <a href="http://wxpython.org/Phoenix/snapshot-builds/" target="_blank">here</a>. Note: These tarballs are only for Mac and Window users and they are not completely working.</p>
<p>For those of you who don&#8217;t know anything about Project Phoenix, you can read about it on the <a href="http://wiki.wxpython.org/ProjectPhoenix" target="_blank">wxPython wiki</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/12/14/wxpython-phoenix-documentation-beta-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>wxPython 101: Creating Taskbar Icons</title>
		<link>http://www.blog.pythonlibrary.org/2011/12/13/wxpython-101-creating-taskbar-icons/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/12/13/wxpython-101-creating-taskbar-icons/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 02:27:30 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1997</guid>
		<description><![CDATA[Have you ever wondered how to create those little status icons in the Windows System Tray that usually appear on the lower right of your screen? The wxPython toolkit provides a pretty simple way to do just that and this article will walk you through the process. Working the Code For reasons I don&#8217;t quite [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/12/13/wxpython-101-creating-taskbar-icons/" data-url="http://bit.ly/teqbRo" data-text="wxPython 101: Creating Taskbar Icons" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/12/13/wxpython-101-creating-taskbar-icons/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div></div><p>Have you ever wondered how to create those little status icons in the Windows System Tray that usually appear on the lower right of your screen? The wxPython toolkit provides a pretty simple way to do just that and this article will walk you through the process.<span id="more-1997"></span></p>
<h2>Working the Code</h2>
<p>For reasons I don&#8217;t quite understand, the wx component we want is wx.TaskBarIcon. I assume it&#8217;s called that because the System Tray is part of the TaskBar or maybe they don&#8217;t differentiate between the TaskBar and the tray area in other operating systems. Anyway, first you need an icon to use. You can get your image wherever you like. In this example, we&#8217;re going to use an an &#8220;envelope&#8221; image that I turned into Python code using wxPython&#8217;s handy img2py utility. When you run an image through img2py, you&#8217;ll end up with something like this:</p>
<pre class="python"><span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># This file was generated by img2py.py</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #ff7700;font-weight:bold;">from</span> wx <span style="color: #ff7700;font-weight:bold;">import</span> ImageFromStream, BitmapFromImage
<span style="color: #ff7700;font-weight:bold;">from</span> wx <span style="color: #ff7700;font-weight:bold;">import</span> EmptyIcon
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">cStringIO</span>, <span style="color: #dc143c;">zlib</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getData<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">zlib</span>.<span style="color: black;">decompress</span><span style="color: black;">&#40;</span>
<span style="color: #483d8b;">'x<span style="color: #000099; font-weight: bold;">\x</span>da<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>86<span style="color: #000099; font-weight: bold;">\x</span>01y<span style="color: #000099; font-weight: bold;">\x</span>fe<span style="color: #000099; font-weight: bold;">\x</span>89PNG<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>1a<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\r</span>IHDR<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00 <span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00 <span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\x</span>06<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00szz<span style="color: #000099; font-weight: bold;">\x</span>f4<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>04sBIT<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\x</span>08|<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>08d<span style="color: #000099; font-weight: bold;">\x</span>88<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>01=IDATX<span style="color: #000099; font-weight: bold;">\x</span>85<span style="color: #000099; font-weight: bold;">\x</span>ed<span style="color: #000099; font-weight: bold;">\x</span>97[<span style="color: #000099; font-weight: bold;">\x</span>9a<span style="color: #000099; font-weight: bold;">\x</span>83 <span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\x</span>85Ol<span style="color: #000099; font-weight: bold;">\x</span>f7<span style="color: #000099; font-weight: bold;">\x</span>1566#<span style="color: #000099; font-weight: bold;">\x</span>ec<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>ac,<span style="color: #000099; font-weight: bold;">\x</span>ace<span style="color: #000099; font-weight: bold;">\x</span>1e<span style="color: #000099; font-weight: bold;">\x</span>e4b <span style="color: #000099; font-weight: bold;">\x</span>fa<span style="color: #000099; font-weight: bold;">\x</span>a9<span style="color: #000099; font-weight: bold;">\x</span>a3<span style="color: #000099; font-weight: bold;">\x</span>e5<span style="color: #000099; font-weight: bold;">\x</span>c5&lt;<span style="color: #000099; font-weight: bold;">\x</span>15$9<span style="color: #000099; font-weight: bold;">\x</span>7fO<span style="color: #000099; font-weight: bold;">\x</span>c0<span style="color: #000099; font-weight: bold;">\x</span>0b<span style="color: #000099; font-weight: bold;">\x</span>d1<span style="color: #000099; font-weight: bold;">\x</span>f0@<span style="color: #000099; font-weight: bold;">\x</span>cf<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>ba<span style="color: #000099; font-weight: bold;">\x</span>aa<span style="color: #000099; font-weight: bold;">\x</span>df<span style="color: #000099; font-weight: bold;">\x</span>007<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>80g<span style="color: #000099; font-weight: bold;">\x</span>fa1<span style="color: #000099; font-weight: bold;">\x</span>fe<span style="color: #000099; font-weight: bold;">\x</span>fe<span style="color: #000099; font-weight: bold;">\x</span>84o<span style="color: #000099; font-weight: bold;">\x</span>89ZkA<span style="color: #000099; font-weight: bold;">\x</span>c3<span style="color: #000099; font-weight: bold;">\x</span>83<span style="color: #000099; font-weight: bold;">\x</span>04<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>8c<span style="color: #000099; font-weight: bold;">\x</span>e3x<span style="color: #000099; font-weight: bold;">\x</span>a1,<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>08p<span style="color: #000099; font-weight: bold;">\x</span>ce<span style="color: #000099; font-weight: bold;">\x</span>89Y<span style="color: #000099; font-weight: bold;">\x</span>d1<span style="color: #000099; font-weight: bold;">\x</span>82<span style="color: #000099; font-weight: bold;">\x</span>fa<span style="color: #000099; font-weight: bold;">\x</span>e2y<span style="color: #000099; font-weight: bold;">\x</span>c2P<span style="color: #000099; font-weight: bold;">\x</span>c5<span style="color: #000099; font-weight: bold;">\x</span>1b<span style="color: #000099; font-weight: bold;">\x</span>00c<span style="color: #000099; font-weight: bold;">\x</span>cc<span style="color: #000099; font-weight: bold;">\x</span>05<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>10Sg<span style="color: #000099; font-weight: bold;">\x</span>9ds0<span style="color: #000099; font-weight: bold;">\x</span>c6<span style="color: #000099; font-weight: bold;">\x</span>ac<span style="color: #000099; font-weight: bold;">\x</span>030<span style="color: #000099; font-weight: bold;">\x</span>f3<span style="color: #000099; font-weight: bold;">\x</span>05<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>94<span style="color: #000099; font-weight: bold;">\x</span>c5<span style="color: #000099; font-weight: bold;">\x</span>99y<span style="color: #000099; font-weight: bold;">\x</span>1d<span style="color: #000099; font-weight: bold;">\x</span>e0<span style="color: #000099; font-weight: bold;">\\</span><span style="color: #000099; font-weight: bold;">\x</span>88<span style="color: #000099; font-weight: bold;">\x</span>c9z<span style="color: #000099; font-weight: bold;">\x</span>e7l<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>147<span style="color: #000099; font-weight: bold;">\x</span>ea*<span style="color: #000099; font-weight: bold;">\x</span>f5<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>fe<span style="color: #000099; font-weight: bold;">\x</span>0fB<span style="color: #000099; font-weight: bold;">\x</span>f6<span style="color: #000099; font-weight: bold;">\x</span>bc<span style="color: #000099; font-weight: bold;">\x</span>fcs<span style="color: #000099; font-weight: bold;">\x</span>fd<span style="color: #000099; font-weight: bold;">\x</span>90-<span style="color: #000099; font-weight: bold;">\x</span>de<span style="color: #000099; font-weight: bold;">\x</span>07<span style="color: #000099; font-weight: bold;">\x</span>8eC<span style="color: #000099; font-weight: bold;">\x</span>c8<span style="color: #000099; font-weight: bold;">\x</span>9e<span style="color: #000099; font-weight: bold;">\x</span>17<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>dbI]<span style="color: #000099; font-weight: bold;">\x</span>bdz#:<span style="color: #000099; font-weight: bold;">\x</span>06Q<span style="color: #000099; font-weight: bold;">\x</span>f7<span style="color: #000099; font-weight: bold;">\x</span>bc8<span style="color: #000099; font-weight: bold;">\x</span>b2<span style="color: #000099; font-weight: bold;">\x</span>1b`<span style="color: #000099; font-weight: bold;">\x</span>1f<span style="color: #000099; font-weight: bold;">\x</span>c4R<span style="color: #000099; font-weight: bold;">\x</span>cf<span style="color: #000099; font-weight: bold;">\x</span>83<span style="color: #000099; font-weight: bold;">\x</span>b8<span style="color: #000099; font-weight: bold;">\x</span>be<span style="color: #000099; font-weight: bold;">\x</span>1b %<span style="color: #000099; font-weight: bold;">\x</span>16<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>f3Z<span style="color: #000099; font-weight: bold;">\x</span>cfu<span style="color: #000099; font-weight: bold;">\x</span>e1<span style="color: #000099; font-weight: bold;">\x</span>dd<span style="color: #000099; font-weight: bold;">\x</span>0eL<span style="color: #000099; font-weight: bold;">\x</span>89<span style="color: #000099; font-weight: bold;">\x</span>de<span style="color: #000099; font-weight: bold;">\x</span>bf<span style="color: #000099; font-weight: bold;">\x</span>c0<span style="color: #000099; font-weight: bold;">\x</span>cc3<span style="color: #000099; font-weight: bold;">\'</span>lU<span style="color: #000099; font-weight: bold;">\x</span>b0=<span style="color: #000099; font-weight: bold;">\x</span>e7<span style="color: #000099; font-weight: bold;">\x</span>cc<span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\x</span>ef<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>fd<span style="color: #000099; font-weight: bold;">\x</span>02<span style="color: #000099; font-weight: bold;">\x</span>88<span style="color: #000099; font-weight: bold;">\x</span>8c<span style="color: #000099; font-weight: bold;">\x</span>a7:<span style="color: #000099; font-weight: bold;">\x</span>1b<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>bd<span style="color: #000099; font-weight: bold;">\x</span>f7<span style="color: #000099; font-weight: bold;">\x</span>d1<span style="color: #000099; font-weight: bold;">\x</span>ca<span style="color: #000099; font-weight: bold;">\x</span>90<span style="color: #000099; font-weight: bold;">\x</span>0b<span style="color: #000099; font-weight: bold;">\'</span><span style="color: #000099; font-weight: bold;">\x</span>b1:<span style="color: #000099; font-weight: bold;">\x</span>8a<span style="color: #000099; font-weight: bold;">\x</span>f8<span style="color: #000099; font-weight: bold;">\x</span>b4&gt;A<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>94|<span style="color: #000099; font-weight: bold;">\x</span>dd<span style="color: #000099; font-weight: bold;">\x</span>81E<span style="color: #000099; font-weight: bold;">\x</span>80)y~|(<span style="color: #000099; font-weight: bold;">\x</span>17<span style="color: #000099; font-weight: bold;">\x</span>d6<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>15&quot;0<span style="color: #000099; font-weight: bold;">\x</span>87<span style="color: #000099; font-weight: bold;">\x</span>e8`<span style="color: #000099; font-weight: bold;">\x</span>c9<span style="color: #000099; font-weight: bold;">\x</span>df<span style="color: #000099; font-weight: bold;">\x</span>00@<span style="color: #000099; font-weight: bold;">\x</span>d9v<span style="color: #000099; font-weight: bold;">\x</span>19<span style="color: #000099; font-weight: bold;">\x</span>b2<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>f0|}-&lt;<span style="color: #000099; font-weight: bold;">\x</span>1f3<span style="color: #000099; font-weight: bold;">\x</span>9bXo<span style="color: #000099; font-weight: bold;">\x</span>e3<span style="color: #000099; font-weight: bold;">\x</span>1e(<span style="color: #000099; font-weight: bold;">\x</span>e2u<span style="color: #000099; font-weight: bold;">\x</span>cf<span style="color: #000099; font-weight: bold;">\x</span>ea<span style="color: #000099; font-weight: bold;">\x</span>cd<span style="color: #000099; font-weight: bold;">\x</span>b4},<span style="color: #000099; font-weight: bold;">\x</span>f7<span style="color: #000099; font-weight: bold;">\x</span>c4<span style="color: #000099; font-weight: bold;">\n</span>@<span style="color: #000099; font-weight: bold;">\x</span>b1<span style="color: #000099; font-weight: bold;">\x</span>fd<span style="color: #000099; font-weight: bold;">\x</span>98<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>d0<span style="color: #000099; font-weight: bold;">\x</span>dax<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\x</span>a2y<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>b5q<span style="color: #000099; font-weight: bold;">\x</span>1e<span style="color: #000099; font-weight: bold;">\x</span>c8<span style="color: #000099; font-weight: bold;">\x</span>a6<span style="color: #000099; font-weight: bold;">\x</span>87<span style="color: #000099; font-weight: bold;">\x</span>d1<span style="color: #000099; font-weight: bold;">\x</span>99<span style="color: #000099; font-weight: bold;">\x</span>d6<span style="color: #000099; font-weight: bold;">\x</span>eb<span style="color: #000099; font-weight: bold;">\x</span>e3<span style="color: #000099; font-weight: bold;">\x</span>aaz<span style="color: #000099; font-weight: bold;">\x</span>fa0<span style="color: #000099; font-weight: bold;">\x</span>e9<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>f5J<span style="color: #000099; font-weight: bold;">\x</span>96<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>c2<span style="color: #000099; font-weight: bold;">\x</span>e7<span style="color: #000099; font-weight: bold;">\x</span>fd5<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00-@<span style="color: #000099; font-weight: bold;">\x</span>af<span style="color: #000099; font-weight: bold;">\x</span>e8<span style="color: #000099; font-weight: bold;">\x</span>feZ~<span style="color: #000099; font-weight: bold;">\x</span>03t<span style="color: #000099; font-weight: bold;">\x</span>07<span style="color: #000099; font-weight: bold;">\x</span>f8<span style="color: #000099; font-weight: bold;">\x</span>03<span style="color: #000099; font-weight: bold;">\x</span>82<span style="color: #000099; font-weight: bold;">\x</span>ac<span style="color: #000099; font-weight: bold;">\</span>
<span style="color: #000099; font-weight: bold;">\x</span>a4VT<span style="color: #000099; font-weight: bold;">\x</span>fd<span style="color: #000099; font-weight: bold;">\x</span>cd<span style="color: #000099; font-weight: bold;">\x</span>a3<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00IEND<span style="color: #000099; font-weight: bold;">\x</span>aeB`<span style="color: #000099; font-weight: bold;">\x</span>82<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>a7<span style="color: #000099; font-weight: bold;">\x</span>a9<span style="color: #000099; font-weight: bold;">\x</span>a8'</span> <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getBitmap<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> BitmapFromImage<span style="color: black;">&#40;</span>getImage<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getImage<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    stream = <span style="color: #dc143c;">cStringIO</span>.<span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span>getData<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ImageFromStream<span style="color: black;">&#40;</span>stream<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getIcon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    icon = EmptyIcon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    icon.<span style="color: black;">CopyFromBitmap</span><span style="color: black;">&#40;</span>getBitmap<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> icon</pre>
<p>The image data is all in the <strong>getData</strong> function. I am going to call this file &#8220;email_ico.py&#8221;. We&#8217;ll import it into our main program and call its <strong>getIcon</strong> method to acquire the icon we want to use. Let&#8217;s take a look at the main application now:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">from</span> mail_ico <span style="color: #ff7700;font-weight:bold;">import</span> getIcon
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MailIcon<span style="color: black;">&#40;</span>wx.<span style="color: black;">TaskBarIcon</span><span style="color: black;">&#41;</span>:
    TBMENU_RESTORE = wx.<span style="color: black;">NewId</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    TBMENU_CLOSE   = wx.<span style="color: black;">NewId</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    TBMENU_CHANGE  = wx.<span style="color: black;">NewId</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    TBMENU_REMOVE  = wx.<span style="color: black;">NewId</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, frame<span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">TaskBarIcon</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">frame</span> = frame
&nbsp;
        <span style="color: #808080; font-style: italic;"># Set the image</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span> = getIcon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">SetIcon</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span>, <span style="color: #483d8b;">&quot;Test&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># bind some events</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_MENU</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnTaskBarClose</span>, <span style="color: #008000;">id</span>=<span style="color: #008000;">self</span>.<span style="color: black;">TBMENU_CLOSE</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_TASKBAR_LEFT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnTaskBarLeftClick</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> CreatePopupMenu<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, evt=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        This method is called by the base class when it needs to popup
        the menu for the default EVT_RIGHT_DOWN event.  Just create
        the menu how you want it and return it from this function,
        the base class takes care of the rest.
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        menu = wx.<span style="color: black;">Menu</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        menu.<span style="color: black;">Append</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">TBMENU_RESTORE</span>, <span style="color: #483d8b;">&quot;Open Program&quot;</span><span style="color: black;">&#41;</span>
        menu.<span style="color: black;">Append</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">TBMENU_CHANGE</span>, <span style="color: #483d8b;">&quot;Show all the Items&quot;</span><span style="color: black;">&#41;</span>
        menu.<span style="color: black;">AppendSeparator</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        menu.<span style="color: black;">Append</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">TBMENU_CLOSE</span>,   <span style="color: #483d8b;">&quot;Exit Program&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> menu
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> OnTaskBarActivate<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, evt<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> OnTaskBarClose<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, evt<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Destroy the taskbar icon and frame from the taskbar icon itself
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">frame</span>.<span style="color: black;">Close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> OnTaskBarLeftClick<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, evt<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Create the right-click menu
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        menu = <span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span>.<span style="color: black;">CreatePopupMenu</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">PopupMenu</span><span style="color: black;">&#40;</span>menu<span style="color: black;">&#41;</span>
        menu.<span style="color: black;">Destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MyForm<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, wx.<span style="color: black;">ID_ANY</span>, <span style="color: #483d8b;">&quot;Tutorial&quot;</span>, size=<span style="color: black;">&#40;</span><span style="color: #ff4500;">500</span>,<span style="color: #ff4500;">500</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        panel = wx.<span style="color: black;">Panel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span> = MailIcon<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_CLOSE</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onClose</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onClose<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, evt<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Destroy the taskbar icon and the frame
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span>.<span style="color: black;">RemoveIcon</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">tbIcon</span>.<span style="color: black;">Destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># Run the program</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
    frame = MyForm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>The first class is basically copied straight out of the wxPython demo and simplified slightly. You can look there if you need a more complete example. Anyway, we bind a couple events in our sub-classed TaskBarIcon that allow us to close the application and show a menu, respectively. You will also note that we set the icon we created in the <strong>__init__</strong> simply by calling its <strong>SetIcon</strong> method and passing in a string for its tooltip.</p>
<p>In the close method, we call the frame directly that we want it to close. A better method would be to use pubsub here. If you want to pause a moment and read about pubsub, I&#8217;ve written a little <a href="http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/" target="_blank">post </a>about it too. The rest of the code is pretty self-explanatory.</p>
<p>Now we can move on to the wx.Frame sub-class. Here we basically just instantiate the TaskBarIcon class that we created earlier and we bind the frame to <strong>EVT_CLOSE</strong>. You might wonder about this. There are some got&#8217;chas with using the TaskBarIcon on Windows. If I just tell the frame to close, it closes just fine, but the icon remains and Python just kind of hangs in lala land. If you only allow the user to close using the task bar icon&#8217;s right-click menu, then you could just add a <strong>RemoveIcon</strong> method and a self.Destroy() there and you&#8217;d be good to go (for some reason, RemoveIcon isn&#8217;t enough to get rid of the TaskBarIcon, so you also need to tell it to Destroy itself too) But if you allow the user to press the little &#8220;x&#8221; in the upper right-hand corner, then you&#8217;ll need to catch <strong>EVT_CLOSE</strong> and deal with it appropriately. When you do catch this event, you can NOT just call <strong>self.Close()</strong> or you&#8217;ll end up in an infinite loop, which is why we call <strong>self.Destroy()</strong> instead. </p>
<h2>Wrapping Up</h2>
<p>Now you should be able to create your own TaskBarIcon application. I highly recommend looking at the wxPython demo to see what else you can do with it. I think adding an icon can add a bit of polish to your application, especially if you need to have it running hidden for a while and then make it pop-up at the user&#8217;s command.</p>
<h2>Further Reading</h2>
<ul>
<li><a href="http://wiki.wxpython.org/FlashingTaskbarIcon" target="_blank">Create a Flashing TaskBarIcon</a></li>
<li><a href="http://www.techniqal.com/blog/2005/07/20/creating-a-task-bar-icon-in-wxpython/" target="_blank">Another blog&#8217;s</a> take on this subject</li>
<li>The TaskBarIcon <a href="http://www.wxpython.org/docs/api/wx.TaskBarIcon-class.html" target="_blank">documentation</a></li>
</ul>
<h2>Source</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/TBI_src.tar'>TBI_src.tar</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/TBI_src.zip'>TBI_src.zip</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/12/13/wxpython-101-creating-taskbar-icons/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ANN: MediaLocker – A wxPython App to Track Your Media</title>
		<link>http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 14:11:01 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[wxPython]]></category>
		<category><![CDATA[MediaLocker]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2112</guid>
		<description><![CDATA[Background ================ This is the first release of a real project that I&#8217;ve been involved in. I had written an article last month that inspired Werner Bruhin to want to take it and make it into a demonstration program for new wxPython programmers in how to do MVC and CRUD while interfacing with a database. [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/" data-url="http://bit.ly/swrK6M" data-text="ANN: MediaLocker – A wxPython App to Track Your Media" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/";
			reddit_title = "ANN: MediaLocker – A wxPython App to Track Your Media";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/"></g:plusone></div></div><p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/medialocker1.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/medialocker1-300x168.png" alt="" title="medialocker_windows" width="300" height="168" class="aligncenter size-medium wp-image-2120" /></a></p>
<p>Background<br />
================</p>
<p>This is the first release of a real project that I&#8217;ve been involved in. I had written an article last month that inspired Werner Bruhin to want to take it and make it into a demonstration program for new wxPython programmers in how to do MVC and CRUD while interfacing with a database. Thus, MediaLocker was born. We hope you like it.</p>
<p>Description<br />
================</p>
<p>A wxPython database application that can help you keep track of your media. Currently, it only tracks your Book library. You can read more about the project’s development in the following two articles:</p>
<ul>
<li><a href="http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/" target="_blank">Improving MediaLocker: wxPython, SQLAlchemy and MVC</a></li>
<li><a href="http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/" target="_blank">wxPython and SQLAlchemy: An Intro to MVC and CRUD</a></li>
</ul>
<p>Requirements<br />
================</p>
<p>- Python 2.6+<br />
- wxPython 2.8.11+ with the new pubsub (download <a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/pubsub.zip'>here</a>) or wxPython 2.9.3<br />
- <a href="http://www.sqlalchemy.org" target="_blank">SQLAlchemy </a>0.7.3+<br />
- <a href="http://pypi.python.org/pypi/ObjectListView" target="_blank">ObjectListView </a>1.2</p>
<p>Configuration<br />
================</p>
<p>After you have downloaded the source, run &#8220;python setup_lib.py develop&#8221; in the main folder before you try to run &#8220;mediaLocker.py&#8221;. If you are on wxPython 2.8, download the pubsub path (above) and extract it to &#8220;C:\Python27\Lib\site-packages\wx-2.9.2-msw\wx\lib&#8221; (or wherever your wxPython is installed).</p>
<p>Source<br />
================</p>
<p>You can download the source from BitBucket: <a href="https://bitbucket.org/driscollis/medialocker" target="_blank">https://bitbucket.org/driscollis/medialocker<br />
</a> </p>
<p>You can also just download a snapshot of the current files here (uploaded 2011.12.09 @ 1138 hrs CST):</p>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/medialocker.zip'>medialocker.zip</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/12/medialocker.tar'>medialocker.tar</a></li>
<li>Or just download from the tip on <a href="https://bitbucket.org/driscollis/medialocker/downloads" target="_blank">bitbucket</a></li>
</ul>
<p>How you can help<br />
================</p>
<p>Download the software and report bugs on BitBucket. We also happily accept feature requests, especially if they include patches or code.</p>
<p><em>Note: This has only been tested on Windows XP and 7</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%e2%80%93-a-wxpython-app-to-track-your-media/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Improving MediaLocker: wxPython, SQLAlchemy, and MVC</title>
		<link>http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 02:26:54 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Education]]></category>
		<category><![CDATA[SqlAlchemy]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2092</guid>
		<description><![CDATA[This blog ran an article about wxPython, SQLAlchemy, CRUD and MVC earlier this month. The program that we created in that post was dubbed &#8220;MediaLocker&#8221;, whether or not it was explicitly stated as such. Anyway, since then, I have received a couple comments about improving the program. One came from Michael Bayer, one of the [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/" data-url="http://bit.ly/vJC7nC" data-text="Improving MediaLocker: wxPython, SQLAlchemy, and MVC" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/";
			reddit_title = "Improving MediaLocker: wxPython, SQLAlchemy, and MVC";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/"></g:plusone></div></div><p>This blog ran an article about wxPython, SQLAlchemy, CRUD and MVC earlier this month. The program that we created in that post was dubbed &#8220;MediaLocker&#8221;, whether or not it was explicitly stated as such. Anyway, since then, I have received a couple comments about improving the program. One came from <a href="http://techspot.zzzeek.org/" target="_blank">Michael Bayer</a>, one of the creative minds behind SQLAlchemy itself and the other comments came from Werner Bruhin, a nice guy who haunts the wxPython mailing list, helping new users. So I went about creating an improved version of the code following their advice. Werner then improved it a bit more. So in this article, we will be looking at improving the code, first with my example and then with his. Enough talk though; let&#8217;s get to the meat of story!<span id="more-2092"></span></p>
<h2>Making MediaLocker Better</h2>
<p>Michael Bayer and Werner Bruhin both thought that I should only connect to the database once as that&#8217;s a fairly &#8220;expensive&#8221; operation. This could be an issue if there were multiple sessions existing at the same time too, but even in my original code, I made sure to close the session so that wouldn&#8217;t happen. When I wrote my original version, I thought about separating out the session creation, but ended up going with what I thought was more straightforward. To fix this niggling issue, I changed the code so that I passed the session object around instead of constantly calling my controller&#8217;s <strong>connectToDatabase</strong> function. You can read more about Sessions <a href="http://www.sqlalchemy.org/docs/orm/session.html?highlight=session" target="_blank">here</a>. See the code snippet from <strong>mediaLocker.py</strong>:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">class</span> BookPanel<span style="color: black;">&#40;</span>wx.<span style="color: black;">Panel</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Panel</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;devdata.db&quot;</span><span style="color: black;">&#41;</span>:
            controller.<span style="color: black;">setupDatabase</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">session</span> = controller.<span style="color: black;">connectToDatabase</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = controller.<span style="color: black;">getAllRecords</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">session</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span></pre>
<p>Note that we have a little conditional right up front that will create the database if it doesn&#8217;t already exist. Next I create the session object in the main GUI as a property of the panel sub-class. Then I pass it where ever I need to. One example can be seen above where I pass the session object to the controller&#8217;s <strong>getAllRecords</strong> method. </p>
<p>Another big change was to remove the ObjectListView model from <strong>model.py</strong> and just use the SQLAlchemy table class instead:</p>
<pre class="python"><span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>DeclarativeBase<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    __tablename__ = <span style="color: #483d8b;">&quot;book&quot;</span>
&nbsp;
    <span style="color: #008000;">id</span> = Column<span style="color: black;">&#40;</span>Integer, primary_key=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    author_id = Column<span style="color: black;">&#40;</span>Integer, ForeignKey<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;person.id&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    title = Column<span style="color: black;">&#40;</span>Unicode<span style="color: black;">&#41;</span>
    isbn = Column<span style="color: black;">&#40;</span>Unicode<span style="color: black;">&#41;</span>
    publisher = Column<span style="color: black;">&#40;</span>Unicode<span style="color: black;">&#41;</span>
    person = relation<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Person&quot;</span>, backref=<span style="color: #483d8b;">&quot;books&quot;</span>, cascade_backrefs=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
    @<span style="color: #008000;">property</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> author<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;%s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">person</span>.<span style="color: black;">first_name</span>, <span style="color: #008000;">self</span>.<span style="color: black;">person</span>.<span style="color: black;">last_name</span><span style="color: black;">&#41;</span></pre>
<p>This is actually mostly the same as the original class except that it uses SQLAlchemy constructs. I also needed to add a special property to return the author&#8217;s full name for display in our widget, so we used Python&#8217;s built-in function: <a href="http://docs.python.org/library/functions.html#property" target="_blank">property</a> which returns a property attribute. It&#8217;s easier to understand if you just look at the code. As you can see, we applied <strong>property </strong>as a decorator to the <strong>author </strong>method.</p>
<h2>Werner&#8217;s Additions</h2>
<p>Werner&#8217;s additions are mostly adding more explicit imports in the model. The biggest change in the model is as follows:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>, <span style="color: #483d8b;">'frozen'</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># needed when having multiple versions of SA installed</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> pkg_resources
    pkg_resources.<span style="color: black;">require</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;sqlalchemy&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># get latest version</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> sqlalchemy as sa
<span style="color: #ff7700;font-weight:bold;">import</span> sqlalchemy.<span style="color: black;">orm</span> as sao
<span style="color: #ff7700;font-weight:bold;">import</span> sqlalchemy.<span style="color: black;">ext</span>.<span style="color: black;">declarative</span> as sad
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">ext</span>.<span style="color: black;">hybrid</span> <span style="color: #ff7700;font-weight:bold;">import</span> hybrid_property
&nbsp;
maker = sao.<span style="color: black;">sessionmaker</span><span style="color: black;">&#40;</span>autoflush=<span style="color: #008000;">True</span>, autocommit=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
DBSession = sao.<span style="color: black;">scoped_session</span><span style="color: black;">&#40;</span>maker<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Base<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Extend the base class
&nbsp;
    - Provides a nicer representation when a class instance is printed.
        Found on the SA wiki, not included with TG
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;%s(%s)&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
                 <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.__class__.__name__<span style="color: black;">&#41;</span>,
                 <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;%s=%r&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>key, <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                            <span style="color: #ff7700;font-weight:bold;">for</span> key <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: #0000cd;">__dict__</span>.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> key.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
DeclarativeBase = sad.<span style="color: black;">declarative_base</span><span style="color: black;">&#40;</span>cls=Base<span style="color: black;">&#41;</span>
metadata = DeclarativeBase.<span style="color: black;">metadata</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> init_model<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Call me before using any of the tables or classes in the model.&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    DBSession.<span style="color: black;">configure</span><span style="color: black;">&#40;</span>bind=engine<span style="color: black;">&#41;</span></pre>
<p>The first few lines are for people with SetupTools / easy_install on their machine. If the user has multiple versions of SQLALchemy installed, it will force it to use the latest. Most of the other imports are shortened to make it very obvious where various classes and attributes come from. I am honestly not familiar with the <strong>hybrid_property</strong>, so here&#8217;s what its docstring had to say:</p>
<p><em>A decorator which allows definition of a Python descriptor with both instance-level and class-level behavior.</em></p>
<p>You can read more here: <a href="http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html" target="_blank">http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html</a></p>
<p>Werner also added a little <strong>__repr__</strong> method to the Base class to make it return a better representation of the class instance when it&#8217;s printed, which is handy for debugging. Finally, he added a function called <strong>init_model</strong> to initialize the model.</p>
<h2>Wrapping Up</h2>
<p>Now you should know that Werner and I have decided to make MediaLocker into an example of a wxPython database-enabled application. He&#8217;s been doing a bunch of work on it since the simple edits I mentioned above. We&#8217;ll be making an official announcement about that soon. In the mean time, I hope that this has helped open your eyes to some fun ways to enhance a project and clean it up a bit. It is my plan to add lots of new features to this program and chronicle those on this blog in addition to all my other articles.</p>
<h2>Source Code</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/wxSa2.zip'>wxSa2.zip</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/wxSa2.tar'>wxSa2.tar</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/11/30/improving-medialocker-wxpython-sqlalchemy-and-mvc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>wxPython and SqlAlchemy: An Intro to MVC and CRUD</title>
		<link>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/#comments</comments>
		<pubDate>Fri, 11 Nov 2011 04:15:35 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Education]]></category>
		<category><![CDATA[wxPython]]></category>
		<category><![CDATA[SqlAlchemy]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2035</guid>
		<description><![CDATA[In this article, we will be creating a program to store our personal books or perhaps just the books you&#8217;ve read. It will demonstrate how to combine wxPython and SqlAlchemy, a SQL Object Relational Mapper (ORM). This program will also give you an introduction to the model-view-controller (MVC) and &#8220;create, read, update and destroy&#8221; (CRUD) [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/" data-url="http://bit.ly/tNneVU" data-text="wxPython and SqlAlchemy: An Intro to MVC and CRUD" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/";
			reddit_title = "wxPython and SqlAlchemy: An Intro to MVC and CRUD";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/"></g:plusone></div></div><p>In this article, we will be creating a program to store our personal books or perhaps just the books you&#8217;ve read. It will demonstrate how to combine wxPython and SqlAlchemy, a SQL Object Relational Mapper (ORM). This program will also give you an introduction to the model-view-controller (MVC) and &#8220;create, read, update and destroy&#8221; (CRUD) methodologies. The aim is to show you how to create an application that can do the following:</p>
<ul>
<li>Create a database (create)</li>
<li>Add records to that database (sort of create)</li>
<li>Display the records (read and view)</li>
<li>Modify records (update)</li>
<li>Delete records (destroy)</li>
</ul>
<p>The order of this tutorial will follow MVC, so we will start with the model. The model is the basis for the GUI (the View) anyway, so it&#8217;s a good place to start.<span id="more-2035"></span></p>
<h2>Prerequisites</h2>
<p>Before we jump into the model section, you may need to download some extras to follow along. Here&#8217;s what you&#8217;ll need:</p>
<ul>
<li>Python 2.5 or better, but not 3.x</li>
<li><a href="http://www.wxpython.org/" target="_blank">wxPython </a>>= 2.8.10.1</li>
<li><a href="http://www.sqlalchemy.org/" target="_blank">SqlAlchemy </a>>= 0.5.0</li>
<li><a href="http://pypi.python.org/pypi/ObjectListView" target="_blank">ObjectListView</a></li>
</ul>
<p>Once you have all those installed, you&#8217;re ready to move on to the next section!</p>
<h2>The Model</h2>
<p>Our model contains our SqlAlchemy database classes and a model for our ObjectListView widget, which we&#8217;ll be using to display our data later. The SqlAlchemy classes are using the <a href="http://www.sqlalchemy.org/docs/orm/extensions/declarative.html" target="_blank">Declarative system</a>, which combines the table creation and the class creation. It&#8217;s a little easier to understand if you just take a look at the code.</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># model.py</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> Table, Column, create_engine
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> Integer, ForeignKey, String, Unicode
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">ext</span>.<span style="color: black;">declarative</span> <span style="color: #ff7700;font-weight:bold;">import</span> declarative_base
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">orm</span> <span style="color: #ff7700;font-weight:bold;">import</span> backref, relation
&nbsp;
engine = create_engine<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;sqlite:///devdata.db&quot;</span>, echo=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
DeclarativeBase = declarative_base<span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span>
metadata = DeclarativeBase.<span style="color: black;">metadata</span>
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> OlvBook<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Book model for ObjectListView
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">id</span>, title, author, isbn, publisher, last_name, first_name<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: #008000;">id</span> = <span style="color: #008000;">id</span>  <span style="color: #808080; font-style: italic;"># unique row id from database</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">title</span> = title
        <span style="color: #008000;">self</span>.<span style="color: black;">author</span> = author
        <span style="color: #008000;">self</span>.<span style="color: black;">isbn</span> = isbn
        <span style="color: #008000;">self</span>.<span style="color: black;">publisher</span> = publisher
        <span style="color: #008000;">self</span>.<span style="color: black;">last_name</span> = last_name
        <span style="color: #008000;">self</span>.<span style="color: black;">first_name</span> = first_name
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Person<span style="color: black;">&#40;</span>DeclarativeBase<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    __tablename__ = <span style="color: #483d8b;">&quot;people&quot;</span>
&nbsp;
    <span style="color: #008000;">id</span> = Column<span style="color: black;">&#40;</span>Integer, primary_key=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    first_name = Column<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;first_name&quot;</span>, String<span style="color: black;">&#40;</span><span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    last_name = Column<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;last_name&quot;</span>, String<span style="color: black;">&#40;</span><span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&lt;Person: %s %s&gt;&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">first_name</span>, <span style="color: #008000;">self</span>.<span style="color: black;">last_name</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>DeclarativeBase<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    __tablename__ = <span style="color: #483d8b;">&quot;books&quot;</span>
&nbsp;
    <span style="color: #008000;">id</span> = Column<span style="color: black;">&#40;</span>Integer, primary_key=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    author_id = Column<span style="color: black;">&#40;</span>Integer, ForeignKey<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;people.id&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    title = Column<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;title&quot;</span>, Unicode<span style="color: black;">&#41;</span>
    isbn = Column<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;isbn&quot;</span>, Unicode<span style="color: black;">&#41;</span>
    publisher = Column<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;publisher&quot;</span>, Unicode<span style="color: black;">&#41;</span>
    person = relation<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Person&quot;</span>, backref=<span style="color: #483d8b;">&quot;books&quot;</span>, cascade_backrefs=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
metadata.<span style="color: black;">create_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>We&#8217;re not going to spend a lot of time parsing this code as there are several SqlAlchemy tutorials out there and the SqlAlchemy documentation is really good. Instead, we&#8217;ll just give a quick overview. The beginning of the code imports all the SqlAlchemy stuff we need. One of the most important bits is where create the engine:</p>
<pre class="python">engine = create_engine<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;sqlite:///devdata.db&quot;</span>, echo=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre>
<p>This means that we&#8217;ll be creating a SQLite database in the same directory as the model is in. You can pass a path in too, like this: <strong>create_engine(&#8220;sqlite:///c:/path/to/devdata.db&#8221;)</strong> and you can name the database whatever you want, including the extension. The <strong>echo</strong> parameter is turned on for debugging purposes. It will output all the SQL that SqlAlchemy issues so we can use it to figure out our queries or issues that may crop up when we create the database.</p>
<p>The first class we encounter is <strong>OlvBook</strong>, which defines a book class. We&#8217;ll be using that later to help us populate the previously mentioned ObjectListView widget that we will use to display our records. The next two classes are called <strong>Person</strong> and <strong>Book</strong>, respectively. The tablename is defined by the magic method: __tablename__. Person is a ForeignKey in Book, which we use for our Author. Originally, I thought I could use Person to add multiple authors or other people related to the book, like the artist. Or maybe for the Songwriter for one of my CDs, but I decided to just keep it simple instead. You can enhance this model a little to make it more polymorphic so it can behave in that way though. </p>
<p>Anyway, if you run this script, it will execute the last line: <strong>metadata.create_all()</strong> This causes the database file to be created with those two tables defined. Now we&#8217;re ready to add data to it. But first, we need to take a look at the View!</p>
<h2>The View</h2>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/media_organizer.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/media_organizer-300x113.png" alt="" title="media_organizer" width="300" height="113" class="aligncenter size-medium wp-image-2044" /></a></p>
<p>The View is our wxPython interface that we will use to display the records as well as filter, add, modify and delete them. The code for our GUI is just over 150 lines long. Let&#8217;s take a look!</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> addModRecord
<span style="color: #ff7700;font-weight:bold;">import</span> commonDlgs
<span style="color: #ff7700;font-weight:bold;">import</span> controller
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">from</span> ObjectListView <span style="color: #ff7700;font-weight:bold;">import</span> ObjectListView, ColumnDefn
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> BookPanel<span style="color: black;">&#40;</span>wx.<span style="color: black;">Panel</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Panel</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = controller.<span style="color: black;">getAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
        mainSizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">VERTICAL</span><span style="color: black;">&#41;</span>
        searchSizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">HORIZONTAL</span><span style="color: black;">&#41;</span>
        btnSizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">HORIZONTAL</span><span style="color: black;">&#41;</span>
        font = wx.<span style="color: black;">Font</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>, wx.<span style="color: black;">SWISS</span>, wx.<span style="color: black;">NORMAL</span>, wx.<span style="color: black;">BOLD</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># create the search related widgets</span>
        cat = <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;Author&quot;</span>, <span style="color: #483d8b;">&quot;Title&quot;</span>, <span style="color: #483d8b;">&quot;ISBN&quot;</span>, <span style="color: #483d8b;">&quot;Publisher&quot;</span><span style="color: black;">&#93;</span>
        searchByLbl = wx.<span style="color: black;">StaticText</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Search By:&quot;</span><span style="color: black;">&#41;</span>
        searchByLbl.<span style="color: black;">SetFont</span><span style="color: black;">&#40;</span>font<span style="color: black;">&#41;</span>
        searchSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>searchByLbl, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">categories</span> = wx.<span style="color: black;">ComboBox</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, value=<span style="color: #483d8b;">&quot;Author&quot;</span>, choices=cat<span style="color: black;">&#41;</span>
        searchSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">categories</span>, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">search</span> = wx.<span style="color: black;">SearchCtrl</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, style=wx.<span style="color: black;">TE_PROCESS_ENTER</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">search</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_TEXT_ENTER</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onSearch</span><span style="color: black;">&#41;</span>
        searchSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">search</span>, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span> = ObjectListView<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, style=wx.<span style="color: black;">LC_REPORT</span>
                                                        |wx.<span style="color: black;">SUNKEN_BORDER</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>.<span style="color: black;">SetEmptyListMsg</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;No Records Found&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">setBooks</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># create the button row</span>
        addRecordBtn = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Add&quot;</span><span style="color: black;">&#41;</span>
        addRecordBtn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_BUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onAddRecord</span><span style="color: black;">&#41;</span>
        btnSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>addRecordBtn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        editRecordBtn = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Edit&quot;</span><span style="color: black;">&#41;</span>
        editRecordBtn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_BUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onEditRecord</span><span style="color: black;">&#41;</span>
        btnSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>editRecordBtn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        deleteRecordBtn = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Delete&quot;</span><span style="color: black;">&#41;</span>
        deleteRecordBtn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_BUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onDelete</span><span style="color: black;">&#41;</span>
        btnSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>deleteRecordBtn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        showAllBtn = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Show All&quot;</span><span style="color: black;">&#41;</span>
        showAllBtn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_BUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onShowAllRecord</span><span style="color: black;">&#41;</span>
        btnSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>showAllBtn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        mainSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>searchSizer<span style="color: black;">&#41;</span>
        mainSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>, <span style="color: #ff4500;">1</span>, wx.<span style="color: black;">ALL</span>|wx.<span style="color: black;">EXPAND</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        mainSizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>btnSizer, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">CENTER</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetSizer</span><span style="color: black;">&#40;</span>mainSizer<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onAddRecord<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Add a record to the database
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        dlg = addModRecord.<span style="color: black;">AddModRecDialog</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        dlg.<span style="color: black;">ShowModal</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        dlg.<span style="color: black;">Destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">showAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onEditRecord<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Edit a record
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        selectedRow = <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>.<span style="color: black;">GetSelectedObject</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> selectedRow == <span style="color: #008000;">None</span>:
            commonDlgs.<span style="color: black;">showMessageDlg</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;No row selected!&quot;</span>, <span style="color: #483d8b;">&quot;Error&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
        dlg = addModRecord.<span style="color: black;">AddModRecDialog</span><span style="color: black;">&#40;</span>selectedRow, title=<span style="color: #483d8b;">&quot;Modify&quot;</span>,
                                           addRecord=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
        dlg.<span style="color: black;">ShowModal</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        dlg.<span style="color: black;">Destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">showAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onDelete<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Delete a record
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        selectedRow = <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>.<span style="color: black;">GetSelectedObject</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> selectedRow == <span style="color: #008000;">None</span>:
            commonDlgs.<span style="color: black;">showMessageDlg</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;No row selected!&quot;</span>, <span style="color: #483d8b;">&quot;Error&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
        controller.<span style="color: black;">deleteRecord</span><span style="color: black;">&#40;</span>selectedRow.<span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">showAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onSearch<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Searches database based on the user's filter choice and keyword
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        filterChoice = <span style="color: #008000;">self</span>.<span style="color: black;">categories</span>.<span style="color: black;">GetValue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">keyword</span> = <span style="color: #008000;">self</span>.<span style="color: black;">search</span>.<span style="color: black;">GetValue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;%s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>filterChoice, <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = controller.<span style="color: black;">searchRecords</span><span style="color: black;">&#40;</span>filterChoice, <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">setBooks</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onShowAllRecord<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Updates the record list to show all of them
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">showAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> setBooks<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>.<span style="color: black;">SetColumns</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>
            ColumnDefn<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Title&quot;</span>, <span style="color: #483d8b;">&quot;left&quot;</span>, <span style="color: #ff4500;">350</span>, <span style="color: #483d8b;">&quot;title&quot;</span><span style="color: black;">&#41;</span>,
            ColumnDefn<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Author&quot;</span>, <span style="color: #483d8b;">&quot;left&quot;</span>, <span style="color: #ff4500;">150</span>, <span style="color: #483d8b;">&quot;author&quot;</span><span style="color: black;">&#41;</span>,
            ColumnDefn<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ISBN&quot;</span>, <span style="color: #483d8b;">&quot;right&quot;</span>, <span style="color: #ff4500;">150</span>, <span style="color: #483d8b;">&quot;isbn&quot;</span><span style="color: black;">&#41;</span>,
            ColumnDefn<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Publisher&quot;</span>, <span style="color: #483d8b;">&quot;left&quot;</span>, <span style="color: #ff4500;">150</span>, <span style="color: #483d8b;">&quot;publisher&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResultsOlv</span>.<span style="color: black;">SetObjects</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> showAllRecords<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        Show all records in the object list view control
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">bookResults</span> = controller.<span style="color: black;">getAllRecords</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">setBooks</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> BookFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, title=<span style="color: #483d8b;">&quot;MvP Media Organizer&quot;</span>,
                          size=<span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>, <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        panel = BookPanel<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
    frame = BookFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>You&#8217;ll notice that we import a few custom items, like addModRecord, commonDlgs and controller. The <strong>addModRecord</strong> is a dialog that can be used both to add a record and modify one. The <strong>commonDlgs </strong>module is used just to simplify creating message dialogs. If we add some new features to this program, we would add other small dialog code in that module. The <strong>controller</strong> module is where all the SqlAlchemy code is executed. Most programs have some configuration options, so this would be a good place to store that code.</p>
<p>Anyway, let&#8217;s go over the highlights of the GUI. The search bar is set to search when the user presses enter. That&#8217;s what the style flag <strong>wx.TE_PROCESS_ENTER</strong> means. That and the ObjectListView&#8217;s <strong>SetEmptyListMsg </strong>method are probably the only really unfamiliar things here. That method just shows a message to the user when there&#8217;s no data in the control.</p>
<p>The <strong>onAddRecord </strong>and <strong>onEditRecord</strong> both call our addModRecord module to display the Add / Modify dialog. It should look something like this:</p>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/media_org_add_record.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/media_org_add_record.png" alt="" title="media_org_add_record" width="400" height="250" class="aligncenter size-full wp-image-2045" /></a></p>
<p>The <strong>onEditRecord</strong> method sets a couple parameters that affect the look of the widget and passes in some information to populate the fields. The <strong>onDelete</strong> method just takes the selected item and calls the controller to delete it, then it updates the display.</p>
<p>Our <strong>onSearch</strong> method does what you&#8217;d expect. It searches for records in our database based on what filter the user chooses and their keyword. They can choose &#8220;Author&#8221;, &#8220;Title&#8221;, &#8220;ISBN&#8221; or &#8220;Publisher&#8221; as their filter. </p>
<p>The <strong>onShowAllRecord</strong> method just shows all the records on the display. A future enhancement would be to limit the number of currently showed records so we don&#8217;t cause major slow down of the application. The <strong>setBooks</strong> method just updates the displayed records. </p>
<p>Now we&#8217;ve reached the last piece of our puzzle: the Controller.</p>
<h2>The Controller and CRUD</h2>
<p>The controller is the glue which holds the model and the view together. At least, that&#8217;s what it seems like to me. It uses the model for queries and for adding, updating and deleting records. It also reports the updates to the database to the view (our GUI) so it can update appropriately. Let&#8217;s take a look at our controller code:</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># controller.py</span>
<span style="color: #ff7700;font-weight:bold;">from</span> model <span style="color: #ff7700;font-weight:bold;">import</span> Book, Person, OlvBook
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> create_engine
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">orm</span> <span style="color: #ff7700;font-weight:bold;">import</span> sessionmaker
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> addRecord<span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Data should be a tuple of two dictionaries in the following format:
&nbsp;
    (&quot;</span>author<span style="color: #483d8b;">&quot;:{&quot;</span>first_name<span style="color: #483d8b;">&quot;:&quot;</span>John<span style="color: #483d8b;">&quot;, &quot;</span>last_name<span style="color: #483d8b;">&quot;:&quot;</span>Doe<span style="color: #483d8b;">&quot;},
     &quot;</span>book<span style="color: #483d8b;">&quot;:{&quot;</span>title<span style="color: #483d8b;">&quot;:&quot;</span>Some book<span style="color: #483d8b;">&quot;, &quot;</span>isbn<span style="color: #483d8b;">&quot;:&quot;</span><span style="color: #ff4500;">1234567890</span><span style="color: #483d8b;">&quot;,
             &quot;</span>publisher<span style="color: #483d8b;">&quot;:&quot;</span>Packt<span style="color: #483d8b;">&quot;}
    )
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    book = Book<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    book.<span style="color: black;">title</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;book&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;title&quot;</span><span style="color: black;">&#93;</span>
    book.<span style="color: black;">isbn</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;book&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;isbn&quot;</span><span style="color: black;">&#93;</span>
    book.<span style="color: black;">publisher</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;book&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;publisher&quot;</span><span style="color: black;">&#93;</span>
    author = Person<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    author.<span style="color: black;">first_name</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;author&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;first_name&quot;</span><span style="color: black;">&#93;</span>
    author.<span style="color: black;">last_name</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;author&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;last_name&quot;</span><span style="color: black;">&#93;</span>
    book.<span style="color: black;">person</span> = author
&nbsp;
    <span style="color: #808080; font-style: italic;"># connect to session and commit data to database</span>
    session = connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">add</span><span style="color: black;">&#40;</span>book<span style="color: black;">&#41;</span>
    session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Connect to our SQLite database and return a Session object
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    engine = create_engine<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;sqlite:///devdata.db&quot;</span>, echo=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    Session = sessionmaker<span style="color: black;">&#40;</span>bind=engine<span style="color: black;">&#41;</span>
    session = Session<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> session
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> convertResults<span style="color: black;">&#40;</span>results<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Convert results to OlvBook objects
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span>
    books = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> record <span style="color: #ff7700;font-weight:bold;">in</span> results:
        author = <span style="color: #483d8b;">&quot;%s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>record.<span style="color: black;">person</span>.<span style="color: black;">first_name</span>,
                            record.<span style="color: black;">person</span>.<span style="color: black;">last_name</span><span style="color: black;">&#41;</span>
        book = OlvBook<span style="color: black;">&#40;</span>record.<span style="color: #008000;">id</span>, record.<span style="color: black;">title</span>, author,
                       record.<span style="color: black;">isbn</span>, record.<span style="color: black;">publisher</span>,
                       record.<span style="color: black;">person</span>.<span style="color: black;">last_name</span>,
                       record.<span style="color: black;">person</span>.<span style="color: black;">first_name</span>
                       <span style="color: black;">&#41;</span>
        books.<span style="color: black;">append</span><span style="color: black;">&#40;</span>book<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> books
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> deleteRecord<span style="color: black;">&#40;</span>idNum<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Delete a record from the database
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    session = connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    record = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: black;">filter_by</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=idNum<span style="color: black;">&#41;</span>.<span style="color: black;">one</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>
    session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> editRecord<span style="color: black;">&#40;</span>idNum, row<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Edit a record
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    session = connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    record = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: black;">filter_by</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=idNum<span style="color: black;">&#41;</span>.<span style="color: black;">one</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span>
    record.<span style="color: black;">title</span> = row<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;title&quot;</span><span style="color: black;">&#93;</span>
    record.<span style="color: black;">person</span>.<span style="color: black;">first_name</span> = row<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;first_name&quot;</span><span style="color: black;">&#93;</span>
    record.<span style="color: black;">person</span>.<span style="color: black;">last_name</span> = row<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;last_name&quot;</span><span style="color: black;">&#93;</span>
    record.<span style="color: black;">isbn</span> = row<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;isbn&quot;</span><span style="color: black;">&#93;</span>
    record.<span style="color: black;">publisher</span> = row<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;publisher&quot;</span><span style="color: black;">&#93;</span>
    session.<span style="color: black;">add</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>
    session.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    session.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> getAllRecords<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Get all records and return them
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    session = connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    result = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>.<span style="color: black;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    books = convertResults<span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span>
    session.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> books
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> searchRecords<span style="color: black;">&#40;</span>filterChoice, <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Searches the database based on the filter chosen and the keyword
    given by the user
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    session = connectToDatabase<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> filterChoice == <span style="color: #483d8b;">&quot;Author&quot;</span>:
        qry = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Person<span style="color: black;">&#41;</span>
        result = qry.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>Person.<span style="color: black;">first_name</span>.<span style="color: black;">contains</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        records = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> record <span style="color: #ff7700;font-weight:bold;">in</span> result:
            <span style="color: #ff7700;font-weight:bold;">for</span> book <span style="color: #ff7700;font-weight:bold;">in</span> record.<span style="color: black;">books</span>:
                records.<span style="color: black;">append</span><span style="color: black;">&#40;</span>book<span style="color: black;">&#41;</span>
        result = records
        <span style="color: #ff7700;font-weight:bold;">print</span> result
    <span style="color: #ff7700;font-weight:bold;">elif</span> filterChoice == <span style="color: #483d8b;">&quot;Title&quot;</span>:
        qry = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>
        result = qry.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>Book.<span style="color: black;">title</span>.<span style="color: black;">contains</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> filterChoice == <span style="color: #483d8b;">&quot;ISBN&quot;</span>:
        qry = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>
        result = qry.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>Book.<span style="color: black;">isbn</span>.<span style="color: black;">contains</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        qry = session.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Book<span style="color: black;">&#41;</span>
        result = qry.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>Book.<span style="color: black;">publisher</span>.<span style="color: black;">contains</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">keyword</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    books = convertResults<span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> books</pre>
<p>Our controller has 7 functions defined: </p>
<ul>
<li>addRecord</li>
<li>connectToDatabase</li>
<li>convertResults</li>
<li>deleteRecord</li>
<li>editRecord</li>
<li>getAllRecords</li>
<li>searchRecords</li>
</ul>
<p>These are pretty self explanatory. However, we&#8217;ll spend a little time explaining what <strong>convertResults</strong> does and how <strong>searchRecords</strong> works. </p>
<p>The <strong>convertResults</strong> method is for converting the SqlAlchemy book results that we get from querying the database, into the ObjectListView Book model objects. This is necessary so we can display them when there are updates to the database or when displaying the results of a query. As you can see, we just iterate over the results and massage the data appropriately.</p>
<p>In the <strong>searchRecords</strong> method, we pass in our filter and keyword and do queries on the database using our session object via a conditional &#8220;if&#8221; statement. Depending on the type of filter, we query differently. For the most part, the query is the same though, so this could use some refactoring. I&#8217;ll leave that for the reader to figure out as an assignment. Once we have the results converted, we then return them to the calling function, which in this case happens to be our GUI&#8217;s search event handler.</p>
<p>The CRUD part is covered in the other methods where we create, read, update, and delete records. </p>
<h2>Wrapping Up</h2>
<p>Now you should know the basics behind creating a wxPython program using the MVC framework. This isn&#8217;t a perfect example and I don&#8217;t claim that it is, but it should give you an idea of how to start making your own. It also shows how to interact with a SQLite database using SqlAlchemy. I hope you&#8217;ve found this helpful and look forward to hearing your comments.</p>
<h2>Source Code</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/mediaLocker.zip'>mediaLocker.zip</a></li>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/mediaLocker.tar'>mediaLocker.tar</a></li>
<li>You can also check out the code from <a href="https://bitbucket.org/driscollis/mousevspython/src" target="_blank">Bitbucket</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>wxPython: ANN: Namespace Diff Tool</title>
		<link>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 13:15:54 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=2028</guid>
		<description><![CDATA[Last night, Andrea Gavana released his new Namespace Diff Tool (NDT) to the world. I got his permission to reprint his announcement here for all those people who don&#8217;t follow the wxPython mailing list. I think it sounds like a really cool tool. You should check it out and see what you think. Here is [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/" data-url="http://bit.ly/vwpxHc" data-text="wxPython: ANN: Namespace Diff Tool" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div><div class="socialize-in-button socialize-in-button-left"><script type="text/javascript">
			<!-- 
			reddit_url = "http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/";
			reddit_title = "wxPython: ANN: Namespace Diff Tool";	//-->
		</script><script type="text/javascript" src="http://www.reddit.com/static/button/button2.js"></script></div><div class="socialize-in-button socialize-in-button-left"><g:plusone size="small" href="http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/"></g:plusone></div></div><p>Last night, Andrea Gavana released his new Namespace Diff Tool (NDT) to the world. I got his permission to reprint his announcement here for all those people who don&#8217;t follow the wxPython mailing list. I think it sounds like a really cool tool. You should check it out and see what you think. Here is the <a href="https://groups.google.com/forum/#!topic/wxpython-users/oK8dfnLQ7Rc" target="_blank">announcement</a>:<span id="more-2028"></span></p>
<p>
<p><em>Description<br />
===========</p>
<p>The `Namespace Diff Tool` (NDT) is a graphical user interface that can<br />
be used to discover differences between different versions of a library,<br />
or even between different iterations/sub-versions of the same library.</p>
<p>The tool can be used to identify what is missing and still needs to be<br />
implemented, or what is new in a new release, which items do not have<br />
docstrings and so on.</p>
<p>Full description of the original idea by Robin Dunn:</p>
<p><a href="http://svn.wxwidgets.org/viewvc/wx/wxPython/Phoenix/trunk/TODO.txt?view=markup" target="_blank">http://svn.wxwidgets.org/viewvc/wx/wxPython/Phoenix/trunk/TODO.txt?vi</a>&#8230;</p>
<p>:warning: As most of the widgets in the GUI are owner drawn or custom,<br />
 it is highly probable that the interface itself will look messy on other<br />
 platforms (Mac, I am talking to you). Please do try and create a patch to<br />
 fix any possible issue in this sense.</p>
<p>:note: Please refer to the TODOs section for a list of things that still<br />
need<br />
 to be implemented.</p>
<p>Requirements<br />
============</p>
<p>In order to run NDT, these packages need to be installed:</p>
<p>- Python 2.X (where 5 <= X <= 7);<br />
- wxPython >= 2.8.10;<br />
- SQLAlchemy >= 0.6.4.</p>
<p>More detailed instructions on how to use it, TODO items, list of<br />
libraries/packages I tested NDT against, screenshots and download links can<br />
be found here:</p>
<p><a href="http://xoomer.virgilio.it/infinity77/main/NDT.html" target="_blank">http://xoomer.virgilio.it/infinity77/main/NDT.html</a></p>
<p>If you stumble upon a bug (which is highly probable), please do let me<br />
know. But most importantly, please do try and make an effort to create a<br />
patch for the bug. </em></p>
<p>According to the <a href="https://groups.google.com/forum/#!topic/wxpython-users/oK8dfnLQ7Rc" target="_blank">thread</a>, some bugs were already found and fixed. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/11/10/wxpython-ann-namespace-diff-tool/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>wxPython: Creating a &#8220;dark mode&#8221;</title>
		<link>http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 16:45:10 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1956</guid>
		<description><![CDATA[One day at work last month, I was told that we had a feature request for one of my programs. They wanted a &#8220;dark mode&#8221; for when they used my application at night as the normal colors were kind of glaring. My program is used in laptops in police cars, so I could understand their [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/" data-url="http://bit.ly/u8A9T1" data-text="wxPython: Creating a &#8220;dark mode&#8221;" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div></div><p>One day at work last month, I was told that we had a feature request for one of my programs. They wanted a &#8220;dark mode&#8221; for when they used my application at night as the normal colors were kind of glaring. My program is used in laptops in police cars, so I could understand their frustration. I spent some time looking into the matter and got a mostly working script put together which I&#8217;m going to share with my readers. Of course, if you&#8217;re a long time reader, you probably know I&#8217;m talking about a wxPython program. I write almost all my GUIs using wxPython. Anyway, let&#8217;s get on with the story!<span id="more-1956"></span></p>
<h2>Into the Darkness</h2>
<p>Getting the widgets to change color in wxPython is quite easy. The only two methods you need are <strong>SetBackgroundColour </strong>and <strong>SetForegroundColour</strong>. The only major problem I ran into when I was doing this was getting my ListCtrl / ObjectListView widget to change colors appropriately. You need to loop over each ListItem and change their colors individually. I alternate row colors, so that made things more interesting. The other problem I had was restoring the ListCtrl&#8217;s background color. Normally you can set a widget&#8217;s background color to wx.NullColour (or wx.NullColor) and it will go back to its default color. However, some widgets don&#8217;t work that way and you have to actually specify a color. It should also be noted that some widgets don&#8217;t seem to pay any attention to SetBackgroundColour at all. One such widget that I&#8217;ve found is the wx.ToggleButton.</p>
<p>Now you know what I know, so let&#8217;s look at the code I came up with to solve my issue:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">from</span> ObjectListView <span style="color: #ff7700;font-weight:bold;">import</span> ObjectListView
<span style="color: #ff7700;font-weight:bold;">except</span>:
    ObjectListView = <span style="color: #008000;">False</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> getWidgets<span style="color: black;">&#40;</span>parent<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Return a list of all the child widgets
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    items = <span style="color: black;">&#91;</span>parent<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> parent.<span style="color: black;">GetChildren</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        items.<span style="color: black;">append</span><span style="color: black;">&#40;</span>item<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>item, <span style="color: #483d8b;">&quot;GetChildren&quot;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">for</span> child <span style="color: #ff7700;font-weight:bold;">in</span> item.<span style="color: black;">GetChildren</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                items.<span style="color: black;">append</span><span style="color: black;">&#40;</span>child<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> items
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> darkRowFormatter<span style="color: black;">&#40;</span>listctrl, dark=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Toggles the rows in a ListCtrl or ObjectListView widget.
    Based loosely on the following documentation:

http://objectlistview.sourceforge.net/python/recipes.html#recipe-formatter

    and http://objectlistview.sourceforge.net/python/cellEditing.html
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    listItems = <span style="color: black;">&#91;</span>listctrl.<span style="color: black;">GetItem</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>listctrl.<span style="color: black;">GetItemCount</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> index, item <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>listItems<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> dark:
            <span style="color: #ff7700;font-weight:bold;">if</span> index <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span>:
                item.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Dark Grey&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                item.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Light Grey&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> index <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span>:
                item.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Light Blue&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                item.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Yellow&quot;</span><span style="color: black;">&#41;</span>
        listctrl.<span style="color: black;">SetItem</span><span style="color: black;">&#40;</span>item<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">def</span> darkMode<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, normalPanelColor<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    Toggles dark mode
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
    widgets = getWidgets<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
    panel = widgets<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> normalPanelColor == panel.<span style="color: black;">GetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        dark_mode = <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        dark_mode = <span style="color: #008000;">False</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> widget <span style="color: #ff7700;font-weight:bold;">in</span> widgets:
        <span style="color: #ff7700;font-weight:bold;">if</span> dark_mode:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>widget, ObjectListView<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>widget, wx.<span style="color: black;">ListCtrl</span><span style="color: black;">&#41;</span>:
                darkRowFormatter<span style="color: black;">&#40;</span>widget, dark=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
            widget.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Dark Grey&quot;</span><span style="color: black;">&#41;</span>
            widget.<span style="color: black;">SetForegroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;White&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>widget, ObjectListView<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>widget, wx.<span style="color: black;">ListCtrl</span><span style="color: black;">&#41;</span>:
                darkRowFormatter<span style="color: black;">&#40;</span>widget<span style="color: black;">&#41;</span>
                widget.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;White&quot;</span><span style="color: black;">&#41;</span>
                widget.<span style="color: black;">SetForegroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Black&quot;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            widget.<span style="color: black;">SetBackgroundColour</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">NullColor</span><span style="color: black;">&#41;</span>
            widget.<span style="color: black;">SetForegroundColour</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Black&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> dark_mode</pre>
<p>This code is a little convoluted, but it gets the job done. Let&#8217;s break it down a bit and see how it works. First off, we try to import ObjectListView, a cool 3rd party widget that wraps wx.ListCtrl and makes it a LOT easier to use. However, it&#8217;s not part of wxPython right now, so you need to test for it&#8217;s existence. I just set it to False if it doesn&#8217;t exist. </p>
<p>The <strong>GetWidgets</strong> function takes a parent parameter, which would usually be a wx.Frame or wx.Panel and goes through all of its children to create a list of widgets, which it then returns to the calling function. The main function is <strong>darkMode</strong>. It takes two parameters too, the poorly named &#8220;self&#8221;, which refers to a parent widget, and a default panel color. It calls GetWidgets and then uses a conditional statement to decide if dark mode should be enabled or not. Next it loops over the widgets and changes the colors accordingly. When it&#8217;s done, it will refresh the passed in parent and return a bool to let you know if dark mode is on or off.</p>
<p>There is one more function called <strong>darkRowFormatter</strong> that is only for setting the colors of the ListItems in a wx.ListCtrl or an ObjectListView widget. Here we use a list comprehension to create a list of wx.ListItems that we then iterate over, changing their colors. To actually apply the color change, we need to call SetItem and pass it a wx.ListItem object instance.</p>
<h2>Trying Out Dark Mode</h2>
<p>So now you&#8217;re probably wondering how to actually use the script above. Well, this section will show you how it&#8217;s done. Here&#8217;s a simple program with a list control in it and a toggle button too!</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">import</span> darkMode
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MyPanel<span style="color: black;">&#40;</span>wx.<span style="color: black;">Panel</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Panel</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">defaultColor</span> = <span style="color: #008000;">self</span>.<span style="color: black;">GetBackgroundColour</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        rows = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Ford&quot;</span>, <span style="color: #483d8b;">&quot;Taurus&quot;</span>, <span style="color: #483d8b;">&quot;1996&quot;</span>, <span style="color: #483d8b;">&quot;Blue&quot;</span><span style="color: black;">&#41;</span>,
                <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Nissan&quot;</span>, <span style="color: #483d8b;">&quot;370Z&quot;</span>, <span style="color: #483d8b;">&quot;2010&quot;</span>, <span style="color: #483d8b;">&quot;Green&quot;</span><span style="color: black;">&#41;</span>,
                <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Porche&quot;</span>, <span style="color: #483d8b;">&quot;911&quot;</span>, <span style="color: #483d8b;">&quot;2009&quot;</span>, <span style="color: #483d8b;">&quot;Red&quot;</span><span style="color: black;">&#41;</span>
                <span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span> = wx.<span style="color: black;">ListCtrl</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, style=wx.<span style="color: black;">LC_REPORT</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">InsertColumn</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #483d8b;">&quot;Make&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">InsertColumn</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;Model&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">InsertColumn</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;Year&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">InsertColumn</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">&quot;Color&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        index = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> rows:
            <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">InsertStringItem</span><span style="color: black;">&#40;</span>index, row<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span>index, <span style="color: #ff4500;">1</span>, row<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span>index, <span style="color: #ff4500;">2</span>, row<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span>index, <span style="color: #ff4500;">3</span>, row<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> index <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">SetItemBackgroundColour</span><span style="color: black;">&#40;</span>index, <span style="color: #483d8b;">&quot;white&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>.<span style="color: black;">SetItemBackgroundColour</span><span style="color: black;">&#40;</span>index, <span style="color: #483d8b;">&quot;yellow&quot;</span><span style="color: black;">&#41;</span>
            index += <span style="color: #ff4500;">1</span>
&nbsp;
        btn = wx.<span style="color: black;">ToggleButton</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Toggle Dark&quot;</span><span style="color: black;">&#41;</span>
        btn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_TOGGLEBUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onToggleDark</span><span style="color: black;">&#41;</span>
        normalBtn = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, label=<span style="color: #483d8b;">&quot;Test&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        sizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">VERTICAL</span><span style="color: black;">&#41;</span>
        sizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">list_ctrl</span>, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>|wx.<span style="color: black;">EXPAND</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        sizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>btn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        sizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>normalBtn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetSizer</span><span style="color: black;">&#40;</span>sizer<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onToggleDark<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        darkMode.<span style="color: black;">darkMode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">self</span>.<span style="color: black;">defaultColor</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MyFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, wx.<span style="color: black;">ID_ANY</span>,
                          <span style="color: #483d8b;">&quot;MvP ListCtrl Dark Mode Demo&quot;</span><span style="color: black;">&#41;</span>
        panel = MyPanel<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
    frame = MyFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>If you run the program above, you should see something like this:</p>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/listctrlDark1.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/listctrlDark1.png" alt="" title="ListCtrl Dark Mode Off" width="400" height="250" class="aligncenter size-full wp-image-2015" /></a></p>
<p>If you click the ToggleButton, you should see something like this:</p>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/listctrlDark2.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/listctrlDark2.png" alt="" title="ListCtrl Dark Mode On" width="400" height="250" class="aligncenter size-full wp-image-2017" /></a></p>
<p>Notice how the toggle button was unaffected by the SetBackgroundColour method. Also notice that the list control&#8217;s column headers don&#8217;t change colors either. Unfortunately, wxPython doesn&#8217;t expose access to the column headers, so there&#8217;s no way to manipulate their color. </p>
<p>Anyway, let&#8217;s take a moment to see how the dark mode code is used. First we need to import it. In this case, the module is called <strong>darkMode</strong>. To actually call it, we need to look at the ToggleButton&#8217;s event handler:</p>
<pre class="python">darkMode.<span style="color: black;">darkMode</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">self</span>.<span style="color: black;">defaultColor</span><span style="color: black;">&#41;</span></pre>
<p>As you can see, all we did was call darkMode.darkMode with the panel object (the &#8220;self) and a defaultColor that we set at the beginning of the wx.Panel&#8217;s init method. That&#8217;s all we had to do too. We should probably set it up with a variable to catch the returned value, but for this example we don&#8217;t really care. </p>
<h2>Wrapping Up</h2>
<p>Now we&#8217;re done and you too can create a &#8220;dark mode&#8221; for your applications. At some point, I&#8217;d like to generalize this some more to make into a color changer script where I can pass whatever colors I want to it. What would be really cool is to make it into a mixin. But that&#8217;s something for the future. For now, enjoy!</p>
<h2>Further Reading</h2>
<ul>
<li>ObjectListView <a href="http://objectlistview.sourceforge.net/python/" target="_blank">documentation</a></li>
<li>An ObjectListView <a href="http://www.blog.pythonlibrary.org/2009/12/23/wxpython-using-objectlistview-instead-of-a-listctrl/" target="_blank">tutorial</a></li>
<li>wx.ListCtrl <a href="http://www.wxpython.org/docs/api/wx.ListCtrl-class.html" target="_blank">documentation</a></li>
</ul>
<h2>Source Code</h2>
<ul>
<li><a href='http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/2011-11-5-wxPython-dark-mode.zip'>2011-11-5-wxPython-dark-mode</a></li>
<li>You can also pull the source from <a href="https://bitbucket.org/driscollis/mousevspython/src/4794d34444ad/Published/2011-11-5-wxPython-dark-mode" target="_blank">Bitbucket</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>wxPython: An Intro to the UltimateListCtrl</title>
		<link>http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 00:36:21 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1999</guid>
		<description><![CDATA[One of the new agw widgets to be included in wxPython is one called the UltimateListCtrl. It&#8217;s a pure Python widget that can have pretty much any other widget stuck into any of the cells, which makes it really flexible. It also allows the skilled programmer the ability to add custom renderers to make the [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/" data-url="http://bit.ly/vDOTEP" data-text="wxPython: An Intro to the UltimateListCtrl" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div></div><p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/ultimateListCtrlDemo.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/ultimateListCtrlDemo-300x225.png" alt="" title="ultimateListCtrlDemo" width="300" height="225" class="aligncenter size-medium wp-image-2000" /></a></p>
<p>One of the new agw widgets to be included in wxPython is one called the UltimateListCtrl. It&#8217;s a pure Python widget that can have pretty much any other widget stuck into any of the cells, which makes it really flexible. It also allows the skilled programmer the ability to add custom renderers to make the interface different. In this article, we will take a quick look at this fascinating widget.<span id="more-1999"></span></p>
<h2>Getting Started</h2>
<p><a href="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/mvpULCDemo.png"><img src="http://www.blog.pythonlibrary.org/wp-content/uploads/2011/11/mvpULCDemo-300x184.png" alt="" title="mvpULCDemo" width="300" height="184" class="aligncenter size-medium wp-image-2002" /></a></p>
<p>The simplest way to learn a new widget is to look at an example. You can look at the wxPython demo for the 2.9 series if you want to see several complex demos of this awesome widget, but for our purposes, we&#8217;re going to create a stripped down version that&#8217;s based on one of those demos, namely the report view version. Here&#8217;s the code for your viewing pleasure:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">from</span> wx.<span style="color: black;">lib</span>.<span style="color: black;">agw</span> <span style="color: #ff7700;font-weight:bold;">import</span> ultimatelistctrl as ULC
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TestPanel<span style="color: black;">&#40;</span>wx.<span style="color: black;">Panel</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Panel</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>
&nbsp;
        font = wx.<span style="color: black;">SystemSettings_GetFont</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">SYS_DEFAULT_GUI_FONT</span><span style="color: black;">&#41;</span>
        boldfont = wx.<span style="color: black;">SystemSettings_GetFont</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">SYS_DEFAULT_GUI_FONT</span><span style="color: black;">&#41;</span>
        boldfont.<span style="color: black;">SetWeight</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">BOLD</span><span style="color: black;">&#41;</span>
        boldfont.<span style="color: black;">SetPointSize</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span> = ULC.<span style="color: black;">UltimateListCtrl</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, agwStyle = wx.<span style="color: black;">LC_REPORT</span>
                                         | wx.<span style="color: black;">LC_VRULES</span>
                                         | wx.<span style="color: black;">LC_HRULES</span><span style="color: black;">&#41;</span>
&nbsp;
        info = ULC.<span style="color: black;">UltimateListItem</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        info._mask = wx.<span style="color: black;">LIST_MASK_TEXT</span> | wx.<span style="color: black;">LIST_MASK_IMAGE</span> | wx.<span style="color: black;">LIST_MASK_FORMAT</span> | ULC.<span style="color: black;">ULC_MASK_CHECK</span>
        info._image = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        info._format = <span style="color: #ff4500;">0</span>
        info._kind = <span style="color: #ff4500;">1</span>
        info._text = <span style="color: #483d8b;">&quot;Artist Name&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertColumnInfo</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, info<span style="color: black;">&#41;</span>
&nbsp;
        info = ULC.<span style="color: black;">UltimateListItem</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        info._format = wx.<span style="color: black;">LIST_FORMAT_RIGHT</span>
        info._mask = wx.<span style="color: black;">LIST_MASK_TEXT</span> | wx.<span style="color: black;">LIST_MASK_IMAGE</span> | wx.<span style="color: black;">LIST_MASK_FORMAT</span> | ULC.<span style="color: black;">ULC_MASK_FONT</span>
        info._image = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        info._text = <span style="color: #483d8b;">&quot;Title&quot;</span>
        info._font = boldfont
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertColumnInfo</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, info<span style="color: black;">&#41;</span>
&nbsp;
        info = ULC.<span style="color: black;">UltimateListItem</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        info._mask = wx.<span style="color: black;">LIST_MASK_TEXT</span> | wx.<span style="color: black;">LIST_MASK_IMAGE</span> | wx.<span style="color: black;">LIST_MASK_FORMAT</span>
        info._format = <span style="color: #ff4500;">0</span>
        info._text = <span style="color: #483d8b;">&quot;Genre&quot;</span>
        info._font = font
        info._image = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertColumnInfo</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, info<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #483d8b;">&quot;Newsboys&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;Go&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;Rock&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;Puffy&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;Bring It!&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;Pop&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">InsertStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;Family Force 5&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;III&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetStringItem</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;Crunk&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetColumnWidth</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">150</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetColumnWidth</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>.<span style="color: black;">SetColumnWidth</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
        sizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">VERTICAL</span><span style="color: black;">&#41;</span>
        sizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ultimateList</span>, <span style="color: #ff4500;">1</span>, wx.<span style="color: black;">EXPAND</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetSizer</span><span style="color: black;">&#40;</span>sizer<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TestFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Constructor&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, title=<span style="color: #483d8b;">&quot;MvP UltimateListCtrl Demo&quot;</span><span style="color: black;">&#41;</span>
        panel = TestPanel<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
    frame = TestFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>Let&#8217;s take a few moments to break this down a bit. First off, to import this widget, we need to do something like the following: <strong>from wx.lib.agw import ultimatelistctrl as ULC</strong>. Then to instantiate it, we call <strong>ULC.UltimateListCtrl()</strong> and pass it a few key values. In this case, we pass in a parent and three styles: wx.LC_REPORT, wx.LC_VRULES and wx.LC_HRULES. The first agwStyle is LC_REPORT, which puts the widget in &#8220;Report&#8221; mode, probably the most common mode you&#8217;ll see for a ListCtrl and one of the most useful. The other two styles put vertical and horizontal lines in, respectively.</p>
<p>Next, we want to create our columns. We use <strong>ULC.UltimateListItem</strong> to do that, although according to the <a href="http://xoomer.virgilio.it/infinity77/AGW_Docs/ultimatelistctrl.UltimateListItem.html#ultimatelistctrl-ultimatelistitem" target="_blank">documentation</a>, this can also be used to create &#8220;items&#8221; too. As you can see, the UltimateListItem has many attributes that we can set. You can add an image, a checkbox (via the mask and the style: ULC.ULC_MASK_CHECK), a kind (0 &#8211; normal, 1 &#8211; checkbox, 2 &#8211; radio button), a format (which controls label positioning), the font and text and several others. Once you&#8217;ve set that stuff up, you call the UltimateListItem object&#8217;s <strong>InsertColumnInfo()</strong> method on it to apply your settings.</p>
<p>Finally, to add data to the UltimateListCtrl, we do the same thing that we would do with a normal ListCtrl. Namely, we first call <strong>InsertStringItem(index, label)</strong> where index is the row number. Then to add strings to the other columns, you&#8217;ll want to call <strong>SetStringItem(index, col, label)</strong>. There are lots of other methods you can call to add other types of data, but you&#8217;ll need to read the demo&#8217;s source or the documentation to learn that. And now we&#8217;re done with our first demo!</p>
<h2>Wrapping Up</h2>
<p>There is a lot more information to be found in the official wxPython 2.9 series demo. In fact, there are several demos showing the various styles and UI variations that this widget can do. You can see an example of one of those demos in the screenshot at the beginning of this article. I would recommend this widget any time you need to insert other widgets into the cells of a ListCtrl or whenever you need lots of control over the widget&#8217;s presentation. Happy hacking!</p>
<h2>Further Reading</h2>
<ul>
<li>UltimateListCtrl <a href="http://xoomer.virgilio.it/infinity77/AGW_Docs/ultimatelistctrl_module.html#ultimatelistctrl" target="_blank">Documentation</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/11/02/wxpython-an-intro-to-the-ultimatelistctrl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wxPython: Binding Multiple Widgets to the Same Handler</title>
		<link>http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/</link>
		<comments>http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 01:02:38 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.blog.pythonlibrary.org/?p=1942</guid>
		<description><![CDATA[If you&#8217;ve been in the wxPython community for more than a couple months, you will probably recognize the following question: &#8220;How do I bind multiple buttons to the same event handler and make them do different things?&#8221; Well, this article will show you how to do exactly that. Note: This article is based on some [...]]]></description>
			<content:encoded><![CDATA[<div class="socialize-in-content" style="float:left;"><div class="socialize-in-button socialize-in-button-left"><a href="http://twitter.com/share" class="twitter-share-button" data-counturl="http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/" data-url="http://bit.ly/vF9XzY" data-text="wxPython: Binding Multiple Widgets to the Same Handler" data-count="vertical" data-via="socializeWP" ><!--Tweetter--></a></div><div class="socialize-in-button socialize-in-button-left"><iframe src="http://www.facebook.com/plugins/like.php?href=http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/&amp;layout=button_count&amp;show_faces=true&amp;width=100&amp;action=like&amp;font=arial&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px !important; height:65px;" allowTransparency="true"></iframe></div></div><p>If you&#8217;ve been in the wxPython community for more than a couple months, you will probably recognize the following question: &#8220;How do I bind multiple buttons to the same event handler and make them do different things?&#8221; Well, this article will show you how to do exactly that. <span id="more-1942"></span></p>
<p><em>Note: This article is based on some code from a previous article on buttons from this very blog!</em></p>
<h2>Let&#8217;s Get Started</h2>
<p>To begin, we need to write some code that actually contains multiple buttons. We will go through an example that shows two different ways to get the button object so you can manipulate your program as needed. Here&#8217;s the code you&#8217;ve been waiting for:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> wx
&nbsp;
<span style="color: #808080; font-style: italic;">########################################################################</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MyForm<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, wx.<span style="color: black;">ID_ANY</span>, <span style="color: #483d8b;">&quot;Button Tutorial&quot;</span><span style="color: black;">&#41;</span>
        panel = wx.<span style="color: black;">Panel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, wx.<span style="color: black;">ID_ANY</span><span style="color: black;">&#41;</span>
&nbsp;
        sizer = wx.<span style="color: black;">BoxSizer</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">VERTICAL</span><span style="color: black;">&#41;</span>
        buttonOne = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span>panel, label=<span style="color: #483d8b;">&quot;One&quot;</span>, name=<span style="color: #483d8b;">&quot;one&quot;</span><span style="color: black;">&#41;</span>
        buttonTwo = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span>panel, label=<span style="color: #483d8b;">&quot;Two&quot;</span>, name=<span style="color: #483d8b;">&quot;two&quot;</span><span style="color: black;">&#41;</span>
        buttonThree = wx.<span style="color: black;">Button</span><span style="color: black;">&#40;</span>panel, label=<span style="color: #483d8b;">&quot;Three&quot;</span>, name=<span style="color: #483d8b;">&quot;three&quot;</span><span style="color: black;">&#41;</span>
        buttons = <span style="color: black;">&#91;</span>buttonOne, buttonTwo, buttonThree<span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">for</span> button <span style="color: #ff7700;font-weight:bold;">in</span> buttons:
            <span style="color: #008000;">self</span>.<span style="color: black;">buildButtons</span><span style="color: black;">&#40;</span>button, sizer<span style="color: black;">&#41;</span>
&nbsp;
        panel.<span style="color: black;">SetSizer</span><span style="color: black;">&#40;</span>sizer<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> buildButtons<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, btn, sizer<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        btn.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_BUTTON</span>, <span style="color: #008000;">self</span>.<span style="color: black;">onButton</span><span style="color: black;">&#41;</span>
        sizer.<span style="color: black;">Add</span><span style="color: black;">&#40;</span>btn, <span style="color: #ff4500;">0</span>, wx.<span style="color: black;">ALL</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> onButton<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
        This method is fired when its corresponding button is pressed
        &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
        button = event.<span style="color: black;">GetEventObject</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;The button you pressed was labeled: &quot;</span> + button.<span style="color: black;">GetLabel</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;The button's name is &quot;</span> + button.<span style="color: black;">GetName</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        button_id = event.<span style="color: black;">GetId</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        button_by_id = <span style="color: #008000;">self</span>.<span style="color: black;">FindWindowById</span><span style="color: black;">&#40;</span>button_id<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;The button you pressed was labeled: &quot;</span> + button_by_id.<span style="color: black;">GetLabel</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;The button's name is &quot;</span> + button_by_id.<span style="color: black;">GetName</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#----------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># Run the program</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
    frame = MyForm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    frame.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>To start, we create three button objects. Then to make things slightly less messy, we put them into a list and iterate over the list to add the buttons to a sizer and bind them to an event handler. This is a good way to cut down on spaghetti code (i.e. copy and pasted code) and makes it a little cleaner and easier to debug. Some people go ahead and create some elaborate helper methods like <strong>buildButtons</strong> that can handle other widgets and are more flexible. </p>
<p>The part we really care about though is the event handler itself. The easiest way to get the widget in the event handler is by calling the event object&#8217;s <strong>GetEventObject</strong>() method. That will return the widget and then you can do whatever you like. Some people will change the widget&#8217;s value or label, others will use the widgets ID or unique name and set up some conditional structures to do something if this button is pressed and do something else if a different button is pressed. The functionality is up to you.</p>
<p>The second way to get the widget is a two-step process where we need to extract the ID from the event using its <strong>GetID</strong>() method. Then we pass that result to our frame object&#8217;s <strong>FindWindowById</strong>() method and we once again have the widget in question. </p>
<h2>Wrapping up</h2>
<p>Now you know the &#8220;secret&#8221; of binding multiple widgets to the same event handler. Go forth and code like there&#8217;s no tomorrow and create something amazing! The code can be downloaded on the new blog&#8217;s Mercurial <a href="https://bitbucket.org/driscollis/mousevspython/overview" target="_blank">repository</a>. </p>
<h2>Additional Resources</h2>
<ul>
<li><a href="http://www.blog.pythonlibrary.org/2010/06/09/wxpython-a-tour-of-buttons-part-1-of-2/" target="_blank">wxPython: A Tour of Buttons (Part 1 of 2)</a></li>
<li><a href="http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind" target="_blank">self.Bind vs. self.button.Bind</a></li>
<li>wx.Button <a href="http://www.wxpython.org/docs/api/wx.Button-class.html" target="_blank">documentation</a></li>
<li>Creating buttons tutorial on <a href="http://www.youtube.com/watch?v=cp1ZeMisTNo" target="_blank">Youtube</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 5.776 seconds -->

