<?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>Apolitically Incorrect &#187; IronPython</title>
	<atom:link href="http://www.oak-tree.us/blog/index.php/category/computerprog/ironpython/feed" rel="self" type="application/rss+xml" />
	<link>http://www.oak-tree.us/blog</link>
	<description>The Rants and Raves of an Unsettled Mind</description>
	<lastBuildDate>Mon, 31 Oct 2011 21:56:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Cross Platform GUI Development with Python and Qt</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt#comments</comments>
		<pubDate>Tue, 12 May 2009 21:16:18 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[PyQt]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=897</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Cross+Platform+GUI+Development+with+Python+and+Qt&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt&amp;rft.language=English"></span>
One of computer programmers many fantasies (or at least one of my fantasies) is a cross-platform codebase that is easy to maintain.  I want to write an application once and then be able to deploy in on any platform in existence.  It should integrate into the destination environment in a native manner, but still be [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt">Cross Platform GUI Development with Python and Qt</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Cross+Platform+GUI+Development+with+Python+and+Qt&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt&amp;rft.language=English"></span>
<p><img style="display: inline; margin: 0px 15px 15px 0px" src="http://www.tailsnscales.com/images/albino_burm_head.jpg" alt="" width="245" height="184" align="left" />One of computer programmers many fantasies (or at least one of my fantasies) is a cross-platform codebase that is easy to maintain.  I want to write an application once and then be able to deploy in on any platform in existence.  It should integrate into the destination environment in a native manner, but still be similar enough to the other platforms so that  issues can be addressed in a way that doesn’t hinder overall progress.</p>
<p>Part of this dream can be fulfilled by using Python and standard library, it is also possible to do much of it by using <a href="http://www.oak-tree.us/blog/index.php/2008/11/18/ironpython-part1">IronPython</a> and .Net (through the OpenSource <a href="http://mono-project.com/Main_Page">Mono</a> framework).  However, in each case, you are forced to make a tradeoff.  Python and the standard library are wonderful, if you are willing to accept a speed hit.  IronPython and Mono also work well, as long as you avoid using any of the Windows specific libraries.  Unfortunately, many of neatest .Net features (like <a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3">Windows Presentation Foundation</a>) are only available on Windows.</p>
<p>Okay, there is always GTK+ or <a href="http://www.wxwidgets.org/">wxWidgets</a> (the same toolkits used for the <a href="http://www.gnome.org/">Gnome</a> desktop), but GTK+ is written in C and while much of the miscellaneous nastiness has been abstracted away, it is still one of the hardest toolkits to work with.  Oh, and the documentation sucks.  (When any documentation can be found at all.)  Thus, we arrive at the final contender: <a href="http://www.qtsoftware.com/products/">Qt</a>.  Qt has had a <a href="http://en.wikipedia.org/wiki/Qt_(toolkit)">long and controversial history</a>  involving license issues, passion, and miscellaneous geek pride.  In fact, it’s due to Qt and some rather divisive decisions made by its developers that we even have alternative toolkits at all.  But, despite that history, <a href="http://arstechnica.com/open-source/news/2009/01/nokia-qt-lgpl-switch-huge-win-for-cross-platform-development.ars">Trolltech’s recent decision</a> to release the framework under the permissive LGPL license (rather than the noxious GPL) changes all that.  In many ways, Qt might just become the cross-platform toolkit of choice</p>
<p>Of course, it's a given that Qt is tremendously powerful with rich functionality.  Applications that are written in Qt are fully cross-platform and behave the same way wherever they are deployed.  It uses native widgets whenever possible and has a sophisticated theming system that allows it to follow platform conventions without significantly modifying the underlying code.  More importantly, Qt is backed by a passionate developer community and a well funded corporation (Nokia).  It is true, you get what you pay for.  Qt is well designed and the documentation is simply fantastic.  And unlike GTK+ or wxWidgets, the entire toolkit is written in proper object oriented C++.</p>
<p>I first started experimenting with the Qt framework about two months ago, after deciding to tackle <a href="http://www.oak-tree.us/blog/index.php/2009/03/04/perfect-tool">a major add-on</a> to one of my favorite writing programs, <a href="http://www.lyx.org/">LyX</a>.  As I have said <a href="http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7">elsewhere</a>, I am not the world’s most</p>
<p><img style="display: inline; margin-left: 0px; margin-right: 0px" src="http://farm2.static.flickr.com/1319/1129819772_77804dda7f.jpg" alt="" width="402" height="136" align="right" /></p>
<p>gifted computer programmer (far from it actually), but Qt actually makes it pretty easy to get yourself up and running in a reasonable amount of time.  If I were forced to do most of my GUI programming in Qt and C++, that would be an acceptable solution.  However, that is completely unnecessary.  You see, Qt has one of the most tightly integrated Python bindings available, through the user of <a href="http://www.riverbankcomputing.co.uk/software/pyqt/intro">PyQt</a> from Riverbank software.  Qt plus Python is, quite simply, programming perfection.  So while I did some mild experimenting with the Qt frameworks in C++, I have spent much of the past few months doing the heavy work of learning the framework via the use of  Python.</p>
<p>In the process, I have made a great many mistakes and a great many more discoveries.  And since the final step in any discovery is to share your findings, I will be doing that through this series of articles.  Of more interest to most, however, I will also be introducing the fruits of my labors: a somewhat functional prototype of my outliner add-on for LyX.<span id="more-897"></span></p>
<h2>Part 0: Thoughts on Licenses, Setup and Installation</h2>
<p>But before I bore you over the benefits of abstraction and dynamically typed object oriented programming, I should first dispense with some of the nuances and details of setting up a system to run Qt.   This also, unfortunately, must include a brief discussion of licenses.  While most general computer users likely do not care, the license under which a given piece of software is released is tremendously important.  In the case of a most OpenSource software, it determines what rights the users receive and what the developers retain.  In some cases, it may even determine if the developer is able to charge for his or her work.</p>
<p>This is why Trolltech’s decision to switch from the GPL (a popular and very restrictive OpenSource license) to the more permissive LGPL is a very big deal.  As alluded to above, it allows for commercial developers to link against the Qt libraries without legal fears.  Unfortunately, however, the new licensing is only for the most recent version of the toolkit (version 4.5).  In addition, while Qt is available under a more permissive license, PyQt is not.  PyQt is only available under the terms of the GPL or a separately purchased commercial license.  For people who will use PyQt for in-house work or for end users, the distinction is a purely philosophical matter.  But if you are a developer who intends to distribute your code (or attempt to charge for it), it is something that you need to consider carefully.  Unless you buy a commercial license, PyQt can only be used for GPL related development.  The good news, however, is that it is perfectly possible to utilize a commercial PyQt license in conjunction with the LGPLed Qt.  Further, the costs for a commercial PyQt license are quire reasonable, about $400 dollars per developer.  While this might sound like a lot, compare it to the more than $5000 that Trolltech charges for a cross-platform commercial Qt license.</p>
<h3>Installation, Setup and Configuration</h3>
<p>Now that some of the grit has been sorted, let’s get down to the the minutiae of setting up a PyQt development environment.  This guide will focus on using the most recent version of the framework (Qt 4.5.1).  Since the procedure varies slightly based upon your platform, separate instructions will be provided for Mac OS X, Linux and Windows.</p>
<p>There are four separate pieces of software that you will need to download and install on your system.  1) The Qt Framework, which you can get from the Trolltech website, 2) the Python interpreter and related libraries, 3) SIP, which is used to generate Python bindings to C and C++ code, and 4) PyQt.  In general, the installation procedure goes like this:</p>
<ol>
<li>Download and install Qt via the package installer for your platform from the <a href="http://www.qtsoftware.com/downloads">Trolltech homepage</a>.  In order to avoid manually compiling the libraries, I would recommend downloading the package entitled “Qt SDK: The Complete Development Environment.”</li>
<li>Install the GNU compiler tools for Windows (MinGW).  If you use the complete Qt4 package in step 1, this will happen automatically.  (The GCC tools are typically provided as a package for Linux and can be installed from the Mac OS X system CD or by downloading the XCode developer tools)</li>
<li>If there isn’t a version of Python provided with your OS, download, install and configure <a href="http://www.python.org/download/">Python</a>.    For Windows users, be sure to select the 2.5.4 Windows installer.  (Both Linux and Mac OS X ship with a Python interpreter and can skip this step).</li>
<li>Download and manually compile the <a href="http://www.riverbankcomputing.co.uk/software/sip/download">SIP library</a> from Riverbank Computing.  <em>Note: Because we will be using the most recent version of Qt, you will need version 4.8 or greater.  As of this writing, SIP 4.8 was still in development, thus get the <strong>most recent development snapshot</strong>.</em></li>
<li>Download, manually compile and install the <a href="http://www.riverbankcomputing.co.uk/software/pyqt/download">PyQt source code</a> for your platform.  <em>Note: Again, because we are using the most recent version of Qt, you will need to <strong>download the development snapshot</strong>.  Be sure that the version on the bindings is 4.5 or greater.</em></li>
</ol>
<p>While the general procedure may look quite intimidating at first glance, it is actually fairly simple.  The platform specific guides below explain how to do everything step by step.  There is some variability between platforms, so be sure to select the guide for your OS.</p>
<ol>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux">Linux</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows">Windows</a> - Qt, MinGW, Python, SIP and PyQt</li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac">Mac OS X</a> - Qt, XCode, GCC, Autoconf, SIP and PyQt on Mac OS X</li>
</ol>
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/20/back-in-time1" rel="bookmark" title="July 20, 2009">Back In Time (Part 1): Linux Backup Made Easy</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/23/iphone-quality" rel="bookmark" title="December 23, 2008">The iPhone App Store and Software Quality: A User’s Perspective</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/03/04/perfect-tool" rel="bookmark" title="March 4, 2009">Creating the Perfect Writing Tool: A Proposal</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1" rel="bookmark" title="January 6, 2009">IronPython - Data Binding and Data Templates - Part 1</a></li>
</ul>
<p><!-- Similar Posts took 35.784 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt">Cross Platform GUI Development with Python and Qt</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installation of PyQt on Mac OS X</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac#comments</comments>
		<pubDate>Tue, 12 May 2009 21:12:17 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[PyQt]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=896</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Mac+OS+X&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac&amp;rft.language=English"></span>
Note: The installation instructions in this article apply to Mac OS X 10.5 (Leopard) and Qt 4.5.3.  While it is possible to get Qt 4.5.3 to run on Snow Leopard, it requires compiling it from source.  Instructions for doing so can be found in the comments below.  It is important to note, however, that there [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac">Installation of PyQt on Mac OS X</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Mac+OS+X&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac&amp;rft.language=English"></span>
<p><em>Note: The installation instructions in this article apply to Mac OS X 10.5 (Leopard) and Qt 4.5.3.  While it is possible to get Qt 4.5.3 to run on Snow Leopard, it requires compiling it from source.  Instructions for doing so can be found in the comments below.  </em><em>It is important to note, however, that there are some minor issues with the 4.5 framework on Snow Leopard (including mutlithreaded memory leaks).</em></p>
<p><em>You can find instructions for how to install PyQt on Snow Leopard using the Qt 4.7 frameworks at <a href="http://blog.oak-tree.us/index.php/2010/05/27/pyqt-snow-leopard">http://blog.oak-tree.us/index.php/2010/05/27/pyqt-snow-leopard</a>.</em></p>
<p>To install PyQt on Mac OS X, it is also necessary to install and configure the GCC compilers and the Qt framework in addition to SIP and PyQt.  The easiest way to get the most current version of the GCC compilers and tools is by downloading the XCode tools package from Apple at the <a href="http://developer.apple.com/mac/">Apple Developer Connection (ADC)</a>.  ADC requires that you have an Apple ID and account, which are both free.  After you log-in, download the XCode developer tools package, which is a bit hefty (nearly 1 GB in size) and may take a while to download depending on your internet speed.</p>
<h2>XCode and Qt</h2>
<p>While waiting for the XCode tools to download, you can also begin downloading the Qt binary installer from the <a href="http://www.qtsoftware.com/downloads">Trolltech downloads site</a>.  As with Windows, I would advise that you you select  the complete SDK (which also include pre-compiled binaries) rather than the source release.  If you only download the Qt framework, you will need to compile the source yourself which is both time intensive and is not worth the additional headache.</p>
<p>Once XCode has finished downloading, run the package installer.  It will ask you to select the destination drive and what components of the software you would like to install.</p>
<p><img style="display: inline; border-width: 0px;" title="Select the installation disc where you want to install XCode the developer tools" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/pyqtmacinstall17.png" border="0" alt="Select the installation disc where you want to install XCode the developer tools" width="550" height="390" /></p>
<p><a href="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/pyqtmacinstall26.png"><img style="display: inline; border-width: 0px;" title="Choose the components you would like to install" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/pyqtmacinstall26-thumb.png" border="0" alt="Choose the components you would like to install" width="550" height="390" /></a></p>
<p>This will automatically install and configure the GNU tool chain.  Once it has finished, you can access the tools by going to the “/Developer/” folder on the root of the drive.</p>
<p>After XCode has finished, run the Qt installer.</p>
<p><img style="display: inline; border-width: 0px;" title="The Qt SKD Installer" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/pyqtmacinstall3.png" border="0" alt="The Qt SKD Installer" width="550" height="392" /></p>
<p><img style="display: inline; border-width: 0px;" title="Select the installation destination" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/pyqtmacinstall4.png" border="0" alt="Select the installation destination" width="550" height="387" /></p>
<p>The Qt installer package will automatically place the tools and other things that you will need in the same Developer folder where the XCode tools and frameworks are located.  You will need to make a note of the path for qmake.  The default installation site for qmake is “/usr/bin/qmake-4.5”.</p>
<h2>SIP and PyQt</h2>
<p>SIP is a program that makes it easy to create C++ bindings program for Python.  You can find the source code at Riverbank’s <a href="http://www.riverbankcomputing.co.uk/software/sip/download">SIP download page</a>.  Since we will be using the 4.5 version of PyQt, you will need to download the latest developer snapshot (version 4.8 or greater).  Be sure to get the Linux/Unix source code, rather than the Windows source.  You will also need the latest source code snapshot for PyQt 4.5, which is also <a href="http://www.riverbankcomputing.co.uk/software/pyqt/download">available from Riverbank</a>.</p>
<p>After you have finished downloading the source files, move them to a folder in your Users directory.  I have a special directory entitled “Applications” where I keep the source code for programs that I have manually compiled.  <em>Note: The rest of the steps will be done from the Mac OS X terminal.</em></p>
<p>After you have moved the source code for both SIP and PyQt to this new directory, extract it by using the tar utility with the x and f options (tar –xf):</p>
<blockquote><p>cd ~/Applications<br />
tar -xf sip-4.8-snapshot-20090430.tar<br />
tar -xf PyQt-mac-gpl-4.5-snapshot-20090507.tar</p></blockquote>
<p>After you have expanded the files, it might be a good idea to rename the directories to something more manageable (like sip-4.8 and PyQt4.5:</p>
<blockquote><p>mv sip-4.8-snapshot-20090430 sip-4.8<br />
mv PyQt-mac-gpl-4.5-snapshot-20090507 PyQt4.5</p></blockquote>
<p>First, we need to compile and install SIP.  The default configuration will move the compiled files to a directory where Leopard can’t read them.  So, we will manually need to specify the destination directory using the –d flag:</p>
<blockquote><p>cd sip-4.8<br />
python configure.py -d /Library/Python/2.5/site-packages</p></blockquote>
<p>After the configuration is finished, run make and sudo make install:</p>
<blockquote><p>make<br />
sudo make install</p></blockquote>
<p>Once SIP has finished installing, we need to repeat the process for PyQt.  From the sip-4.8 directory, chagne to PyQt:</p>
<blockquote><p>cd ..<br />
cd PyQt4</p></blockquote>
<p>Next, run the configuration script specifying the path to your version of qmake and the installation directory for the python bindings:</p>
<blockquote><p>python configure.py -q /usr/bin/qmake-4.5 -d /Library/Python/2.5/site-packages/</p></blockquote>
<p>Then compile and install:</p>
<blockquote><p>make<br />
sudo make install</p></blockquote>
<p>Since Qt is a rather large framework, it may require between 15 and 30 minutes to fully compile.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows" rel="bookmark" title="May 12, 2009">Installation of PyQt on Windows</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/10/07/duplicity-mac" rel="bookmark" title="October 7, 2009">Installing Duplicity on Mac OS X</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/10/05/install-timedrive-ubuntu" rel="bookmark" title="October 5, 2009">Install Time Drive On Ubuntu and Other Debian Linux Distributions</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
</ul>
<p><!-- Similar Posts took 287.832 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac">Installation of PyQt on Mac OS X</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Installation of PyQt on Windows</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows#comments</comments>
		<pubDate>Tue, 12 May 2009 18:00:38 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[PyQt]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=883</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Windows&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows&amp;rft.language=English"></span>
On Windows, we first need to install the pre-compiled Qt binary package from the Trolltech downloads page.&#160; Select the LGPL/Free tab and choose the “Qt SDK: Complete Development Environment” for Windows.&#160; It is a fairly hefty package (167 megabytes) and may take a while to transfer.&#160; The installer includes the core Qt libraries, several important [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows">Installation of PyQt on Windows</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Windows&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows&amp;rft.language=English"></span>
<p>On Windows, we first need to install the pre-compiled Qt binary package from the <a href="http://www.qtsoftware.com/downloads">Trolltech downloads page</a>.&#160; Select the LGPL/Free tab and choose the “Qt SDK: Complete Development Environment” for Windows.&#160; It is a fairly hefty package (167 megabytes) and may take a while to transfer.&#160; The installer includes the core Qt libraries, several important C++ development tools, and an integrated development environment (IDE) called Qt creator.&#160; Luckily, the same installer will work on Windows XP, Windows Vista and Windows 7.</p>
<h2>Qt and MinGW</h2>
<p>When you run the installer, it will ask for the installation destination.&#160; To avoid future problems, this folder should not include any spaces. The default is “C:\Qt\2009.02”,&#160; but because I like to keep the root directory of my drive as clean as possible, I changed this to “C:\Qt\Windows”.&#160; To begin the installation, press “Install.”</p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Change the installation directory to C:\Windows\Qt" border="0" alt="Change the installation directory to C:\Windows\Qt" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image391.png" width="450" height="353" /></p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image-thumb551.png" width="450" height="351" /></p>
<p>The installer will also download and configure the GNU compiler toolset for Windows (also known as MinGW).&#160; By default, MinGW will be installed in a subdirectory under the main Qt directory.&#160; In this example, it was installed to “C:\WINDOWS\Qt\mingw”.&#160; Note this file path, it will be important to the steps below.</p>
<h2>Python</h2>
<p>After you finish with the Qt framework, the next step is to download and install Python.&#160; You can get the Python interpreter and other associated files from the <a href="http://www.python.org/download/releases/2.5.4/">Python release download page</a>.&#160; While the newest version is Python 3.0.1, I would recommend that you download and install Python 2.5.4 instead.&#160; When trying to set up SIP with Python 2.6.2 and Python 3.0.1, I experienced a number of errors.&#160; These were resolved by using the x86 version of Python 2.5.</p>
<p>When you first run the installer, it will ask whether you want to install Python for all users or for just the current users.&#160; Make sure that “install for all users” is selected.&#160; Like Qt, you should install Python to a directory without spaces.&#160; The default install location will be “C:\Python25”, though I typically change it to “C:\Windows\Python25” so that it matches the installation directory for Qt.</p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Make sure that the &quot;Install for all users&quot; option is selected" border="0" alt="Make sure that the &quot;Install for all users&quot; option is selected" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image1.png" width="450" height="393" /></p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Change the installation directory to &quot;C:\Windows\Python25&quot; so that it is similar to the installation directory of Qt" border="0" alt="Change the installation directory to &quot;C:\Windows\Python25&quot; so that it is similar to the installation directory of Qt" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image2.png" width="450" height="389" /></p>
<p align="left">After the Python installer has finished running, you will need to modify one of the Windows environment variables.&#160; On Windows XP, the easiest way to access the environment variables to right click on “My Computer” and select “Properties” from the drop own menu.&#160; When the “System Properties” window launches click on the “Advanced” tab and then press the “Environment Variables” button.&#160;&#160; (If you are using Windows Vista or the Windows 7 beta, the easiest way to access the Environment Variables is to go to Control Panel and Search for “Path” in the search bar.&#160; All other steps remain the same.)</p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="You can open the &quot;Environment Variables&quot; by right clicking on &quot;My Computer&quot; and selecting &quot;Properties.&quot;  Then choose the advanced tab and click on the &quot;Environment Variables&quot; button" border="0" alt="You can open the &quot;Environment Variables&quot; by right clicking on &quot;My Computer&quot; and selecting &quot;Properties.&quot;  Then choose the advanced tab and click on the &quot;Environment Variables&quot; button" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image641.png" width="400" height="466" /></p>
<p align="left">From the “System Variables” list, select the Path Variable and then press “Edit”.</p>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Select Path from the &quot;System Variables&quot; list and select &quot;Edit&quot;" border="0" alt="Select Path from the &quot;System Variables&quot; list and select &quot;Edit&quot;" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/05/image701.png" width="375" height="421" /></p>
<p align="left">In the variable <a href="http://www.pricespectre.com">value box</a>, type in the path to the Python folder you just installed, the path to the “bin” folder of MinGW (which should be under the MinGW folder from above), and last the path to a Qt program called qmake (which is located in the qt\bin folder of the Qt installation) .&#160; You should separate these values from the other paths (and from each other) by a semi-colon.&#160; If you have followed all of the instructions in this tutorial, you will add:</p>
<blockquote><p align="left">C:\Windows\Qt\mingw\bin;C:\Windows\Python25;C:\Windows\Qt\qt\bin</p>
</blockquote>
<p align="left">And your path variable should now look something like:</p>
<blockquote><p align="left">%SystemRoot%\System32; C:\Windows\Qt\mingw\bin; C:\Windows\Python25; C:\Windows\Qt\qt\bin</p>
</blockquote>
<p align="left">Press “Ok” to close the dialog box and then “Ok” again to close first the Environment Variables and then the “System Properties Pane.”&#160; Now that you have changed the Path variable, you need to restart your computer so that the changes can take effect.</p>
<h2>SIP and PyQt</h2>
<p>Prior to compiling PyQt, you will first need to compile and install SIP, which can be found at <a href="http://www.riverbankcomputing.co.uk/software/sip/download">Riverbank Software</a>.&#160; Though the stable version of the software is currently (4.7.9), you will need to download the latest Windows source code&#160; snapshot of version 4.8 (Qt 4.5 doesn’t work with earlier versions of SIP).&#160; (<em>Update: Alternatively, you can also find a copy of the 4.8 snapshot <a href="http://www.oak-tree.us/tutorials/sip48.zip">here</a>.</em>)&#160; You will need the most recent source code snapshot of PyQt 4.5, which is also <a href="http://www.riverbankcomputing.co.uk/software/pyqt/download">available from Riverbank</a>.&#160; (<em>Update: Multiple people seem to have had problems installing the 4.5 snapshot from the Riverbank website.&#160; As a matter of convenience, you can find the April 30, 2009 version <a href="http://www.oak-tree.us/tutorials/PyQt4.zip">here</a>.&#160; This is the same version that was used in the writing of this article.)</em></p>
<p>After you have finished downloading the source files, extract them to the Qt installation directory (C:\Windows\Qt in this tutorial).&#160; This might also be a good time to rename the directories to something shorter than the default snapshot names.&#160; I have changed mine to PyQt4 and sip-4.8.</p>
<p>The rest of the steps will be run from the command line prompt (cmd.exe) and must be run with administrator privileges to work properly.&#160; Start by going to the start menu and then choosing the run command; then type “cmd.exe” and press enter.&#160; (If you are on Windows Vista, you can open the command prompt by typing “cmd.exe” in the search dialog of the start menu.&#160; To run with administrator privileges, right click on the top program choice and select “Run as administrator” from the context menu.)</p>
<p>At the command line, first, go to the Qt installation directory by typing:</p>
<blockquote><p>cd C:\Windows\Qt</p>
</blockquote>
<p>Then go to the SIP directory:</p>
<blockquote><p>cd sip-4.8</p>
</blockquote>
<p>Prior to compiling, we need to create a proper configuration file:</p>
<blockquote><p>python configure.py –p win32-g++</p>
</blockquote>
<p>After the configuration is done, compile the new file by typing:</p>
<blockquote><p>mingw32-make</p>
</blockquote>
<p>This will take some time.&#160; After the files have finished compiling, you can install them by typing:</p>
<blockquote><p>mingw32-make install</p>
</blockquote>
<p>The process is repeated for PyQt.&#160; Change to the PyQt4 source directory by typing:</p>
<blockquote><p>cd ..      <br />cd PyQt4</p>
</blockquote>
<p>Then configure the make files, compile and install by typing:</p>
<blockquote><p>python configure.py –p win32-g++      <br />mingw32-make       <br />mingw32-make install</p>
</blockquote>
<p>Since Qt is a rather large framework, it may take between 15 and 30 minutes to fully compile.</p>
<p><strong>Update: </strong>If you only want to run PyQt programs, the installation process can be greatly simplified by using the automated PyQt installer for Windows.&#160; The installer will automatically install a copy of the Qt framework and the PyQt bindings.&#160; You will need to install Python separately, however.</p>
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac" rel="bookmark" title="May 12, 2009">Installation of PyQt on Mac OS X</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/10/07/duplicity-mac" rel="bookmark" title="October 7, 2009">Installing Duplicity on Mac OS X</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/10/05/install-timedrive-ubuntu" rel="bookmark" title="October 5, 2009">Install Time Drive On Ubuntu and Other Debian Linux Distributions</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2011/10/26/core-dhcp" rel="bookmark" title="October 26, 2011">Installing and Configuring DHCP on Windows Server Core</a></li>
</ul>
<p><!-- Similar Posts took 14.884 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows">Installation of PyQt on Windows</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Installation of PyQt on Linux (Ubuntu)</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux#comments</comments>
		<pubDate>Tue, 12 May 2009 17:52:17 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[PyQt]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=870</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Linux+%28Ubuntu%29&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux&amp;rft.language=English"></span>
In comparison to Windows and Mac OS X, installing PyQt on Linux is trivially easily.  It is likely that all of the software necessary for Python development is likely available in your favorite distribution repository.  If you are using the most recent version of Ubuntu 9.04 (and who isn't), then, all you need to do is [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux">Installation of PyQt on Linux (Ubuntu)</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Installation+of+PyQt+on+Linux+%28Ubuntu%29&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-05-12&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux&amp;rft.language=English"></span>
<p>In comparison to Windows and Mac OS X, installing PyQt on Linux is trivially easily.  It is likely that all of the software necessary for Python development is likely available in your favorite distribution repository.  If you are using the most recent version of Ubuntu 9.04 (and who isn't), then, all you need to do is open up your terminal and type:</p>
<blockquote><p>sudo apt-get install python-qt4 qt4-dev-tools python-qt4-dev build-essential pyqt4-dev-tools</p></blockquote>
<p>The package manager (apt-get) will take care of downloading and installing any dependencies.  Once the installation routine finishes, you will have a fully working installation of Qt 4.5 and PyQt 4.5 without any compilation, configuration, or other miscellaneous headaches.  The qt4-dev-tools, pyqt4-dev-tools and python-qt4-dev packages install important tools used for creating user-interfaces.  The build-essential package installs the GNU compilers and autoconf tool chain.  If you will only be running PyQt programs, these additional packages are unnecessary.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac" rel="bookmark" title="May 12, 2009">Installation of PyQt on Mac OS X</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows" rel="bookmark" title="May 12, 2009">Installation of PyQt on Windows</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/10/05/install-timedrive-ubuntu" rel="bookmark" title="October 5, 2009">Install Time Drive On Ubuntu and Other Debian Linux Distributions</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2011/10/26/core-dhcp" rel="bookmark" title="October 26, 2011">Installing and Configuring DHCP on Windows Server Core</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/20/back-in-time1" rel="bookmark" title="July 20, 2009">Back In Time (Part 1): Linux Backup Made Easy</a></li>
</ul>
<p><!-- Similar Posts took 20.684 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux">Installation of PyQt on Linux (Ubuntu)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-linux/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>IronPython in Action</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action#comments</comments>
		<pubDate>Mon, 09 Feb 2009 20:46:53 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Book Reviews]]></category>
		<category><![CDATA[IronPython in Action]]></category>
		<category><![CDATA[Michael Foord]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+in+Action&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-02-09&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action&amp;rft.language=English"></span>
There is an old adage, often used and much abused, “Give a man a fish and he will eat for a day.  Teach a man to fish and he will never want for food.”  And while this old saying is extremely tired and very much cliché, it is a surprisingly apt way for me to [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action">IronPython in Action</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+in+Action&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-02-09&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action&amp;rft.language=English"></span>
<p><img style="border-right-width: 0px; margin: 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="IronPython in Action" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/02/ironpythoninaction-thumb.jpg" border="0" alt="IronPython in Action" width="300" height="373" align="left" />There is an old adage, often used and much abused, “Give a man a fish and he will eat for a day.  Teach a man to fish and he will never want for food.”  And while this old saying is extremely tired and very much cliché, it is a surprisingly apt way for me to begin a review of “<a href="http://www.amazon.com/exec/obidos/ASIN/1933988339/ref=nosim/apolitiincorr-20%3E">IronPython in Action</a>,” a programming book by Michael J. Foord and Christian Muirhead.</p>
<p>“IronPython in Action” delves into the use of scripting (or dynamic) languages and how they merge with Microsoft’s enormous .Net platform.  For readers of this site, it shouldn’t be any secret that I have been working hard to <a href="http://www.oak-tree.us/blog/index.php/2008/11/18/ironpython-part1">teach myself Python</a>.  And while that particular adventure is better documented <a href="http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7">elsewhere</a>, “IronPython in Action" has been central to it.  Indeed, it has been my primary reference manual and guide.</p>
<p>It’s been nearly six months and it’s far past time to write a review of the guide.  But this review is going to be a little bit different than others that you might read.  If you are looking for a more traditional summary, you might be better served by Craig Murphy’s exhaustive <a href="http://www.craigmurphy.com/blog/?p=1257">breakdown</a>.  Rather than detail the contents and render an opinion, I would like to first tell a story and then focus on a much narrower question: Is IronPython valuable for people who are new to Python or .Net programming?  More to the point, can it be used to teach a novice “how to fish?”<span id="more-639"></span></p>
<h2>Backgrounds and Purposes</h2>
<p>To understand my take on Foord’s book, it is important to understand my background.  You see, I am not a computer science person.  I am not a programmer.  I am first and foremost a  research scientist and then an engineer.  Most of the time, I am concerned about refining and extending the technology of others; not creating it from nothing.  And while I occasionally need to write a bit of code, it usually falls into a realm that most <em>real</em> <em>programmers</em> treat with disdain: scripting.  This explains why, for the past five years or so, I have had an ongoing (if rather tempestuous) love affair with a technical computing toolbox called <a href="http://www.mathworks.com/">Matlab</a>.</p>
<p>During those years, I have helped The Mathworks Company (creators of Matlab) to line their pockets and strengthen their stranglehold as the de-facto language for technical computing, I have also had a long string of much-wiser computer people tell me that I should consider OpenSource alternatives.  (Anyone who is at all familiar with computers should be aware of the OpenSource/Proprietary divide.  If you’re not, it is very similar to the Windows/Mac divide; except substitute flame-throwers for flame-bait.)  OpenSource certainly has its advantages: it’s free, you can audit the code, there are a huge number of well written extensions, it will never go away, and it has a <a href="http://ubuntuforums.org/">very enthusiastic community</a>.  It also has some severe weaknesses: documentation sucks, there’s no technical support, and it has an <a href="http://www.stallman.org/">overly enthusiastic</a> <a href="http://boycottnovell.com/">community</a>.  I was particularly hung up on the bit about sucky documentation.</p>
<p>And then, about 18 months ago, <a href="http://www.oak-tree.us/articles/Bioen02.pdf">something</a> happened that changed my opinion.  Instead of trying to apply existing tech to new problems, I and my research group found ourselves looking at some very complex issues that no one had really studied before.  It didn’t take long to realize that our existing tool set was completely inadequate.  The group desperately needed alternatives to Matlab and I found myself burdened with a rather unpleasant research project.  I needed to find and screen said alternatives.  This started with Perl, proceeded to Ruby, and eventually ended up at Python. </p>
<p>I quickly decided that I liked what I saw. Python was fast, flexible, and had a very simple (yet elegant) syntax that could be taught to students and technicians familiar with Matlab.  There was a large number of extensions available and it was cross platform.  There was, however, a major problem: Python lacked bindings for the Insight Toolkit (ITK), an essential framework for people who work with medical imaging data.  Cue despair.  But … after yet more research, I found an acceptable workaround.  While Python might lack bindings, C# does not.  Coincidentally, there happened to be a Python implementation which allows for C# code to be used like native Python code: IronPython.</p>
<p>More importantly, however, all of the advantages were retained.  IronPython is Python.  The syntax still works, many of the extensions will load and run, and (through the use of Mono) IronPython is cross platform.  There are additional benefits as well: .Net grants access to an enormous number of very high quality C# libraries.  Thus, after careful consideration (lasting about 15 or 20 seconds), I made the decision to move our nascent code from Matlab to Python.  There was just one problem, I and essentially everyone else would need to learn Python and .Net from scratch, which might prove a formidable challenge.</p>
<h2>Learning IronPython</h2>
<p>This is where “IronPython in Action” makes its first appearance.  The book was first recommended by a friend familiar with my panic-stricken, "make things up as I go along" style.  He said it was well written and would be a good first read for someone with some (but not a whole lot) of computer programming experience.  I thanked him for his suggestion and purchased an electronic copy of the work in progress via the Manning Early Access Program (MEAP).</p>
<p>At the time, I had a list of very specific needs: </p>
<ol>
<li>Learn Python, its frameworks, syntax, and shortcomings.</li>
<li>Get a whirlwind introduction to .Net (Mono), its architecture and how IronPython fit into the big scheme of .Net dynamic languages.</li>
</ol>
<p>“IronPython in Action” fulfilled both, after a fashion, in addition to several more that I didn’t recognize as needs.  Of these unrecognized needs, the most important important was facing my own ignorance.  You see, IronPython helped me start to fill a few of the holes in my computer science education.  Being an engineer and not a programmer, I always considered myself above actually learn how to code.  I much preferred a “practical” view of coding best be articulated as, “Make it work!  Now!”  This “practical” view was most often delivered to an underling, at the top of my voice, prior to a major deadline.  And, as might be guessed, it didn’t always lend itself to an elegant, reusable, or even a useful end-product.</p>
<p>Fortunately, Python (by design) encourages all of the above: elegance, use and reuse.  More importantly though, Foord and Muirhead stress these concepts from the moment that you open their book.  Rather than delve immediately into the gritty of examples, Chapters 1 to 3 <em>insist</em> on providing a comprehensive overview and background to .Net, Python and how the two integrate.  To return to the fishing analogy: instead of baiting the hook and getting the reader started immediately, Foord instead opts to describe the tackle and trade tools and how they are used.</p>
<p>This can be quite frustrating to someone who wants to deal with the “practical” world.  After all, I want to code, not re-learn how to think!  Except … that is exactly what I needed to do.  As I read through “IronPython in Action,” I found myself drawn to the many footnotes (29 in the second chapter alone) and references so that I could learn more about a given topic.  Instead of tackling syntax, frameworks and shortcomings I found myself reading a great deal about object oriented, procedural, and meta programming.  More fatally, instead of focusing on “just making it work,” I was entertaining radical thoughts like “how does it work” and “can it be improved.”  Such introspection approaches sacrilegious among “practical” people.</p>
<p>Thus, when the authors do begin to provide examples during Part 2 of the book, the reader is in a much better position to make good use of them.  Essential lessons, the equivalent of baiting hooks and making a cast, have already been covered and Foord is able to begin sharing insights into how to successfully “fish.”  And there are plenty of said insights covering most major topics of interest: Windows Forms, Web Development, and even Windows Presentation Foundation (WPF).  The chapters covering system administration are just a bonus.</p>
<h2>An Education</h2>
<p>At every point, Foord and Muirhead seem to hold to another old adage, “Rather than ‘teach,’ I would prefer to help you learn.”  In doing so, they encourage and empower their readers to explore well beyond the examples and techniques covered within the pages of “IronPython in Action.”</p>
<p>In case it isn’t clear, I heartily recommend that anyone interested in learning Python or .Net purchase this book.  It certainly has its idiosyncrasies, but it still manages two roles very successfully: 1)  introductory text and 2) reference manual.  While novice readers (like myself six months ago) will find tremendous value in reading the book from cover to cover, more experienced hands will find value in skimming individual chapters.  As someone who has written technical documentation, I can testify that such a feat is extremely difficult to pull off.</p>
<p>While this style is particularly valuable to the novice, it might not work to the benefit of everyone.  More advanced readers might desire to see more extensive/complicated examples or a more thorough overview of both the Python and .Net frameworks.  But ... I suspect that these individuals will be few, after all, that information is provided by the respective Python Standard Library and Microsoft documentation libraries.</p>
<p>In conclusion, I can only congratulate the authors on this excellent introductory work.  While I initially set out with a desire to learn a skill, I instead received an education.  In the process, I got excited about programming, Python, and OpenSource.  To answer my own question: Can IronPython in Action be used to teach a novice how to “fish?”</p>
<p>Most definitely.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2009/02/11/pitiful" rel="bookmark" title="February 11, 2009">A Pitiful and Pathetic Story</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/05/backup-part5-1" rel="bookmark" title="July 5, 2009">Backup, Sync and Share &ndash; Part 5.1: Windows Vista Backup (Files)</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/02/21/question-answer" rel="bookmark" title="February 21, 2009">Inheritance Questions and Answers</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/21/collection03-moment" rel="bookmark" title="December 21, 2008">The Collection – A Moment</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/14/twitter" rel="bookmark" title="May 14, 2009">I Killed Twitter</a></li>
</ul>
<p><!-- Similar Posts took 19.796 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action">IronPython in Action</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/02/09/ironpython-in-action/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>IronPython - Data Binding and Data Templates - Part 1</title>
		<link>http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1</link>
		<comments>http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1#comments</comments>
		<pubDate>Tue, 06 Jan 2009 05:12:26 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=464</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+-+Data+Binding+and+Data+Templates+-+Part+1&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-01-06&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1&amp;rft.language=English"></span>
Figure 1. The main Podcast list for Podcatcher. This is an example of WPF data binding where a data template and data trigger have been applied. The selected item shows the feed description in addition to the feed name, link and image. One of the most important and fundamental purposes of computers is to manipulate [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1">IronPython - Data Binding and Data Templates - Part 1</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+-+Data+Binding+and+Data+Templates+-+Part+1&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2009-01-06&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1&amp;rft.language=English"></span>
<div>
<table style="border-collapse:collapse" border="0" align="left">
<colgroup span="1">
<col style="width: 373px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 10px; padding-bottom: 10px; padding-right: 10px"><img class="aligncenter" src="http://www.oak-tree.us/blog/wp-content/uploads/2009/01/010409-2255-ironpythond11.png" alt="" width="356" height="430" /></td>
</tr>
<tr>
<td style="padding-left: 10px; padding-bottom: 10px; padding-right: 20px"><strong>Figure 1. </strong>The main Podcast list for Podcatcher. This is an example of WPF data binding where a data template and data trigger have been applied. The selected item shows the feed description in addition to the feed name, link and image.</td>
</tr>
</tbody>
</table>
</div>
<p>One of the most important and fundamental purposes of computers is to manipulate information. This can range anywhere from simple storage and retrieval to complex applications, like automated detection of diseased heart tissue. However, automated manipulation of data is only of limited interest. At some point, data must interact with human beings in order to be interesting. Luckily, Windows Presentation Foundation (WPF) has an extremely powerful feature meant to facilitate man's interaction with his data. This feature is called <a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx">data binding</a>. As described by Microsoft:</p>
<p>"Data binding is the process that establishes a connection between an application and the underlying logic. If the binding has the correct settings, when the data changes its value, the elements that are bound to the data reflect changes automatically."</p>
<p>Data binding has appeared in many incarnations among the various Microsoft technologies. A version of it can be found in Windows Forms as well among the various voodoo cults of web programming. Since data binding has been around for a while, the version included in WPF is a very mature technology. Tens of thousands of developers have helped Microsoft work out the rough edges and it is possible to do some rather sophisticated things.</p>
<p>While data binding is capable of doing sophisticated things to complex sets of information, you won't find much of that here. Rather, this article and the others in this series will focus on a very simple application: manipulating and displaying information from RSS feeds. After all, <a href="http://www.oak-tree.us/blog/index.php/2008/11/18/ironpython-part1">I am hardly an expert</a> in either IronPython or WPF. Rather, I plan to stick to comfortable ground and I will be returning to my Podcast aggregator. Previously, I created a <a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6">download manager</a> to handle the work of retrieving files; now it's time to start tackling another major module: the Library. In doing so, I will compose variations on a theme. I will show how WPF displays data and facilitates user interaction with that data. This article will introduce the features of the project and provide some background on data-binding. Later articles will look at code and how to add in bells and whistles.<span id="more-464"></span></p>
<h2>The Project</h2>
<p>With that introduction, let's talk about some of my program's needs. While the download manager of my Podcast aggregator is completed, a download manager without things to download is of little use. I, therefore, need a way to manage the podcasts I am currently subscribed to, delete podcasts which no longer interest me, and add additional podcasts. Much of the behind the scenes action will be provided by the <a href="http://msdn.microsoft.com/en-us/library/ms686418.aspx">Windows RSS platform</a> but I still need to provide the user interface. This is where WPF comes in.</p>
<p>There are three major components to my planned library interface. First, I need a way to list the podcasts to which I am currently subscribed and view details about a selected podcast (Figure 1 provides an example of what this might look like). Next, I need to see individual episodes for that podcast and be able to interact with the items. For each item, I want to be able to download the feed enclosure, listen to it using my computer, send it to my mobile phone or handheld using Windows Media Player, or delete it from the list. Last, I want a way to add new Podcasts to my subscriptions. Since the Windows RSS platform is integrated with Internet Explorer that is one way which additional Podcasts can be added. However, this is not necessarily the best or most convenient way to add additional podcasts. Referring to other podcast aggregators, like iTunes, provides some additional ways content might be added.</p>
<p>A great strengths of iTunes is its integrated Podcast directory, which is maintained through the iTunes store. The podcast directory offers users a central place to browse and subscribe to content while at the same time providing a means to discover new and unappreciated podcasts. It might even be fair to say that the podcast directory is one of the most compelling reasons to use iTunes. After some thought, I decided that it would be very nice to have a similar feature within my own podcast aggregator.</p>
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2009/01/010409-2255-ironpythond21.png" alt="" /></p>
<p style="text-align: center"><strong>Figure 2. iTunes Podcast Directory.</strong> The iTunes podcast directory, which is maintained by Apple, is a great way to discover new and unappreciated content.</p>
<p>It is very fortunate that a number of websites maintain directories similar to that in iTunes. While reading about the <a href="http://amarok.kde.org/blog/archives/574-Podcast-directory-service.html">podcast support</a> in one of my favorite Linux audio players, <a href="http://amarok.kde.org/">AmaroK</a>, I stumbled upon a catalog maintained by <a href="http://www.digitalpodcast.com/opml.php">DigitalPodcast.com</a>. This particular directory is slightly different from others as they publish their entire catalog as an <a href="http://en.wikipedia.org/wiki/OPML">OPML feed</a>. OPML is an XML format used for outlines and can be used to exchange a list of webfeeds between aggregators. To leave geek-speak behind for a minute, DigitalPodcast.com has made it ridiculously easy for anyone to add a Podcast directory to their program.</p>
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2009/01/010409-2255-ironpythond31.png" alt="" /></p>
<p style="text-align: center"><strong>Figure 3. User Interface Mock-Up for Podcast Catalog in Podcatcher. </strong>The catalog is maintained by <a href="http://www.digitalpodcast.com/opml.php">DigitalPodcast.com</a>.</p>
<h2>Data Binding Basics</h2>
<p>Now that the project has been described, let's review some of the fundamentals of data binding. These include how to create a binding and appropriately convert data when necessary in addition to defining some of the data binding vernacular. We'll then look at how data can be presented in a uniform manner by the use of <strong>DataTemplates</strong>.</p>
<h3>Data binding in WPF</h3>
<p>Data binding in WPF can be used to connect a broad range of object properties to a very large variety of data sources. These include CLR objects, ADO.NET objects, objects associated with Web Services or Web properties as well as XML data. Objects which are bound to a given data set can be grouped, filtered or sorted. Any changes which occur to the underlying data are immediately reflected in the user interface.</p>
<p>Data binding works as bridge from the interface to the underlying data. In Microsoft's language, the interface (or binding target) is also called a dependency object. The figure below (stolen from the <a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx">data binding</a> overview) shows how the data binding bridge works in practice. The binding target typically has a property which receives the data and the binding source typically has a property which supplies it. The link between the two can either be established in XAML or in code. Data can flow one-way (from the data source to the target or from the target to the source) or two ways where changes made to one are updated in the other instantly.</p>
<p style="text-align: center"><a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2009/01/010409-2255-ironpythond41.png" border="0" alt="" /></a></p>
<h3>Should I data bind with XAML or Python?</h3>
<p>In Windows Forms programming, much of the data binding occurs within the Visual Basic or C# code. WPF, however, is substantially different in that much of the syntax required for data binding appears alongside the XAML that defines the user interface. While it is possible to provide the syntax necessary for data binding from either XAML or code, it is easier to do some things from one location rather than the other. As my language of choice when working with WPF is Python, it should be mentioned that it is sometimes necessary to do things from code rather than from XAML. Defining how data should be presented in the XAML while managing the data source from the Python appears to work well.</p>
<h2>Data Templates</h2>
<p>WPF contains a convenient way to set up the presentation of data through the use of <a href="http://msdn.microsoft.com/en-us/library/ms742521.aspx">data templates</a>. All but the most trivial WPF programming require a means to present data in a more powerful way than just binding one property on an object to one property on a data source. Often, a data source will contain many related values and those values should combine to form a cohesive visual representation. <strong>DataTemplates</strong> provide instructions to the binding target about how they should display the data provided by the source. Without a data template, the data may be presented as a list of custom clr objects, or the presentation might not appear as you would expect.</p>
<p>Data templates are typically applied to the <strong>ItemTemplate</strong> property of the binding target. Nearly all WPF controls have the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplate.aspx">ItemTemplate</a> property. The ItemTemplate abstracts away the process of creating a proper container object. For example, if a data template is assigned to the <strong>ItemTemplate</strong> of a ListBox, the data binding classes will automatically generate a <strong>ListBoxItem</strong>. The DataTemplate could be applied to another control type, and the proper container would be generated for that object as well. Figure 1 in this article shows an example of a ListBox with a custom DataTemplate.</p>
<p>Conveniently, a DataTemplate can show mixed content including might include pictures, text or even animations. Further, through the use of styles and triggers, more than one DataTemplate can be used within the same object or a DataTemplate can be customized based on the content.</p>
<h3>DataTemplates and Reusability</h3>
<p>One of the greatest strengths of DataTemplates is their ability to be defined as a resource. This is typically done in the &lt;Window.Resources&gt; tag of the XAML file. An alternative is to declare the DataTemplate as part of the control which will use it. Consider the following examples, which create a very simple DataTemplate with only a single TextBlock. The first codeblock shows the template being declared inline and the second declares it as a resource.</p>
<pre class="brush: xml; title: ; notranslate">&lt;ListBox Width=&quot;400&quot; margin=&quot;10&quot; &gt;
    &lt;ListBox.ItemTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;TextBlock Text=&quot;{Binding Path = FeedName}&quot; /&gt;
        &lt;/DataTemplate&gt;
    &lt;ListBox.ItemTemplate&gt;
&lt;/ListBox&gt;</pre>
<pre class="brush: xml; title: ; notranslate">&lt;Window.Resources&gt;
    &lt;DataTemplate x:Key = &quot;Example1&quot;&gt;
        &lt;TextBlock Text = &quot;{Binding Path = FeedName}&quot; /&gt;
    &lt;DataTemplate&gt;
&lt;/Window.Resources&gt;</pre>
<p>There are substantial advantages to declaring a <strong>DataTemplate</strong> as a resource. The first is that it can be reused. It can be dynamically added to other controls that have a property which will accept a <strong>DataTemplate</strong> type. A second is that declarations within XAML are convenient. Such declarations are often shorter than their Python counterparts. An additional benefit is that declarations in XAML can act in a manner similar to a statically typed language without many of the drawbacks.</p>
<h3>Declaring a DataTemplate as a Static Resrouce</h3>
<p>As I mentioned above, it is possible to define data binding relationships completely from within the XAML markup. This ability is due to a feature of statically typed languages. When working with dynamic languages, we are then presented with somewhat of a conundrum. In many cases, data binding examples are performed completely within the XAML and this requires a statically typed language to function correctly. There is, however, a workaround for dynamic languages such as Python. DataTemplates can be declared as a Static Resource. When properly converted values are assigned, the data binding then just works. The code block below shows the main DataTemplate from Figure 1.</p>
<pre class="brush: xml; title: ; notranslate">&lt;Window&gt;
    &lt;Window.Resources&gt;
        &lt;DataTemplate x:Key=&quot;ShowFeed&quot; &gt;
            &lt;Grid x:Name=&quot;LayoutRoot&quot; Height=&quot;60&quot; Margin=&quot;5&quot;&gt;
                &lt;Image HorizontalAlignment=&quot;Left&quot; Margin=&quot;0,0,0,0&quot;
                    Stretch=&quot;Fill&quot; Width=&quot;60&quot;
                    Source=&quot;{Binding Path=Image}&quot;/&gt;
                &lt;TextBlock Margin=&quot;70,0,8,0&quot; Text=&quot;{Binding Path=Name}&quot;
                    FontSize=&quot;13&quot; TextWrapping=&quot;Wrap&quot; Height=&quot;35&quot;
                    VerticalAlignment=&quot;Top&quot; ScrollViewer.CanContentScroll=&quot;True&quot;/&gt;
                &lt;TextBlock Margin=&quot;70,0,0,9&quot; Text=&quot;{Binding Path=Link}&quot;
                    FontSize=&quot;11&quot; TextWrapping=&quot;Wrap&quot; Height=&quot;16&quot;
                    VerticalAlignment=&quot;Bottom&quot;
                    ScrollViewer.CanContentScroll=&quot;True&quot;/&gt;
            &lt;/Grid&gt;
        &lt;/DataTemplate&gt;
    &lt;/Window.Resources&gt; 

        &lt;Grid&gt;
            &lt;ListBox x:Name = &quot;listboxRssFeeds&quot; Itemtemplate=&quot;{StaticResrouce ShowFeed}&quot; /&gt;
        &lt;/Grid&gt;
&lt;/Window&gt;</pre>
<p> </p>
<p>The Python code includes a custom class that creates an object with Image, Name and Link properties. Once the values of the custom class are assigned to the DataSource property of the ListBox, the data is presented without further fuss. I will be returning to this example in depth during the next article in this series.</p>
<h3>Data Triggers</h3>
<p>Another powerful feature in DataTemplates is the ability to respond to the contextual details of the data. In Figure 1, the selected item shows the feed description in addition to the other information. This is accomplished by making use of a DataTrigger. DataTriggers are an important component of data binding and can be used to customize the appearance or response of a given object. They can include specific values within the data source or they can arise due to user interaction.</p>
<p>Using data triggers, it might be possible to bold the name of podcast feeds with new content or provide additional information about the selected feed. They are also highly flexible. Triggers can be defined within the DataTemplate itself or in the control where the DataTemplate will be applied. Given their importance, they will also feature prominently in Part 2 of this series.</p>
<h2>Conclusion</h2>
<p>Data binding and data templating are extremely powerful technologies that have been refined in WPF. Through the use of data binding, it is possible to present data in a highly attractive (and reusable manner). Further, it is possible to modify data presentation in response to its context and values. In this article, some of the important concepts and terms used in data binding and templating were reviewed. In Part 2 of this series, I will show how these concepts can be applied to a simple data source: a list of subscribed RSS feeds.</p>
<p><span style="color: #333333;">_____________________________________________________<br />
</span></p>
<h2>Acknowledgements, References and Further Reading</h2>
<p>The strategy and layout of this example has its roots firmly embedded in a <a href="http://devhawk.net/">DevHawk</a> article on the same subject. It's definitely worth having a <a href="http://devhawk.net/2008/11/18/IronPython+And+WPF+Part+3+Data+Binding.aspx">look</a>. The MSDN introductions to <a href="http://msdn.microsoft.com/en-us/library/ms752347.aspx">data binding</a> and <a href="http://msdn.microsoft.com/en-us/library/ms742521.aspx">data templating</a> give a good background of how these two technologies work. They also include an example that explores how these two technologies overlap.</p>
<p>The article "<a href="http://msdn.microsoft.com/magazine/cc163299">Data Binding in WPF</a>" which was published in the December 2007 edition of MSDN magazine includes a great introduction to the core data binding concepts. Another article, "<a href="http://msdn.microsoft.com/en-us/magazine/cc700358.aspx">Customize Data Display with data Binding and WPF</a>," gives a good overview on how to separate data from its presentation.<br />
_____________________________________________________<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials" rel="bookmark" title="December 11, 2008">IronPython – Windows Presentation Foundation Tutorials</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3" rel="bookmark" title="December 16, 2008">WPF – SVG Graphics and XAML – Part 3</a></li>
</ul>
<p><!-- Similar Posts took 23.506 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1">IronPython - Data Binding and Data Templates - Part 1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WPF – SVG Graphics and XAML – Part 3</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3#comments</comments>
		<pubDate>Tue, 16 Dec 2008 22:49:00 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Illustration]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=367</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+3&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-16&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3&amp;rft.language=English"></span>
As described in part 1 of this article, vector graphics offer a tremendous number of advantages over their raster counterparts. These benefits include the ability to enlarge the image to any size without a loss of detail or quality and better reproduction in both print and online form. Combined with the existence of many high [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3">WPF – SVG Graphics and XAML – Part 3</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+3&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-16&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3&amp;rft.language=English"></span>
<p>As described in <a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1">part 1</a> of this article, <a href="http://en.wikipedia.org/wiki/Vector_graphics">vector graphics</a> offer a tremendous number of advantages over their <a href="http://en.wikipedia.org/wiki/Raster_graphics">raster</a> counterparts. These benefits include the ability to enlarge the image to any size without a loss of detail or quality and better reproduction in both print and online form. Combined with the existence of many high quality icon libraries, vector graphics represent a valuable source of art for desktop applications.</p>
<p>In <a href="http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2">part 2</a> of this article, we looked at a way to convert vector graphics using Adobe Illustrator. While useful, the XAML export plug-in has a number of limitations and is not always able to faithfully convert the image to XAML. Thus, while Adobe Illustrator is a good conversion method when working directly with artists and graphic designers who are able to provide art files in Adobe Illustrator (AI) format, it is not so well suited to existing OpenSource libraries which tend to be distributed in the SVG format.</p>
<p>Due to their use of alpha transparency, Adobe Illustrator is always able to read the images from other editors, though it contains basic SVG support. This is unfortunate as these icon libraries, such as the <a href="http://www.oxygen-icons.org/">Oxygen Icon Set</a>, are freely available under permissive licenses. Fortunately, there is a way to overcome some of these limitations. In this article, I will look at how to convert SVG icons to XAML using the stand-alone utility <a href="http://www.codeplex.com/XamlTune">XamlTune</a>. We will also be using the OpenSource SVG editor, <a href="http://www.inkscape.org/">Inkscape</a>.</p>
<p style="TEXT-ALIGN: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph1.png" alt="" /><span id="more-367"></span></p>
<h2>SVG Icon Sources</h2>
<p>Prior to delving into the process by which SVG can be converted to XAML, I thought it might be good to take a minute and highlight some excellent sources of high quality SVG art. These include a number of general resources as well as dedicated SVG libraries.</p>
<h3>Wikimedia Commons</h3>
<p>One of the better art libraries can be found at <a href="http://commons.wikimedia.org/wiki/Main_Page">Wikimedia Commons</a>. It includes an enormous number of public domain and free-licensed media content with a healthy section of SVG images. Some of the more popular examples include the <a href="http://commons.wikimedia.org/wiki/Category:Nuvola_SVG_icons">Nuvola</a> and <a href="http://commons.wikimedia.org/wiki/Bluesphere_SVG_icons">Bluesphere</a> themes. The database of images is both searchable and browseable.</p>
<p>While the vast majority of the images are available in the public domain or under permissive licenses, it is important to read the specific license of each image which will be used. Even when using OpenSource artwork, the type of license is important. Images released under the GPL cannot be used in commercial projects, for example.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 142px;" span="1"></col>
<col style="width: 134px;" span="1"></col>
<col style="width: 206px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none">
<p style="text-align: center"><a href="http://upload.wikimedia.org/wikipedia/commons/2/24/Nuvola_apps_konsole.png"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph2.png" border="0" alt="" /></a></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none">
<p style="text-align: center"><a title="&quot;Nuvola Nordic flags.svg&quot;" href="http://upload.wikimedia.org/wikipedia/commons/8/89/Nuvola_Nordic_flags.svg"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph3.png" border="0" alt="" /></a></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none">
<p style="text-align: center"><a href="http://upload.wikimedia.org/wikipedia/commons/2/26/Nuvola_apps_edu_mathematics-ar.svg"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph4.png" border="0" alt="" /></a></p>
</td>
</tr>
<tr>
<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; TEXT-ALIGN: left" colspan="3"><strong>Figure 1. </strong>Sample images from the Nuvola theme at Wikimedia Commons</td>
</tr>
</tbody>
</table>
</div>
<h3>Oxygen</h3>
<p>The <a href="http://www.oxygen-icons.org/">Oxygen</a> icon theme is the default icon set for the KDE desktop. The sample artwork at the beginning of each of the parts in this series were taken from the Oxygen project. The set is licensed under both the LGPL and Creative Commons, as a result, it can be used in both commercial and OpenSource applications. There are a huge number of individual icons which cover actions, file types, and applications. Thus, between its beauty and permissive license, in addition to the fact that it is available in svg format, Oxygen is an ideal source of artwork. The Oxygen theme will be the source of the art used in this tutorial.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 159px;" span="1"></col>
<col style="width: 159px;" span="1"></col>
<col style="width: 160px;" span="1"></col>
<col style="width: 160px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px" colspan="2"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph5.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph6.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph7.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph8.png" alt="" /></td>
</tr>
<tr>
<td style="PADDING-RIGHT: 7px; PADDING-LEFT: 7px; TEXT-ALIGN: left" colspan="4"><strong>Figure 2.</strong> Sample images from the Oxygen icon set.</td>
</tr>
</tbody>
</table>
</div>
<p>In contrast to the icons available at Wikimedia Commons, however, the Oxygen Icons can only be downloaded via <a href="http://subversion.tigris.org/">Subversion</a>. You will thus need either need to download the command line toolset, or a GUI client like <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a>. The Oxygen icons can be found at:</p>
<p><span style="font-family: Courier New;">    svn://anonsvn.kde.org/home/kde/trunk/KDE/kdebase/runtime/pics/oxygen/<br />
</span></p>
<p>If you are working from the command line, go to the directory where you would like to save the icons., then type:</p>
<p><span style="font-family: Courier New;">    svn co svn://anonsv.kde.org/home/kde/trunk/KDE/kdebase/runtime/pics/oxygen Oxygen<br />
</span></p>
<p>The icons will be downloaded to a folder called 'Oxygen.' If you want to only download the SVG versions of the icons, use:</p>
<p><span style="font-family: Courier New;">    svn://anonsvn.kde.org/home/kde/trunk/KDE/kdebase/runtime/pics/oxygen/scalable</span></p>
<h2>Method 2: Inkscape and XamlTune</h2>
<h3>Installation<img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph9.png" alt="" align="right" /></h3>
<p>To convert SVG icons using XamlTune is a two step process. You will need to have both Inkscape and Xamltune. A Windows Installer for Inkscape can be found <a href="http://www.inkscape.org/download/?lang=en">here</a>. XamlTune can be downloaded from its <a href="http://www.codeplex.com/XamlTune">CodePlex download page</a>. Click on the "Download Now" button on the right part of the page.</p>
<p>After XamlTune has downloaded, you will need to extract the binary and supporting libraries to a folder. It does not have an automatic installer. To run XamlTune, double click on XamlTune.exe. Alternatively, there is also a WebApp version, which can be found <a href="http://labs.ucaya.com/xamltune/">here</a>. The in this tutorial were converted using the desktop application.</p>
<h3>Program Use</h3>
<p>XamlTune is only able to convert well-formed SVG to XAML. When I tried converting compressed SVG (svgz), it caused the program to crash. Thus it is very important to make sure that they are plain, vanilla SVG. If they were created by Inkscape, Krita, or OpenOffice Draw this is likely not the case. All three programs use markup not part of the SVG standard to properly render and edit the images. While this additional markup is ignored by viewers, it may cause a converter to crash.</p>
<h4>Convert SVGZ to SVG</h4>
<p>The first step is to then convert the distribution format to vanilla SVG. To do so:</p>
<ol>
<li>Open Inkscape and load the file. </li>
<li>Choose <strong>File &gt; Save As</strong></li>
<li>Select the destination and provide the name of the file. In the list of file types, choose <strong>Plain SVG </strong>and then click "Ok."</li>
</ol>
<h4>Conversion to Xaml – Desktop Application</h4>
<p>The XamlTune UI includes two windows, which are shown in figure 3 below. The first window is used for input and the second window is used for output. You can either cut and paste the SVG into the text box or load it from file. The second window contains the conversion options, the converted XAML, and a preview of the converted image. It is possible to convert to both WPF and Silverlight XAML.</p>
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph10.png" alt="" /></p>
<p><strong>Figure 3. The XamlTune User Interface. </strong>There are two windows in the XamlTune UserInterface. The first is used for the data. The second window includes the conversion options, the converted XAML text and a preview of the converted image.</p>
<p>Once the image has been converted, it can be saved to the active directory by typing a filename and clicking the "<strong>Save</strong>" button. You will need to add the .xaml, as this is not done by the program automatically.</p>
<h4>Examples</h4>
<p>The examples below show images that were converted with XamlTune from plain SVG. In each case, there were significant differences between the source image and the converted XAML. The most common discrepancies were seen in shadows and complex gradients which used alpha transparency. I also noticed problems in images which made use of extensive typography, however.</p>
<p>The first example (Figure 4) is a beautiful rendering of a newspaper. It includes a number of complex gradients and makes extensive use of typography. In the exported XAML, many of the gradients were not correctly exported nor was the text.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 352px;" span="1"></col>
<col style="width: 352px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph11.png" alt="" /></p>
</td>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph12.png" alt="" /></p>
</td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph13.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph14.png" alt="" /></td>
</tr>
<tr>
<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; TEXT-ALIGN: left" colspan="2"><strong>Figure 4. </strong>The top panels show how the original SVG image appears in Inkscape. The detail at right has been zoomed to 400% of the original size. The bottom panel shows the XAML created by XamlTune. While most of the gradients and much of the illustration was converted without difficulty, the fonts and type were ignored.</td>
</tr>
</tbody>
</table>
</div>
<p>In the second example (Figure 5) shows similar issues as the first. The color effects on the controls in addition to the shadows were not correctly exported. Other elements were shifted from their original location, which suggests that there may be an issue in keeping track of coordinates.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 319px;" span="1"></col>
<col style="width: 319px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph15.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph16.png" alt="" /></td>
</tr>
<tr>
<td style="PADDING-RIGHT: 7px; PADDING-LEFT: 7px; TEXT-ALIGN: left" colspan="2"><strong>Figure 5.</strong> In this example, it is possible to notice some distortion in the converted Xaml. Some of the gradients were not properly converted and some of the controls have shifted location. The shadows have also not been correctly rendered.</td>
</tr>
</tbody>
</table>
</div>
<p>In this third example, we see a complex example with gradients, shadows and lettering. Again, there are major discrepancies between the source image (left) and the exported XAML. In addition, there is also some distortion of the chip body.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 319px;" span="1"></col>
<col style="width: 319px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph17.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px" valign="middle">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121608-2248-wpfsvggraph18.png" alt="" /></p>
</td>
</tr>
<tr>
<td style="PADDING-RIGHT: 7px; PADDING-LEFT: 7px; TEXT-ALIGN: left" colspan="2"><strong>Figure 6.</strong> As in previous examples, there are some major inconsistencies between the source image and the converted XAML. Shadows and some gradients did not transfer correctly. The background image of an X on the top of the chip was also omitted.</td>
</tr>
</tbody>
</table>
</div>
<h2>Conclusion</h2>
<p>Much like XAML created with the Adobe Illustrator plug-in, there are often discrepancies between the source SVG and the final image. XamlTune struggled to consistently portray complex gradients (making use of alpha transparency) as well as to properly render shadows. Simpler images which lack these elements appeared to export without distortion. While not a perfect solution, both techniques allow for SVG assets to be converted to XAML and used in both WPF and Silverlight applications.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2" rel="bookmark" title="December 14, 2008">WPF – SVG Graphics and XAML – Part 2</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1" rel="bookmark" title="December 13, 2008">WPF – SVG Graphics and XAML – Part 1</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/07/backup-part5-2" rel="bookmark" title="July 7, 2009">Backup, Sync and Share &ndash; Part 5.2: Windows Vista Backup (Disaster Prevention)</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1" rel="bookmark" title="January 6, 2009">IronPython - Data Binding and Data Templates - Part 1</a></li>
</ul>
<p><!-- Similar Posts took 37.670 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3">WPF – SVG Graphics and XAML – Part 3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WPF – SVG Graphics and XAML – Part 2</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2#comments</comments>
		<pubDate>Sun, 14 Dec 2008 05:34:38 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Illustration]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=342</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+2&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-14&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2&amp;rft.language=English"></span>
In part 1 of this article, I introduced some of the difficulties in converting SVG graphics to WPF XAML. These included inconsistent implementations across SVG editors and the lack of a high quality XAML export. I also introduced two methods for the conversion of vector graphics to XAML. The first uses Adobe Illustrator and the [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2">WPF – SVG Graphics and XAML – Part 2</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+2&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-14&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2&amp;rft.language=English"></span>
<p>In <a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1">part 1</a> of this article, I introduced some of the difficulties in converting SVG graphics to WPF XAML. These included inconsistent implementations across SVG editors and the lack of a high quality XAML export. I also introduced two methods for the conversion of vector graphics to XAML. The first uses Adobe Illustrator and the second makes use of free standalone program called XamlTune. In this article will take a detailed look at the first of these methods. In part 3, we will look at the second method.</p>
<p style="text-align: center;"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph1.png" alt="" /><span id="more-342"></span></p>
<h2>Method 1: Adobe Illustrator</h2>
<p>When working on most vector graphics projects, there is really only one software program that really matters: Adobe Illustrator. While I'd like to say it is the 800 pound gorilla in the room, it is probably more accurate to say it is the only gorilla in the room. Given its near omnipresence in the artistic community, it is hugely convenient that there is a <a href="http://www.mikeswanson.com/XAMLExport/default.htm">highly capable plug-in</a> which can export high quality XAML directly from Illustrator.</p>
<h3>Installation</h3>
<p>Installation of the plug-in is simple and straightforward. You can find it at <a href="http://www.mikeswanson.com/XAMLExport/default.htm">MikeSwanson.com</a>, under XamlExport. After it has been downloaded, unzip it to the Illustrator Illustrator plug-in folder. For a Windows default installation of Create Suite CS3, the path is <strong>C:\Program Files\Adobe\Adobe Illustrator CS3\Plug-ins</strong>. If you don't have access to the administrator account on your computer or if you prefer to install to an alternate location, that is also possible. Go to <strong>Edit &gt; Preferences &gt; Plug-ins &amp; Scratch Disks</strong> and put a check in the "Additional Plug-ins Folder." You can then specify a folder other than the default.</p>
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph2.png" alt="" /></p>
<p>Once you have copied the XAMLExport.aip file to the proper folder, you will need to restart Adobe Illustrator. The export to XAML option can be found under <strong>File &gt; Export</strong>. There will be options to export to both Windows Presentation Foundation XAML and Silverlight XAML. The export plug-in works with Adobe Illustrator CS, CS2 or CS3.</p>
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph3.png" alt="" /></p>
<h3>Plug-In Use</h3>
<p>Using the plug-in, it is possible to export any file which Illustrator is capable of reading. This includes AI files, Illustrator compatible SVG files, and PDF files. The size of the exported images is adjusted by changing the document properties, found under <strong>File &gt; Document Setup.</strong></p>
<p>While the plugin will work on all file types, not all of the features of Adobe Illustrator are supported. Mark Swenson gives a detailed list at the <a href="http://www.mikeswanson.com/XAMLExport/default.htm">download site</a>, but there are a few import limitations that should be mentioned.</p>
<ol>
<li>Text Export. In the current implementation, there is no support for WPF native text rendering. While it is possible to work around this limitation by choosing <strong>Select &gt; Object &gt; Text Objects</strong> then changing the text to an outline prior to performing the export (<strong>Type &gt; Create Outlines</strong>), this is an imperfect solution.</li>
<li>Raster Images. There is no support for raster images that are part of the AI image. Illustrator images that incorporate any Photoshop documents or other bitmap style objects will not export correctly.</li>
<li>Illustrator Meshes. Illustrator meshes cannot be exported and will be ignored in the final output.</li>
</ol>
<p>While the lack of text and raster image support prevent the export plug-in from rendering XAML that is 100% identical to the source image, it nonetheless produces high quality output from most Adobe Illustrator objects. I experimented with a number of logos and design elements with generally good results, though there were some issues with complex paths and gradients. Some examples are shown below.</p>
<h3>Examples</h3>
<p>In the first example (Figure 1), I have used a simple logo from the <a href="http://hodad.sci.utah.edu/">Scientific Computing Institute (SCI)</a> at the University of Utah. A screenshot of the original as it appears in Illustrator is shown (top left panel) as well as two different exports. The first time I performed the export (seen in the top right panel), I did not first convert the text elements to outlines. As a result, the lettering was not converted to XAML correctly. In the second export (bottom panel), I converted the lettering to an outline prior to the export.</p>
<div style="text-align: center; margin-left: 42pt">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 291px;" span="1"></col>
<col style="width: 291px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph4.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph5.png" alt="" /></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px" colspan="2">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph6.png" alt="" /></p>
<p style="text-align: left;"><strong>Figure 1. Original SCI Logo (top left) and XAML Export from Adobe Illustrator. </strong>In the first instance (top right), the text was not changed to an outline prior to export. As a result, it was ignored. In the second instance (bottom), the text was transformed prior to export.</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>In a second example (Figure 2), we see an example where an icon contains unsupported elements. While most of the image is faithfully rendered, there are two major issues. First, an error occurred when rendering the color of the inner path, which is supposed to white. This region appears as an off grey in the XAML. There was also an issue with the beautiful blue to violet gradient on the left of the image. In the XAML, it is rendered as a single color.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 351px;" span="1"></col>
<col style="width: 265px;" span="1"></col>
</colgroup>
<tbody>
<tr style="height: 324px;">
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph7.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph8.png" alt="" /></p>
</td>
</tr>
<tr style="height: 69px;">
<td style="padding-right: 7px; padding-left: 7px; text-align: left;" colspan="2"><strong>Figure 2. Amarok Icon. </strong>The image at left shows the original artwork in Adobe Illustrator and the image at right shows the exported XAML. There are two problems in the export. The center path is no longer white and the blue to violet gradient now appears as a solid band of light blue.</td>
</tr>
</tbody>
</table>
</div>
<p>Figure 3 shows a particularly complex example which was rendered without any issues. The original image was created from a photo using Illustrator's <a href="http://graphicssoft.about.com/od/illustrator/ss/sflivetrace.htm">LiveTrace</a> feature. The image contains hundreds of individual paths, gradients and other elements. Yet, despite its complexity, it was rendered to XAML without problem.</p>
<div style="text-align: center">
<table style="border-collapse:collapse" border="0">
<colgroup span="1">
<col style="width: 351px;" span="1"></col>
<col style="width: 265px;" span="1"></col>
</colgroup>
<tbody>
<tr style="height: 324px;">
<td style="padding-left: 7px; padding-right: 7px"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph9.png" alt="" /></td>
<td style="padding-left: 7px; padding-right: 7px">
<p style="text-align: center"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121408-0533-wpfsvggraph10.png" alt="" /></p>
</td>
</tr>
<tr style="height: 69px;">
<td style="padding-right: 7px; padding-left: 7px; text-align: left;" colspan="2"><strong>Figure 3. XAML export of an Illustrator LiveTrace Image. </strong>Even though the image contains hundreds of paths and complex elements, the XAML export is an extremely good representation of the original image.</td>
</tr>
</tbody>
</table>
</div>
<p style="text-align: center"> </p>
<h2>Summary</h2>
<p>The XAML exporter plug-in provides high quality XAML directly from Adobe Illustrator without requiring any intermediate steps. This is convenient due to the near omnipresence of the Adobe products among artists and designers. However, the plug-in also has some serious limitations. It is not able to export native text and may have issues with complex gradients.</p>
<p>In Part 3, I will look at using XamlTune, a standalone converter utility.</p>
<p>_____________________________________________________</p>
<h2>Acknowledgements, References and Further Reading</h2>
<h3>Further Reading</h3>
<p>There is <a href="http://channel9.msdn.com/posts/scobleizer/Mike-Swanson-Adobe-Illustrator-to-XAML-converter/">25 minute video</a> which explains the basic use and function of the XAML export plug-in. It is hosted on <a href="http://channel9.msdn.com/">MSDN Channel09</a>.</p>
<h3>Legal Acknowledgements</h3>
<p>The logo of the Scientific Computing Institute is copywrite (2008) by the University of Utah. It may not be used for commercial purposes without written permission from the University of Utah. <span style="color: #333333;">The <a href="http://www.oxygen-icons.org/?page_id=4"></a></span>Oxygen Icon Theme<span style="color: #333333;"> is dual licensed under the <a href="http://creativecommons.org/licenses/by-nc-nd/2.5/"></a></span>Creative Common Attribution-ShareAlike 3.0 License<span style="color: #333333;"> as well as the <a href="http://www.gnu.org/licenses/lgpl.html"></a></span>GNU Lesser General Public License<span style="color: #333333;">.</span><br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3" rel="bookmark" title="December 16, 2008">WPF – SVG Graphics and XAML – Part 3</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1" rel="bookmark" title="December 13, 2008">WPF – SVG Graphics and XAML – Part 1</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/07/backup-part5-2" rel="bookmark" title="July 7, 2009">Backup, Sync and Share &ndash; Part 5.2: Windows Vista Backup (Disaster Prevention)</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/30/time-traveler" rel="bookmark" title="July 30, 2009">A Better Previous Versions: Time Traveler</a></li>
</ul>
<p><!-- Similar Posts took 23.736 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2">WPF – SVG Graphics and XAML – Part 2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>WPF – SVG Graphics and XAML – Part 1</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1#comments</comments>
		<pubDate>Sat, 13 Dec 2008 23:35:31 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Computer]]></category>
		<category><![CDATA[Illustration]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=309</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+1&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-13&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1&amp;rft.language=English"></span>
In a perfect world, most would be judged on the quality of their ideas and depth of character. However, more often they are judged by looks and dress.  What is true in the world of people is also true in the world of software. More than one website, computer program, or presentation has suffered because [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1">WPF – SVG Graphics and XAML – Part 1</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=WPF+%E2%80%93+SVG+Graphics+and+XAML+%E2%80%93+Part+1&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Computer&amp;rft.subject=Illustration&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-13&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1&amp;rft.language=English"></span>
<p style="text-align: left;">In a perfect world, most would be judged on the quality of their ideas and depth of character. However, more often they are judged by looks and dress.  What is true in the world of people is also true in the world of software. More than one website, computer program, or presentation has suffered because it is unattractive. In the inevitable fight between style and substance, substance often exerts more than its fair share of influence.</p>
<p>Given the importance of stylistic presentation, it is somewhat ironic that one of the most neglected components of many software projects it that of the artwork. While the code may be carefully vetted and analyzed, often icons and other artwork are chosen at the last stage of the design. While this might be unfortunate, it is due to an important reality: high quality artwork can be very, very expensive.</p>
<p>Fortunately, there are a number of beautiful graphics libraries that are either cheap or free of charge. Most are available under permissive or OpenSource licenses and can even be used in commercial products. There is just one problem; nearly all of these libraries are available in formats which don't play nicely with WPF and XAML. With a little bit of planning and strategy, however, it isn't too difficult to use these resources in your own applications.<span style="font-family: Consolas;"><br />
</span></p>
<p style="text-align: center"><a href="http://www.oxygen-icons.org/?cat=3"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121308-2334-wpfsvggraph12.png" border="0" alt="" /></a><span id="more-309"></span></p>
<h2>Working with Vector Graphics</h2>
<p>While there are a huge number of beautifully done vector graphics, it is important to understand a few basic things about vector images prior to working with them. These include how they are both similar to and different from traditional graphics formats, as well as some practical limitations and realities. It is also important to know which programs you will be working with. SVG vector graphics created in one program can't always be opened in another editor.</p>
<h3>Traditional Image Formats Versus SVG: What Are the Differences?</h3>
<p>Anyone who works with computers is familiar with the familiar types of image formats: jpeg, png, bmp, etc. These are the file types that come from digital cameras, scanners, and <a href="http://en.wikipedia.org/wiki/Raster_graphics">raster</a> based graphics programs (such as Photoshop). A raster graphic is composed of a collection of (usually) rectangular pixels. In black and white images, there is value at each pxiel that describes the intensity. A value of zero corresponds to black while large values correspond to white. Values in the middle are differing shades of grey. Color images, in contrast are coded by values that correspond to red, green, or blue. These disparate values are then mixed to arrive at the final shade. Programs such as Photoshop and the GIMP edit the individual pixel values.</p>
<div>
<table style="border-collapse:collapse; padding-right:10px" border="0" align="left">
<colgroup span="1">
<col style="width: 318px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-left: 7px; padding-right: 7px"><a href="http://en.wikipedia.org/wiki/Image:Rgb-raster-image.png"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121308-2334-wpfsvggraph22.png" border="0" alt="" /></a></td>
</tr>
<tr>
<td style="padding-left: 7px; padding-right: 7px; padding-bottom: 7px; "><strong>Figure 1. Example of a Raster Based Graphic</strong>. Raster images are composed of arrays of pixels. At each pixel location, there is a value that corresponds to the color of the pixel. Image Source: <a href="http://en.wikipedia.org/wiki/Image:Rgb-raster-image.png">Wikipedia</a>.</td>
</tr>
</tbody>
</table>
</div>
<p>Raster images are dependent on the resolution which they are displayed. As can be seen in the example (Figure 1), the image looks better at low resolution. When it is enlarged to a high resolution, it becomes blurry.</p>
<p>In contrast to raster images, vector images are based on mathematical models. They combine different geometrical elements (such as points, lines, curves, shapes, etc) to describe the shape and color of the final drawing. They also make it easier to use a variety of advanced filters and processing tricks to generate effects such as transparency or light.</p>
<p>Vector images also offer another important benefit over raster images. They can be enlarged without a loss of quality. Figure 2 illustrates this point; it show how a vector image appears when it is enlarged. A bitmap, enlarged to the same size, is also shown for comparison</p>
<h3>Limitations and Realities</h3>
<p>While SVG has been adopted as an official W3C standard, it has never been really endorsed by any of the major software developers (which is ironic since it was initially developed and advocated by Adobe). This has led to a large number of parallel implementations, on both the proprietary and OpenSource sides of the fence. In addition to parallel implementations, SVG has suffered from limited penetration. The most common type of vector graphics in the art world isn't SVG, but rather the native file format of Adobe Illustrator, AI.</p>
<p>To further complicate things, many of the programs which read SVG files support different parts of the specification. While Adobe Illustrator can export directly to XAML through use of a plugin, the most common version of Illustrator (CS3) uses a rather basic implementation of the SVG standard. It lacks support for alpha channels and other advanced features, which makes it impossible to open images from other SVG editors.</p>
<p>It doesn't get much better from the OpenSource side of the fence either. File conversion and portability might charitably be described as "promising." The most popular editor, <a href="http://www.inkscape.org/">Inkscape</a>, implements most of the features available in the WC3 standard; it doesn't, however, play nicely with other programs. It includes its own extensions to the file format. While these extensions should effect image portability in theory, I found otherwise in practice. In multiple tests, I was not able to export images to a format which could be read by Illustrator or other OpenSource editors. And while Inkscape has a plugin to export XAML directly, the output is garbled and unusable. Other OpenSource programs, such as OpenOffice Draw and Krita, offer only very basic support for the file format and are still under active development.</p>
<div>
<table style="border-collapse:collapse; padding-left:10px" border="0" align="right">
<colgroup span="1">
<col style="width: 379px;" span="1"></col>
</colgroup>
<tbody>
<tr>
<td style="padding-right: 7px; padding-left: 7px; text-align: center;"><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121308-2334-wpfsvggraph32.png" alt="" /></td>
</tr>
<tr style="height: 102px;">
<td style="padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  none"><strong>Figure 2. Example of a Vector Based Graphic. </strong>Vector graphics are composed of different geometrical shapes (points, lines, curves, etc) to describe the shape and color of final image. Vector graphics can be scaled to any size without losing any quality. Image Source: <a href="http://en.wikipedia.org/wiki/File:VectorBitmapExample.png">Wikipedia</a>.</td>
</tr>
</tbody>
</table>
</div>
<p>Microsoft is hardly a champion of interoperability either. There is only one program which can read and write XAML files directly; Microsoft's own <a href="http://www.gnu.org/licenses/lgpl.html">Expression Suite</a>. In a rather egregious oversight, the Expression suite lacks an easy way to import SVG and directly convert it to XAML.</p>
<p>So while WPF includes support both raster and vector images, many of the more advanced features of WPF (including resolution independence) really need vec tor graphics to function properly and getting the more common SVG file formats (.ai and .svg) converted to XAML can be difficult.</p>
<h3>The Solutions</h3>
<p>Luckily, however, there are two ways to successfully convert SVG to XAML. Determining which method to use largely depends on the source of the file.</p>
<ol>
<li>The first uses an Adobe Illustrator <a href="http://blogs.msdn.com/mswanson/archive/2005/07/12/438178.aspx">plugin</a> to export AI files too XAML. This method should be used when working with professional artists or graphic designers (who are likely to use the Creative Suite of Applications).</li>
<li>The second makes use of a free standalone program (<a href="http://www.codeplex.com/XamlTune">XamlTune</a>) to convert properly formatted SVG to XAML. This process makes the most sense when using existing OpenSource libraries or other freely available samples.</li>
</ol>
<p>In the next article in this series, I will look at these two methods in depth.</p>
<p>_____________________________________________________</p>
<h2>Acknowledgements, References and Further Reading</h2>
<h3>Additional Reading</h3>
<p style="text-align: justify">There is an <a href="http://weblogs.asp.net/jgalloway/archive/2007/06/05/silverlight-and-xaml-have-you-guys-met-old-man-svg.aspx">overview</a> of why WPF uses a different specification than SVG to display vector graphics on <a href="http://weblogs.asp.net/jgalloway/default.aspx">Jon Galloway's blog</a>.</p>
<p style="text-align: justify">Mike Swanson, author of the <a href="http://www.mikeswanson.com/XAMLExport/">XAML Adobe Illustrator Plugin</a>, has a dedicated page which describes the installation and limitations of the plug-in. This includes a <a href="http://www.mikeswanson.com/XAMLExport/Eye%20Candy.htm">sample gallery</a> with a number of complex examples.</p>
<p>On <a href="http://www.uxpassion.com/">UXPassion</a>, there is a tutorial about how to convert to XAML using a <a href="http://www.uxpassion.com/2008/10/how-to-convert-svg-to-xaml-and-use-it-in-silverlight-or-wpf/">PDF intermediary</a>.</p>
<h3>Legal</h3>
<p style="text-align: justify">The image examples in this tutorial were taken from Wikipedia and are available in the Public Domain. The logos and images of the <a href="http://www.sci.utah.edu/">Scientific Computing Institute</a> (SCI) are copyrighted (2008) by the University of <a href="http://www.carinsurancerates.com/utah-car-insurance.html">Utah</a>. They may not be used for commercial purposes without written permission from the University of Utah. The <a href="http://www.oxygen-icons.org/?page_id=4">Oxygen Icon Theme</a> is dual licensed under the <a href="http://creativecommons.org/licenses/by-nc-nd/2.5/">Creative Common Attribution-ShareAlike 3.0 License</a> as well as the <a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General Public License</a>.</p>
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/14/wpf-svg-xaml-part2" rel="bookmark" title="December 14, 2008">WPF – SVG Graphics and XAML – Part 2</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3" rel="bookmark" title="December 16, 2008">WPF – SVG Graphics and XAML – Part 3</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/01/25/backup-part2" rel="bookmark" title="January 25, 2009">Backup, Share and Sync &ndash; Part 2: Hard Drive Preparation and Server Configuration</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/07/07/backup-part5-2" rel="bookmark" title="July 7, 2009">Backup, Sync and Share &ndash; Part 5.2: Windows Vista Backup (Disaster Prevention)</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1" rel="bookmark" title="January 6, 2009">IronPython - Data Binding and Data Templates - Part 1</a></li>
</ul>
<p><!-- Similar Posts took 16.289 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1">WPF – SVG Graphics and XAML – Part 1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/13/wpf-svg-xaml-part1/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>IronPython – Windows Presentation Foundation Tutorials</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials#comments</comments>
		<pubDate>Thu, 11 Dec 2008 19:38:02 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=301</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+%E2%80%93+Windows+Presentation+Foundation+Tutorials&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-11&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials&amp;rft.language=English"></span>
After finishing the download manager of my podcast aggregator (PodCatcher), I took a few days off to work on other things. After a brief break, though, I am back at the grindstone and I can happily say that it is starting to come together. The next major component of the aggregator that I will work [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials">IronPython – Windows Presentation Foundation Tutorials</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=IronPython+%E2%80%93+Windows+Presentation+Foundation+Tutorials&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-11&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials&amp;rft.language=English"></span>
<p><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/121108-1937-ironpythonw1.png" alt="" align="left" />After finishing the <a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6">download manager</a> of my <a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2">podcast aggregator</a> (PodCatcher), I took a few days off to work on other things. After a brief break, though, I am back at the grindstone and I can happily say that it is starting to come together.</p>
<p>The next major component of the aggregator that I will work on is the library module. This will include the functions necessary to view, add, remove and manage the different Podcast feeds and the individual podcast episodes. Due to my initial architecture, I have hit a patch of luck.</p>
<p>Since the aggregator sits on top of the <a href="http://msdn.microsoft.com/en-us/library/ms686418.aspx">Windows RSS Platform</a>, much of the "library" functionality is already handed to me. Further, because Internet Explorer uses the RSS platform and the Common Feeds List, there will be a nice integration with other programs. The ability to subscribe to new podcasts from the browser always made more sense to me than the model of other aggregators, where management occurs exclusively in the Podcast Manager.</p>
<p>Since much of the backend is already written, I have been thrown into a realm of programming where I have done very little work: the user interface. While I touched on the user interface a little in the <a href="http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7">Learning IronPython</a> series, I have now gotten serious about it. The screenshot shows the subsequent result. I have a prototype user interface for PodCatcher!</p>
<p>While putting the UI together, however, I discovered a bit of a surprise.  According to the Oracle of Google, there isn't a lot of material on WPF and dynamic languages. What is worse, getting the UI to load and function isn't as simple as applying stock C# principles. To answer my (many) questions I have spent quite a bit of time hunting down tutorials and looking at everything I can find about IronPython and WPF. After trundling through Google, the IronPython users archive, MSDN, and the major IronPython blogs, I have a pretty good list and I thought it might be of interest to others trying to learn IronPython.<span id="more-301"></span></p>
<h2>The Basics – Hello World to Event Handlers</h2>
<p>When getting started, it's best to start with the basics.  As a rite of passage in every programming language, the Hello World Application seemed to make perfect sense for those learning WPF and IronPython. Luckily, there are a diverse number of examples and styles for loading a Window and sending salutations to the world.</p>
<ol>
<li><a href="http://www.seblec.com/?post/2008/11/23/Discovering-IronPython%3A-WPF-Sample">Discovering IronPython - Hello World WPF Sample</a>. This post describes how to create a WPF window and load in Xaml from a file.</li>
<li><a href="http://www.ironpython.info/index.php/WPF_Example">WPF – Example – Working with the StackPanel</a>. This example shows how to create a StackPanel and add elements to it. In contrast to the previous example, all of the manipulation occurs in the code behind.</li>
<li><a href="http://www.ironpython.info/index.php/XAML_GUI_Events_Example">WPF – GUI Events Example</a>. How to load a GUI from a XAML form and hook up events to event handlers dynamically.</li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3">A Multithreaded Hello</a>. How to load a window and launch a BackgroundWorker that counts to 100. (I know, it's a shameless plug.)</li>
</ol>
<h2>Building on the Basics</h2>
<p>While loading windows and hooking up event handlers is useful, it can only get you so far. WPF includes a wealth of additional features like <a href="http://msdn.microsoft.com/en-us/library/ms531387(VS.85).aspx">DataBinding</a>, <a href="http://msdn.microsoft.com/en-us/library/ms742521.aspx">DataTemplates</a>, <a href="http://msdn.microsoft.com/en-us/library/system.windows.trigger.aspx">Triggers</a>, <a href="http://www.microsoft.com/belux/msdn/nl/community/columns/gillcleeren/wpf_stylesandtriggers.mspx">Styles</a> and dozens of other powerful features. it is fortunate that there are a few IronPython specific articles which touch upon how these work with a dynamic language.</p>
<p>An excellent place to start is the <a href="http://devhawk.net/2008/11/13/IronPython+And+LtInsert+MSFT+Technology+Heregt.aspx">IronPython and [Insert MSFT Technology Here]</a> series over on <a href="http://devhawk.net/">DevHawk</a>. The series begins with six posts about how IronPython works with WPF. They all describe a single project (a photo viewer for a Live.com photo feed), so there is a very nice continuity amongst the articles.</p>
<ul>
<li><a href="http://devhawk.net/2008/11/13/IronPython+And+WPF+Part+1+Introduction.aspx">IronPython and WPF – Part 1</a>. In the first article, the ground is set by describing the sample project. Though there isn't a link to them in the first post, you can find the sample files for the project <a href="http://cid-0d9bc809858885a4.skydrive.live.com/self.aspx/DevHawk%20Content/IronPython%20Stuff/WpfThreadDemo.zip?sa=962228383">here</a>.</li>
<li><a href="http://security.symantec.com/sscv6/vc_scan.asp?vc_prescan=1&amp;ax=1&amp;vc_scanstate=2&amp;langid=ie&amp;venid=sym&amp;plfid=24&amp;pkj=UPFRBXUQIZQVMUYTACDhttp://devhawk.net/2008/11/14/IronPython+And+WPF+Part+2+Loading+XAML.aspx">IronPython and WPF – Part 2 : Loading Xaml</a>. This article describes how to compose a user interface in Blend and load it by using a Python script. It is a variation on the Hello World Tutorials above. While it covers a lot of old ground, it also includes a description of how to use C# with custom hooks so that WPF and IronPython play nicely together.</li>
<li><a href="http://devhawk.net/2008/11/18/IronPython+And+WPF+Part+3+Data+Binding.aspx">IronPython and WPF – Part 3 : DataBinding</a>. This article is a must read for anyone interested in WPF and IronPython. It gives a great overview of DataBinding and how IronPython work together. DataBinding is a technology which works wonderfully, but requires a strategy.</li>
<li><a href="http://devhawk.net/2008/11/19/IronPython+And+WPF+Part+4+Background+Processing.aspx">IronPython and WPF – Part 4 : Background Processing</a>. WPF, like Windows Forms, only has a single GUI thread. As a result, long-running processes can clog it and make the UI unresponsive. This article gives a nice overview about how to move functions into the background using Python <a href="http://www.python.org/dev/peps/pep-0318/">decorators</a>.</li>
<li><a href="http://devhawk.net/2008/11/20/IronPython+And+WPF+Background+Processing+Revisited.aspx">IronPython and WPF – Part 4.1 : Background Processing Revisited</a>. In this addendum to <em>IronPython and WPF – Part 4</em>, the author looks at an alternative method to perform the background processing. It also links to a very interesting article that describes <a href="http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx">SynchronizationContext</a>.</li>
<li><a href="http://devhawk.net/2008/11/21/Background+Processing+ReRevisited.aspx">IronPython and WPF – Part 4.2 : Background Processing Re-Revisted</a>. This secondary addendum to <em>IronPython and WPF – Part 4</em> looks at a more elegant way to perform background processing via decorators.</li>
<li><a href="http://devhawk.net/2008/11/24/IronPython+And+WPF+Part+5+Interactive+Console.aspx">IronPython and WPF – Part 5 : The Interactive Console</a>. In this article DevHawk looks at how to implement a loop so that he can interact with his program when it is running. I have used a similar method for poking around inside PodCatcher. As you might imagine, it is very, very valuable to see what objects are loaded and what methods are available.</li>
</ul>
<h2>Tools</h2>
<p>Anyone who has been poking around IronPython for a while has probably stumbled across <a href="http://www.codeplex.com/IronPythonStudio">IronPython Studio</a>, a fantastic tool for working with IronPython from within Visual Studio. When playing with Windows Forms, it works beautifully. However, there are some limitations <a href="http://blogs.msdn.com/aaronmar/archive/2007/08/01/ironpython-integration-sample-and-the-wpf-designer.aspx">when using WPF</a>.</p>
<h2>Additional Examples?</h2>
<p>Admittedly, this list is a bit sparse. Do you know of any additional tutorials or resources? If so please post them in the comments or send them my way. I will also add to the list as I find more material.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 2 – A Simple Project</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/01/06/ironpython-databinding1" rel="bookmark" title="January 6, 2009">IronPython - Data Binding and Data Templates - Part 1</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
</ul>
<p><!-- Similar Posts took 19.294 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials">IronPython – Windows Presentation Foundation Tutorials</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning IronPython - Part 7 - A Summary of Lessons Learned</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7#comments</comments>
		<pubDate>Mon, 08 Dec 2008 19:21:37 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.oak-tree.us/blog/?p=263</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+-+Part+7+-+A+Summary+of+Lessons+Learned&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Featured&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-08&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7&amp;rft.language=English"></span>
Now that I have finished a major component of my PodCast client, I feel as though I have reached a transition point. I have managed to create a useful (albeit small) program and I have become much more productive when I use WPF, Python and the .Net frameworks. So I thought it prudent to take [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7">Learning IronPython - Part 7 - A Summary of Lessons Learned</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+-+Part+7+-+A+Summary+of+Lessons+Learned&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=Featured&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-08&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7&amp;rft.language=English"></span>
<p>Now that I have finished <a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6">a major component of my PodCast client</a>, I feel as though I have reached a transition point. I have managed to create a useful (albeit small) program and I have become much more productive when I use WPF, Python and the .Net frameworks. So I thought it prudent to take a moment and reflect on some of the lessons which I have learned over the course of the last few weeks. After all, learning doesn't necessarily happen in the struggle and frustration of the moment, but in the quiet reflection which comes after.</p>
<p>While there were many specific things I wish I had known (for example, that the <a href="http://www.oak-tree.us/blog/index.php/2008/12/05/the-win32-api-and-simplicity">Win32 API is complicated</a>), there were a few general items that I thought particularly helpful. As a result, this post is going to be painted in the broad swash of generalities. A few specific things I would like to touch on are: setting goals and measuring progress, following schedules while maintaining flexibility, working on a real (practical) project, trying new things out, limiting the number of dependencies, and seeking high quality examples and references. <span id="more-263"></span></p>
<h2>Set Goals and Measure Progress</h2>
<p>I began this series of articles with a confession, and I think it is time for me to make another. This is not the first time that I have attempted to learn Python. It is merely the most successful. Previously, I downloaded the compiler and worked my way through some of the tutorials. A few years ago, I was so enthusiastic as to buy a fifty dollar book on the subject. In fact, when I started this little odyssey, I tried to dig it out for reference and was unable to find it.</p>
<p>The differences between my previous attempts to master Python and this one can be wrapped up in a single word: goals. While I had an "intention" to learn Python, I didn't really have any definitive plans to do anything with it. I would arrive at the end of the tutorial and think, "That was cool, now what?" The rather sad answer to that question , however, was "Good question."</p>
<p>This time round, however, I had very specific plans. I carefully reviewed my needs and came up with a <a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2">number of projects</a> that targeted things that I would like to do, or need to do. This assessment is where my desire for a Podcast client came from and I was able to enumerate a few specific goals that could actually be completed. It is much easier to complete a goal worded as, "Finish a multithreaded download manager" than "Learn IronPython." The first has a discrete start and end point and can be measured. The second has no such built in way to track progress. This same distinction often differentiates good science from poorly executed science. Often in the latter, there is no way to measure or track results. This leads to discouragement and abandonment.</p>
<p>While setting goals and tracking progress may seem superfluous in a personal activity, I actually found them indispensable to "getting things done." While I largely avoided a full "timetable," I did have a goal to complete one blog post of new material every few days. This required that I spend the requisite time thinking about the next steps in my application, researching the various techniques necessary to write the code, and then spending the time to create a working implementation. Without my goals, it is possible I would not have had the personal discipline to invest the time required to make this experiment successful.</p>
<h2>Follow Schedules While Maintaining Flexibility</h2>
<p>While goals provided the focus of "what" to work on, it was also important that I find time to do that work. Like most people, I hopelessly commit and over-schedule myself; often to the detriment of my own projects and of those close to me. Yet, I found that learning how to work in Python was a sufficiently large undertaking that it required regular time and attention. I therefore set aside an hour or so each day for working with my given project. During this time, I would try and read different references, study ways to potentially implement an idea, or try things out with the command line interpreter. Of course, I also spent time actually writing code.</p>
<p>By sticking to a fairly rigid schedule, I found something else interesting; I needed to be flexible. It is very easy to underestimate the amount of time that a given task is going to require or how complicated a given task will be. In such cases, it is important to be flexible. A number of times, I was forced to re-evaluate both my goals and schedule. While this often meant spending more time than I had planned, it also meant lowering my expectations.</p>
<h2>Work on Something Real</h2>
<p>Spending more time than planned on a project designed for "instruction" nearly always feels like a waste. While an undergraduate student at the University of Utah, I took an introductory computer science course which focused on Java. It was an awful experience. I spent thirty hours a week doing homework and completing assignments which had little (if any) practical value. While I learned much about the Java language and frameworks, I didn't learn much that was useful. To this day, I actively avoid doing anything in Java even though I can muddle my way through most C++ code (which is thought in some quarters to be a more difficult language).</p>
<p>When learning IronPython, I was hoping to avoid a similar experience. Thus … my carefully chosen projects. I have often found it easier to be excited about a given piece of software if I will be using that software myself. Far too many times I have heard about a great piece of software, only to discover that it was completely unusable. Until quite recently, a fantastic example is <a href="http://software.sci.utah.edu/SCIRunDocs/index.php/CIBC:Seg3D">Seg3D</a>, a program put out by the University of Utah <a href="http://www.sci.utah.edu/">Scientific Computing Institute (SCI)</a>.</p>
<p>In its earlier builds, Seg3D represented a application looking for a need rather than the other way round. While it did many fantastic things, it would only do so on a very finite number of test data and with a great degree of prodding from someone who had spent hours trying to get it to behave. While this has since been (somewhat) straightened out, it was only after the developers began using their own software. The developer as user paradigm is a good one as it encourages the developers to think about better ways to accomplish a given task. Amongst my serious developer friends, Visual Studio is considered to be the best general IDE in existence (rivaled, perhaps, by Eclipse). I would argue this is because its developers are also its primary users.</p>
<p>Working on a real piece of software that can be used (by both myself and others) gives a degree of energy and focus when confronting challenges and difficulties. Rather than a canned exercise with a specific solution, the struggles and difficulties are also real, though they may also seem larger. Even so, having a "real" project helped me to persevere and complete my work in the absence of other incentives.</p>
<h2>Try Things Out</h2>
<p>Unlike compiled languages, Python and other scripting languages ship with an interactive interpreter that begs to be used. When trying out the various .Net classes, I tried to apply a piece advice found in IronPython in Action.</p>
<blockquote><p>For those new to dynamic languages, the interactive interpreter will … be a pleasant surprise. Far from being a toy, the interactive interpreter is a fantastic tool for experimenting with classes and objects at the console. You can instantiate and explore … classes live, using introspection and the built-in 'dir' and 'help' commands to see what methods and attributes are available to you. As well as experimenting with objects, you can also try out language features to see how they work … (IronPython in Action, Chapter 1).</p></blockquote>
<p><img src="http://www.oak-tree.us/blog/wp-content/uploads/2008/12/120808-1920-learningiro1.png" alt="" align="left" />I found the interpreter to be a fundamental part of my experimentation. As you can see from the screen shot at left, the interpreter became one of my most used programs. it even passed Microsoft Word, which is the first program I open after turning on my computer.</p>
<p>I often found myself transcribing interpreter commands into my code, once I had figured out how to accomplish a particularly difficult set of manipulations. In many ways, the interpreter became my de-facto composition board and I was able to avoid the write-compile-run loop equivalent which often sucks up my time when working in other languages.</p>
<h2>Limit the Number of Dependencies</h2>
<p>I have found that learning to program can sometimes be similar to another computer based experience. Namely, my first growing pains with Linux. I began experimenting with Linux in 2002,using the SuSE distribution. Though the initial install went beautifully, there were a number of programs I wanted to try which were not included on the installation CD. The SuSE RPM framework was still young and I hadn't discovered the beauty which is apt-get. I therefore set about installing my software in the most difficult manner imaginable. I downloaded individual packages and attempted to install them with the package manager. This was my first real experience with packages and dependencies. I quickly discovered the state of existence referred to in the early days of Windows as "DLL Hell."</p>
<p>In one unpleasant example, while trying to install a statistical package, I spent the better part of two days downloading different packages and trying to manually resolve the dependencies. This was when I first learned of something called "nested dependencies." Or, dependencies of dependencies. At the end of the two days, I still didn't have a functioning program, despite hours spent searching for and downloading packages. This experience drove me back to Windows ranting and raving about Linux and OpenSource in general. I was lucky to have friends and others who encouraged me to be patient and allow for the software to develop and come into its own. I am glad I did, I am now a very happy user of Ubuntu.</p>
<p>It is unfortunate (but still true), that learning to program can lead a very similar experience. Programming is a very sequential subject. To be able to function, it is necessary to know a lot of things. Even more disconcerting, before it is possible to understand a given piece of code, it is often necessary to understand one (or more) other ideas. This easily leads to dependencies and dependencies of dependencies. When trying to work with WPF, for example, I found that I needed to know about XAML and databinding. This involved a rather lengthy side trip before I was able to return to working with the much more elegant Python.</p>
<p>So, in the interest in progress, I often found myself needing to simplify. Put another way, I needed to ditch as many dependencies. I was more productive (and more satisfied) when I was working with one or two ideas rather than five or six. So, by keeping the number of technologies to a relative minimum, I was able to actually make something work, rather than uselessly waste my time.</p>
<h2>Find High Quality Reference and Documentation</h2>
<p>As described above, trying to learn anything as complex as Python requires good reference and documentation. While <a href="http://manning.com/foord/">IronPython in Action</a> proved itself invaluable, I found myself rapidly migrating away from it. After reading the first several chapters that outline Python and the .Net framework and the chapters on Windows Forms and WPF, I set it aside for other references. These included blog posts, the <a href="http://www.ironpython.info/index.php/Main_Page">IronPython Cookbook</a>, the MSDN .Net documentation, and <a href="http://www.codeproject.com/">CodeProject</a> (not to mention Google, which is after all, a programmer's best friend).</p>
<p>What I discovered, however, is that each one of these resources was of varying quality. While the IronPython Cookbook was an excellent source of IronPython recipes, much of the information on MSDN and CodeProject was either out of date or incomplete. Faced with a quandary, I began to note the names of authors and locations of material which I found helpful. I then included these names in my Google searches when looking for additional information. Using this strategy, I was able to find posts which often quoted or built upon the work of the original author. I was also often able to find additional posts by the same author. This led to uncovering examples written in C# or Visual Basic that could be translated into IronPython. Doing so taught me a great deal about how the structure of .Net programming should look and proved to be very valuable. It also taught me that I sometimes needed to widen my search.</p>
<p>When trying to find a good way of using a ProgressDialog, I located a C# example that used a BackgroundWorker thread. Using the ideas (and much of the code structure) in this example helped me create the ProgressDialog class in the download manager. I found the code example by a Google search that included the author's name from a previous article.</p>
<h2>Conclusion</h2>
<p>The astute reader will note that many of these generalities do not necessarily have much to do with programming, which is true. However, I found that I was most productive and content when I attempted to follow these general guidelines. I also discovered a more important side effect: after more than a month of playing with Python, I have to admit that I am hooked. While I am still certainly very green, I feel as though I have learned a great deal. It is a fantastic language and offers more flexibility and power than Matlab. In some ways, it is Matlab "all grown up." So, I was successful in at least one of my initial goals; I avoided a fiasco similar to my Java experience.</p>
<p>On a more practical note, while I will remain a student of Python for quite some time, my writing about it needs to become somewhat more … irregular and topical. I hereby retire my label of "Learning IronPython" for a simpler one: "IronPython." While there will surely be other posts (I already have a post on data-binding half written and ideas for six or seven others), they will likely reflect the gems and nuggets I unearth as I further my adventurous exploits rather than a careful and complete documentation of my travels.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 2 – A Simple Project</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/18/ironpython-part1" rel="bookmark" title="November 18, 2008">Learning IronPython – Part 1 – A Halfhearted Manifesto</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials" rel="bookmark" title="December 11, 2008">IronPython – Windows Presentation Foundation Tutorials</a></li>
</ul>
<p><!-- Similar Posts took 38.575 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7">Learning IronPython - Part 7 - A Summary of Lessons Learned</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/08/ironpython-part7/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Learning IronPython - Part 6 - From Rudimentary to Functional</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6#comments</comments>
		<pubDate>Sun, 07 Dec 2008 22:54:18 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://robertsoakes.brinkster.net/blog/?p=246</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+-+Part+6+-+From+Rudimentary+to+Functional&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-07&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6&amp;rft.language=English"></span>
In the last article of this series, my download manager based on the Background Intelligent Transfer Service (BITS) in Microsoft Windows had reached a functional (though far from aesthetically pleasing) state. Making use of a multithreaded model and interfacing with BITS through a C# wrapper, the download manager has been designed to integrate into my [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6">Learning IronPython - Part 6 - From Rudimentary to Functional</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+-+Part+6+-+From+Rudimentary+to+Functional&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-07&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6&amp;rft.language=English"></span>
<p><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/12/120708-1859-learningiro1.png" alt="" align="right" />In the <a href="http://robertsoakes.brinkster.net/blog/">last article</a> of this series, my download manager based on the <a href="http://msdn.microsoft.com/en-us/library/aa362708(VS.85).aspx">Background Intelligent Transfer Service (BITS)</a> in Microsoft Windows had reached a functional (though far from aesthetically pleasing) state. Making use of a <a href="http://robertsoakes.brinkster.net/blog/?p=75">multithreaded model</a> and <a href="http://robertsoakes.brinkster.net/blog/?p=141">interfacing with BITS through a C# wrapper</a>, the download manager has been designed to integrate into my IronPython "learning project," a <a href="http://robertsoakes.brinkster.net/blog/http:/robertsoakes.brinkster.net/blog/?p=71">PodCast plug-in for Windows Media Player</a>.</p>
<p><span style="font-size:9pt"><strong>Figure 1 - Right. User interface of the fully functional IronPython Download Manager. </strong>Major features include the ability to run downloads in the background without affecting foreground application performance and the ability to pause and resume downloads.<br />
</span></p>
<p>With all the major pieces in place, this article will focus on some of the smaller details which transform a rudimentary download manager into a functional one. The files for this article can be found <a href="http://www.oak-tree.us/Tutorials/TestApp_20081203.zip">here</a>. <span id="more-246"></span></p>
<h2>Widgets, Controls and Functionality</h2>
<p>While my rudimentary download manager was "good enough" to get the job done, it lacked both elegance and style. The screen shot at right shows the new download manager, and as is apparent, now it just lacks style.</p>
<p>As compared to the <a href="http://robertsoakes.brinkster.net/blog/?p=222">previous incarnation</a>, there are a number of changes. Some of the more major ones include:</p>
<ul>
<li>All active downloads have been moved from separate windows into a single list.</li>
<li>Two separate views have been added. One for active downloads, which includes information about the download source, the name of the file, and its download progress. The second includes information about the downloaded file.</li>
<li>Downloads can now be paused and re-started.</li>
</ul>
<p>These changes combine to make the program both more functional and easier to use. They were also very easy to implement, requiring only simple changes to the existing code. To understand how, it is necessary to delve into some of the bowels of <a href="http://msdn.microsoft.com/en-us/netframework/aa663326.aspx">Windows Presentation Foundation (WPF)</a> and <a href="http://msdn.microsoft.com/en-us/library/ms752059.aspx">XAML</a>, which was used to build the user interface.</p>
<h2>Extensible Application Markup Language (XAML)</h2>
<p>Just like Python, XAML is a computer programming language in its own right and is incredibly powerful. This was something I underestimated when <a href="http://robertsoakes.brinkster.net/blog/?p=63">I started out on my IronPython Adventure</a>. XAML is used to define the widgets and controls of the user interface as well as their position. However, it can also be used to define their basic behavior and properties. But that is not all! XAML also includes a vector graphics language (similar to SVG) and typesetting capabilities (similar to PDF). Thus using XAML, the user-interface, the graphics, and the text can all be programmed in the same language. In one <a href="http://compilewith.net/2007/10/wpf-simple-text-editor-in-less-than-20.html">particularly impressive example of XAML</a>, a Microsoft Developer created a text editor with spell check and copy/paste in less than 20 lines of XAML code.</p>
<p>There are also more practical benefits to XAML. Perhaps one of the greatest is the ability to separate the function of a program (sometimes called the model) from the UI of the program (called the view). This makes it easier to introduce a separate designer/programmer based workflow as well as maintain the individual classes that comprise the code.</p>
<h3>Windows, Controls and UserControls</h3>
<p>XAML was specifically designed so that one control is capable of hosting the contents of another. Given the markup based nature of the language, it treats text, graphics, and even other UI widgets in a very similar manner. As a result, the technique used to add text to a download button is very similar to that used to add a graphic.</p>
<p>This made it trivially easy to change the manner in which my <strong>ProgressDialog</strong> window is treated. Consider the two code examples below. The first example shows the XAML markup used to create the <strong>ProgressDialog</strong> as a separate window. The second example shows the code used to create the <strong>ProgressDialog</strong> as an item in the main window.</p>
<p>Code Example 1 : <strong>ProgressDialog</strong> as a separate window.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;Window
xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
Title=&quot;Progress Dialog&quot; Width=&quot;300&quot; SizeToContent=&quot;Height&quot;&gt;
    &lt;Grid&gt;
        &lt;StackPanel Margin=&quot;10&quot;&gt;
            &lt;ProgressBar Name=&quot;DownloadProgressBar&quot; Width=&quot;236&quot;
            Height=&quot;21&quot; Minimum=&quot;0&quot; Maximum=&quot;1&quot; Margin=&quot;10&quot;
            HorizontalContentAlignment=&quot;Stretch&quot; /&gt;
            &lt;StackPanel Orientation=&quot;Horizontal&quot; FlowDirection=&quot;RightToLeft&quot;&gt;
                &lt;Button x:Name=&quot;CancelButton&quot; Width=&quot;84&quot;
                Height=&quot;22&quot;&gt;Cancel&lt;/Button&gt;
            &lt;/StackPanel&gt;
        &lt;/StackPanel&gt;
    &lt;/Grid&gt;
&lt;/Window&gt;
</pre>
<p>Code Example 2 : <strong>ProgressDialog</strong> as a control on the main download window.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;UserControl
xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
Width=&quot;Auto&quot; Height=&quot;67&quot;&gt;
    &lt;Grid&gt;
        &lt;StackPanel Margin=&quot;10&quot;&gt;
            &lt;ProgressBar Name=&quot;DownloadProgressBar&quot; Width=&quot;236&quot;
            Height=&quot;21&quot; Minimum=&quot;0&quot; Maximum=&quot;1&quot; Margin=&quot;10&quot;
            HorizontalContentAlignment=&quot;Stretch&quot; /&gt;
            &lt;StackPanel Orientation=&quot;Horizontal&quot; FlowDirection=&quot;RightToLeft&quot;&gt;
                &lt;Button x:Name=&quot;CancelButton&quot; Width=&quot;84&quot;
                Height=&quot;22&quot;&gt;Cancel&lt;/Button&gt;
            &lt;/StackPanel&gt;
        &lt;/StackPanel&gt;
    &lt;/Grid&gt;
&lt;/UserControl&gt;
</pre>
<p>As can be seen, there is only one minor modification to the XAML. The Window tag in the root node of the first example has been changed to a UserControl tag in the second. This one simple addition allows for the behavior of the control to completely change. It can now be added to other controls, such as a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.aspx"><strong>ListBox</strong></a> control, with all of its functionality intact. The Python code associated with the ProgressDialog class largely does not change. In fact, I was able to simplify it by removing the code specific to showing and closing the now unneeded window.</p>
<p>After converting the <strong>ProgressDialog</strong> to a UserControl, I added a <strong>ListBox</strong> control to the program's main form to show the individual download <strong>ProgressDialogs</strong>. No other changes were made to the XAML of the main form. The XAML for the revised main form is shown below.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;Window xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
Title=&quot;IronPython - Download Manager&quot; Width=&quot;450&quot;
SizeToContent=&quot;Height&quot; Height=&quot;Auto&quot;
MinWidth=&quot;450&quot; MinHeight=&quot;106&quot;&gt;
    &lt;Grid Height=&quot;Auto&quot; Width=&quot;Auto&quot;&gt;
        &lt;Separator Margin=&quot;0,0,0,69&quot; Height=&quot;10&quot; VerticalAlignment=&quot;Bottom&quot; /&gt;
        &lt;ListBox x:Name=&quot;listboxDownloads&quot; Margin=&quot;0,0,0,85&quot; /&gt;
        &lt;TextBox x:Name=&quot;txtDownloadUrl&quot; Margin=&quot;6.67,0,110,38&quot; Height=&quot;25&quot;
        VerticalAlignment=&quot;Bottom&quot; /&gt;
        &lt;Button x:Name=&quot;buttonDownloadFile&quot; Margin=&quot;0,0,5,38&quot;
        HorizontalAlignment=&quot;Right&quot; Width=&quot;98.5&quot; Height=&quot;25&quot;
        VerticalAlignment=&quot;Bottom&quot;&gt;Download File&lt;/Button&gt;
        &lt;TextBlock Margin=&quot;6.67,0,0,7&quot; HorizontalAlignment=&quot;Left&quot;
        Width=&quot;110.055&quot; Height=&quot;25&quot; VerticalAlignment=&quot;Bottom&quot;&gt;Download Directory
        &lt;/TextBlock&gt;
        &lt;TextBox x:Name=&quot;txtDownloadDirectory&quot; Margin=&quot;123,0,5,7&quot;
        Height=&quot;25&quot; VerticalAlignment=&quot;Bottom&quot; /&gt;
    &lt;/Grid&gt;
&lt;/Window&gt;
</pre>
<p>Individual items are added to the ListBox with a single line of code in the <strong>btnDownloadFile_Click</strong> event handler of the main script (TstApp_20081203.py):</p>
<pre class="brush: plain; title: ; notranslate">

    def btnDownloadFile_Click(self, sender event):
        …
        self.listboxDownloads.Items.Add(RssDownload.Root)
</pre>
<h2>Bells and Whistles</h2>
<p><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/12/120708-1859-learningiro2.png" alt="" align="left" />By changing the behavior of the <strong>ProgressDialog</strong>, I have taken a step toward unifying the UI of my BITS based Download Manager and that of Firefox, which is serving as my "inspiration." Both windows now prominently feature a central area which shows the number of downloads and their progress. However, there are a number of features included in the FireFox download manager which have not yet been added to my BITS version.</p>
<p><span style="font-size:9pt"><strong>Figure 2. User interface for the Firefox Download Manager.<br />
</strong></span></p>
<p>These include the ability to pause and resume downloads, as well as information about the download source and the file name. It is fortunate that these additional features are also quite easy to add to the <strong>ProgressDialog</strong> class of the download manager.</p>
<h3>Download Details</h3>
<p>XAML includes a simple widget, called a TextBlock, which can display either formatted or unformatted text. The information necessary to populate these widgets be passed to the <strong>ProgressDialog</strong> using the RunWorkerThread method. So, the only code modifications necessary are in the <strong>RunWorkerThread</strong>, <strong>Worker_DoWork</strong> and <strong>Worker_RunWorkerCompleted</strong> methods of the <strong>ProgressDialog</strong> class. An additional button can also be added to toggle between a paused and active state.</p>
<p>In the code block below is shown the new <strong>RunWorkerThread </strong>method. The original <strong>RunWorkerThread</strong> method received three inputs: the function to be run on the background thread (workHandler), a reference to the <strong>BitsJob</strong> (rssJob), and an initial argument (always set to zero) for the <strong>Worker.RunWorkerAsync()</strong> method. The new function, in contrast, receives five inputs. The three original as well as a string that points to the DownloadUrl and to the file destination (FileUrl).</p>
<pre class="brush: python; title: ; notranslate">

    def RunWorkerThread(self, workHandler, rssJob, DownloadUrl, FileUrl, argument):

        if self.autoIncrementInterval &gt; -1:
        self.ProgressTimer.Interval =
        … TimeSpan.FromMilliseconds(self.autoIncrementInterval)
        self.ProgressTimer.Start()

        self.RemoteFileUrl = urlparse.urlparse(DownloadUrl) # 1
        self.LocalFileUrl = FileUrl

        self.uiCulture = Globalization.CultureInfo.CurrentUICulture
        self.WorkerCallback = workHandler # 2
        self.rssJob = rssJob

        self.txtDownloadSource.Text = self.RemoteFileUrl[1] # 3
        self.txtDownloadName.Text = os.path.basename(self.RemoteFileUrl[2])
        self.txtDownloadProgress.Text = self.txtDownloadName.Text

        self.Worker.RunWorkerAsync(argument) # 4
</pre>
<p>The revised function, in addition to launching the background worker using <strong>RunWorkerAsync</strong> (#4), also adds information to the various <strong>TextBlocks</strong>. Information about the site from which it is downloading and the file name is spliced from the DownloadUrl using the Python function, <a href="http://www.python.org/doc/2.5.2/lib/module-urlparse.html">urlparse</a> (#1). Urlparse returns a 6-tuple which includes information about the type of url (file, http, ftp, etc), the site domain, and the download file name. This information is then added to the corresponding <strong>TextBlock </strong>(#3).</p>
<h3>Pause/Resume the Download Job</h3>
<p>The <strong>BitsJob</strong> pointer (rssJob) which is passed to the <strong>ProgressDialog</strong> contains the <strong>BitsJob.Suspend()</strong> and <strong>BitsJob.Resume()</strong> methods. These two methods contain the functionality necessary to pause and resume the download. A new button, buttonChangeStatus, which has been added to the right of the progress bar provides a simple implementation so that the user can call these events as necessary from the GUI. The event handler code is shown below.</p>
<pre class="brush: python; title: ; notranslate">

    def buttonChangeStatus_Click(self, sender, event):

        if self.Paused == False: # 1
        self.Paused = True # 2
        self.rssJob.Suspend() # 3
        self.buttonChangeStatus.Content = self.StartDownloadIcon # 4
        self.buttonChangeStatus.ToolTip = 'Resume Download' # 5
        return

        if self.Paused == True: # 6
        self.Paused = False
        self.rssJob.Resume() # 7
        self.buttonChangeStatus.Content = self.PauseDownloadIcon
        self.buttonChangeStatus.ToolTip = 'Pause Download'
        return
</pre>
<p>Upon first running, the subroutine checks the current state of the <strong>BitsJob</strong>. If it is active (#1), then it first changes the <strong>ProgressDialog</strong> state to self.Paused = True and suspends the <strong>BitsJob</strong> (#2). It then loads a custom icon (#4) and changes the ToolTip text to indicate that clicking on the button will resume the download (#5). If the state is paused, a similar series of events occurs (#6). The job is resumed (#7) and the button text and icon are changed to indicate that clicking them will pause the download.</p>
<h3>Wrapping Up</h3>
<p>Once the <strong>BitsJob</strong> has finished transferring, <strong>Worker_RunWorkerCompleted</strong> is called.</p>
<pre class="brush: python; title: ; notranslate">

    def Worker_RunWorkerCompleted(self, sender, event):

        self.ProgressTimer.Stop()
        self.DownloadProgressBar.Value = self.DownloadProgressBar.Maximum
        self.CancelButton.IsEnabled = False

        # Complete the Download Job
        self.rssJob.Complete() # 1

        # Set the Controls to Completed State
        self.CancelButton.Visibility = Visibility.Collapsed # 2
        self.buttonChangeStatus.Visibility = Visibility.Collapsed
        self.DownloadProgressBar.Visibility = Visibility.Collapsed

        if self.Cancelled == False: # 3
            TimeComplete = DateTime.Now # 4
            TimeCompleteString = TimeComplete.ToString() �
            self.txtDownloadProgress.Text = 'Download Complete'
            self.txtDateTime.Visibility = Visibility.Visible # 5
            self.txtDateTime.Text = TimeComplete.ToString()

            # Set the File Icon # 6
            FileIcon = RetrieveIcon.GetLargeIcon(self.LocalFileUrl)
            FileBmp = FileIcon.ToBitmap()
            strm = MemoryStream()
            FileBmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png)

            bmpImage = BitmapImage()

            bmpImage.BeginInit()
            strm.Seek(0, SeekOrigin.Begin)
            bmpImage.StreamSource = strm
            bmpImage.EndInit()
            self.imgIcon.Source = bmpImage
            self.imgIcon.Height = 48
            self.imgIcon.Width = 48

        else:
            self.txtDownloadProgress.Text = 'Download Cancelled' # 7
</pre>
<p>First, the event handler completes the <strong>BitsJob</strong> (# 1) and hides the Progressbar, Cancel Button and Pause/Resume Button (#2) by setting their Visibility property to Collapsed. In contrast to Windows Forms, WPF makes use of three visibility option: Visibility.Visible which displays the element, Visibility.Hidden which hides the element but still reserves space in the layout, and Visibility.Collapsed which neither shows the element nor reserves space in the layout.</p>
<p>If the download completes without being cancelled (#3), then the current time is added to the txtDateTime TextBlock (#4, #5) and the txtDownloadProgress TextBlock is set to 'Download Complete (#4). Last, the icon for the file type is retrieved and displayed in the Picture element, imgIcon (#6). If the user presses the cancel button, the <strong>ProgressDialog.Cancelled</strong> property is set to True and the text in txtDownloadProgress is set to "Download Cancelled."</p>
<h2>Conclusion</h2>
<p>After adding the ability to Pause/Resume the download and additional elements which display the download details, the rudimentary download manager described in the last article becomes a useful and functional program. This completes an important component of my Podcast Plugin. More importantly, since beginning this project, I have learned a great deal about IronPython, WPF and the .Net framework. The next article in this series will offer a brief summary of some of those lessons.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 2 – A Simple Project</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/16/wpf-svg-xaml-part3" rel="bookmark" title="December 16, 2008">WPF – SVG Graphics and XAML – Part 3</a></li>
</ul>
<p><!-- Similar Posts took 19.417 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6">Learning IronPython - Part 6 - From Rudimentary to Functional</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Learning IronPython – Part 5 – A Rudimentary Download Manager</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5#comments</comments>
		<pubDate>Tue, 02 Dec 2008 02:42:25 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://robertsoakes.brinkster.net/blog/?p=222</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+5+%E2%80%93+A+Rudimentary+Download+Manager&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-01&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5&amp;rft.language=English"></span>
Now that the background and semi-theoretical parts about BITS, multithreading, and downloads have been dealt with; it's time to start wrapping up ends and build a useable program. In this post, I will be looking at how to connect my multithreaded BackgroundWorker Object and SharpBITS to a functioning user interface that notifies the user of [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+5+%E2%80%93+A+Rudimentary+Download+Manager&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-12-01&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5&amp;rft.language=English"></span>
<p>Now that the <a href="http://robertsoakes.brinkster.net/blog/?p=71">background</a> and <a href="http://robertsoakes.brinkster.net/blog/?p=141">semi-theoretical parts</a> about <a href="http://msdn.microsoft.com/en-us/library/aa362708(VS.85).aspx">BITS</a>, <a href="http://robertsoakes.brinkster.net/blog/?p=75">multithreading</a>, and downloads have been dealt with; it's time to start wrapping up ends and build a useable program. In this post, I will be looking at how to connect my multithreaded <strong>BackgroundWorker</strong> Object and <strong>SharpBITS</strong> to a functioning user interface that notifies the user of the download's progress. For those wishing to follow along, the source files and assemblies for this article can be found <a href="http://www.oak-tree.us/Tutorials/TestApp_20081126.zip">here</a>.<span id="more-222"></span></p>
<h2>The Download Manager</h2>
<p><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/12/120108-2021-learningiro12.png" alt="" align="left" />In the first iteration of the download manager, the main form was nothing more than a glorified "Hello World." While its only button practically begged to be pushed, it didn't do anything more complicated than launch a <strong>BackgroundWorker</strong> and the <strong>CountTo100</strong> function.</p>
<p>A generic download manager, however, needs to be slightly more functional, which requires more than a single button. The user interface needs to accept input from the user, including the source of the download as well as a destination folder. As a result, the UI (by necessity) requires more controls. The figure below shows the modified user interface and the code block below provides source XAML of the Download Manager main form. It now includes two text boxes, one for the download URL and the other for the destination directory. The button has been resized and the text changed to better describe its function.</p>
<p style="text-align: center"><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/12/120108-2021-learningiro22.png" alt="" /></p>
<p style="text-align: center"><span style="font-size:9pt"><strong>Figure 1. Download manager user interface. The top text box is used for the download url and the bottom text box is used to specify the download directory.<br />
</strong></span></p>
<p>As can be seen in the source XAML below, I have also added a number of StackPanel objects so that the new TextBoxes and Button stay organized.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x:'http://schemas.microsoft.com/winfx/2006/xaml'
Title=&quot;IronPython - Download Manager&quot; Width=&quot;450.864&quot;
SizeToContent=&quot;Height&quot; Height=&quot;106&quot; MaxWidth=&quot;451&quot;
MinWidth=&quot;450.864&quot; MinHeight=&quot;106&quot;&gt;
    &lt;StackPanel Height=&quot;Auto&quot; Width=&quot;Auto&quot; Orientation=&quot;Vertical&quot;&gt;
        &lt;StackPanel Height=&quot;Auto&quot; Width=&quot;Auto&quot; Orientation=&quot;Horizontal&quot;&gt;
            &lt;TextBox x:Name=&quot;txtDownloadUrl&quot; Height=&quot;22.725&quot; Width=&quot;323.604&quot; /&gt;
            &lt;Button x:Name=&quot;buttonDownloadFile&quot; Height=&quot;22.725&quot;
             Width=&quot;103.626&quot;&gt;
            Download File&lt;/Button&gt;
        &lt;/StackPanel&gt;
        &lt;Separator Height=&quot;12.726&quot; Width=&quot;Auto&quot; /&gt;
        &lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
            &lt;TextBlock Height=&quot;20.907&quot; Width=&quot;112.716&quot; &gt;
            Download Directory&lt;/TextBlock&gt;
             &lt;TextBox x:Name=&quot;txtDownloadDirectory&quot; Height=&quot;22.725&quot;
            Width=&quot;314.514&quot; /&gt;
        &lt;/StackPanel&gt;
    &lt;/StackPanel&gt;
&lt;/Window&gt;
</pre>
<p>In the __init__ function of the main script (TestApp_20081126), the TextBoxes (#2) are created in the same way as the Button (#1).</p>
<pre class="brush: python; title: ; notranslate">
class TestApp(object):
    def __init__(self):
        xamlStream = File.OpenRead('DownloadManager.xaml')
        self.Root = XamlReader.Load(xamlStream)
        self.buttonDownloadFile =
        ... self.Root.FindName('buttonDownloadFile')    # 1
        self.txtDownloadUrl =�
        ... self.Root.FindName('txtDownloadUrl')        # 2
        self.txtDownloadDirectory =
        ... self.Root.FindName('txtDownloadDirectory')
        …
</pre>
<p>The default download directory can then be set by passing a string to the <strong>TextBox.Text</strong> property of the destination textbox at runtime. In this example, I have hardcoded the download default directory to be the Users Downloads Directory.</p>
<pre class="brush: python; title: ; notranslate">
        self.txtDownloadDirectory.Text =
        ... r'C:\Users\Username\Downloads'
</pre>
<p>When there is a valid url is in the source text box, pressing the "Download File" button launches a second dialog which indicates the progress of the background operation. The<strong> ProgressBar.Maximum</strong> is set to the size of the file, and the location of the <strong>ProgressBar</strong> represents the number of bytes transferred . As in <a href="http://robertsoakes.brinkster.net/blog/?p=75">Part 3</a> of this series, both the download job and the updates to the user interface proceed via a separate thread (managed with the BackgroundWorker Class). In this implementation, it is possible to interrupt the background thread and cancel the download by pressing the "Cancel" button.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/12/120108-2021-learningiro32.png" alt="" width="319" height="140" /></p>
<p style="text-align: center"><span style="font-size:9pt"><strong>Figure 2. Dialog Box which shows the download progress by using a BackgroundWorker.<br />
</strong></span></p>
<h3>Managing Downloads</h3>
<p>As described in <a href="http://robertsoakes.brinkster.net/blog/?p=141">Part 4</a>, the BITS service is controlled through the <strong>BitsManager</strong> class created when the main script (TestApp_20081126.py) is loaded (following the import statements).</p>
<div>
<pre class="brush: python; title: ; notranslate">
    import clr
    import os
    import system
    …
    clr.AddReferenceToFile('SharpBITS.Base.dll')
    import SharpBits.Base
    …
    app = Application()
    DownloadManager = SharpBits.Base.BitsManager()
</pre>
</div>
<div>When working with <strong>BitsManager</strong>, there are <a href="http://msdn.microsoft.com/en-us/library/aa362783(VS.85).aspx">a few details</a> which need to be kept in mind, though only one is important to the implementation here; BITS can only download a file to an existing folder. I, therefore, created a helper function called <strong>CheckDirectory</strong> that verifies that the destination directory exists.</div>
<pre class="brush: python; title: ; notranslate">
def CheckDirectory(FolderPath):
    FolderCheck = FolderPath
  �
    if os.path.exists(FolderCheck):    # 1
        print `Folder Path Exists'
    else:
        os.mkdir(FolderCheck)    # 2
</pre>
<p>The code is straightforward.  It makes use of the <strong>os.path.exists</strong> method to determine if the FolderPath is valid (#1). If not, it creates the folder (#2), using <a href="http://www.python.org/doc/2.5.2/lib/module-os.html"><strong>os</strong></a><strong>.mkdir</strong>(DirectoryName).</p>
<div>In addition to <strong>CheckDirectory</strong>, two other functions are used for managing the download and interacting with the UI.</div>
<pre class="brush: python; title: ; notranslate">
def DownloadFile(DownloadUrl, DestUrl):

    # Check if the download directory exists
    CheckDir = os.path.dirname(DestUrl)
    CheckDirectory(CheckDir)

    # Create the download job
    rssJob = DownloadManager.CreateJob(&quot;rssEnclosureDownload&quot;,
    ... SharpBits.Base.JobType.Download)    # 1
    rssJob.AddFile(DownloadUrl, DestUrl)        # 2
    rssJob.Priority = SharpBits.Base.JobPriority.ForeGround    # 3
    return rssJob        # 4
</pre>
<div>The first, <strong>DownloadFile</strong>, creates the download job (#1) and adds the specified file to the queue (#2). It then sets the <strong>BitsJob.Priority</strong> to foreground and returns the created <a href="http://msdn.microsoft.com/en-us/library/aa363132(VS.85).aspx"><strong>BitsJob</strong></a>. The second function, <strong>UpdateFileDialog</strong>, provides feedback to the <strong>ProgressDialog</strong> and runs on the thread created with the <strong>BackgroundWorker</strong>. As in <a href="http://robertsoakes.brinkster.net/blog/?p=75">Part 3</a>, the background thread can be canceled by using the <strong>BackgroundWorker.CancellationPending</strong> property.</div>
<pre class="brush: python; title: ; notranslate">
def UpdateFileDialog(sender, event, rssJob):
    worker = sender    # 1
    # Update the BackgroundWorker/UI of Download Progress
    while rssJob.State != SharpBits.Base.JobState.Transferred:    # 2
        worker.ReportProgress(rssJob.Progress.BytesTransferred)
        Thread.Sleep(150)
                if worker.CancellationPending:        # 3
            rssJob.Cancel()            # 4
            break                # 5
</pre>
<p><strong>UpdateFileDialog </strong>first creates an instance of the worker by referencing the function sender (#1). It then queries the state of the rssJob (#2). If the job reports its status as anything other than "Transferred," the worker then fires the <strong>BackgroundWorker.ReportsProgress </strong>and provides the total bytes transferred. If the <strong>BackgroundWorker.CancellationPending</strong> is true, then the function cancels the <strong>BitsJob </strong>and exits.</p>
<h3>Initiating the Download</h3>
<p>As in the case of the <a href="http://robertsoakes.brinkster.net/blog/?p=75">multithreaded hello world example</a>, the download is started by pressing the button on the main form.</p>
<pre class="brush: python; title: ; notranslate">
def btnDownloadFile_Click(self, sender, event):

    DownloadUrl = self.txtDownloadUrl.Text    # 1

    # Create the File and Destination Url
    FileName = os.path.basename(DownloadUrl)
    FileUrl = self.txtDownloadDirectory.Text + '\\' + FileName

    # Return the txtDownloadUrl TextBox to Blank
    self.txtDownloadUrl.Text = None

    # Create the Background Thread and Download Job
    ProgressWindow = ProgressDialog(app.Dispatcher)    # 2
    rssJob = DownloadFile(DownloadUrl, FileUrl)    # 3

    # Start the Download Job
    rssJob.Resume()        # 4

    # Begin Updating the ProgressDialog
    ProgressWindow.RunWorkerThread(updateFileDialog,�
    ... rssJob, 0)        # 5
</pre>
<p>First, the download source Url (DownloadUrl) is taken from the program's main form (#1) and the file destination url is created. If no valid url is present, the program will quit and return an error.</p>
<p>Next, the DownloadUrl TextBox is set to a null value. The <strong>BackgroundWorker</strong> and <strong>ProgressDialog</strong> are then created (#2). The <strong>BitsJob </strong>is created and started (#4). Finally, the ProgressWindow is opened and the BackgroundWorker is started by using the custom <strong>ProgressDialog.RunWorkerThread,</strong> which was discussed more in depth in <a href="http://www.oak-tree.us/blog/http:/robertsoakes.brinkster.net/blog/?p=75">Part 3</a>.</p>
<h2>The ProgressDialog Class</h2>
<p>As you might have already guessed, BITS is already multithreaded and handles thread to thread communication via the <strong>BitsJob</strong> and <strong>BitsManager </strong>interfaces. As a result, the <strong>BackgroundWorker</strong> launched with the <strong>ProgressDialog.RunWorkerThread</strong> does not directly handle the work of downloading the file. Instead, its primary function is to update the user interface. As a result, it works in very similar fashion to the <a href="http://robertsoakes.brinkster.net/blog/?p=75">CountTo100 example</a> previously described via the <strong>BackgroundWorker.DoWork</strong>, <strong>ProgressChanged</strong> and <strong>RunWorkerCompleted </strong>events.</p>
<p>The code block below shows the most important changes to the <strong>ProgressDialog</strong> class. These include a pointer to the BitsJob and a function which sets the <strong>ProgressBar.Maximum</strong> value. The <strong>BitsJob.Complete()</strong> function has also been added to the <strong>Worker_RunWorkerCompleted()</strong> event handler.<strong><br />
</strong></p>
<pre class="brush: python; title: ; notranslate">
class ProgressDialog(object):

    def __init__(self, ThreadDispatcher):
        …
        self.rssJob = None        # 1
        …

    def RunWorkerThread(self, workHandler, rssJob, argument):
        …
        self.WorkerCallback = workHandler        # 2
        self.rssJob = rssJob                # 3
        self.Worker.RunWorkerAsync(argument)
        …
    def Worker_DoWork(self, sender, event):
        …
        try:
        …
            self.WorkerCallback(sender, event, self.rssJob)    #4
            self.SetMaxValue()

        except:
            …

    def Worker_ProgressChanged(self, sender, event):
        DownloadProgress = event.ProgressPercentage
        self.DownloadProgressBar.Value = DownloadProgress

        if self.DownloadProgressBar.Maximum == 1:        # 5
            self.SetMaxValue()

        if DownloadProgress &gt; self.DownloadProgressBar.Maximum:
            self.SetMaxValue()
        …

   def Worker_RunWorkerCompleted(self, sender, event):
        …
        self.rssJob.Complete()        # 6
</pre>
<p>First, an empty reference called <strong>self.rssJob</strong> is created (#1). It will receive a pointer to the current <strong>BitsJob</strong> when the <strong>RunWorkerThread</strong> method is called (#3). In the <strong>Worker_ProgressChanged </strong>event, the thread checks the <strong>ProgressBar.Maximum </strong>value to ensure that it is correct (#5). This is done via the function, <strong>SetMaxValue()</strong>. After the download is reported complete, the background thread then runs the <strong>BitsJob.Complete()</strong> method to release the files to disk.</p>
<h2>Conclusion</h2>
<p>IronPython is an excellent language in which to glue the functions of multiple components together in an elegant manner. In this post, I looked at how to construct a GUI for the Windows BITS service. I was able to easily modify the BackgroundWorker class and create a custom dialog. Then, using the Worker_ProgressChanged event, it is possible to update the GUI without causing the entire program to lock while the download proceeds.</p>
<p>In the next article in this series, I will begin wrapping up work on the Download Manager. First, I will create a single window and list current downloads in a single list. After that, I will create a custom class that responds to the download state and allows for individual jobs to be paused and resumed.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-windows" rel="bookmark" title="May 12, 2009">Installation of PyQt on Windows</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2009/05/12/pyqt-mac" rel="bookmark" title="May 12, 2009">Installation of PyQt on Mac OS X</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
</ul>
<p><!-- Similar Posts took 20.592 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning IronPython – Part 4 – BITS and Pieces</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4#comments</comments>
		<pubDate>Mon, 01 Dec 2008 03:06:45 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://robertsoakes.brinkster.net/blog/?p=141</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+4+%E2%80%93+BITS+and+Pieces&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-11-30&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4&amp;rft.language=English"></span>
In the first three entries to this series, I have looked at the IronPython language; introduced the project which will help me learn Python and .Net frameworks; and wrote a multithreaded "Hello World" app. Seen in hindsight, these accomplishments seem small … but, for the first time in the last few months, I feel as [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4">Learning IronPython – Part 4 – BITS and Pieces</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+4+%E2%80%93+BITS+and+Pieces&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-11-30&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4&amp;rft.language=English"></span>
<p><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/11/120108-0306-learningiro11.png" alt="" align="left" />In the first three entries to this series, I have looked at the <a href="http://robertsoakes.brinkster.net/blog/?p=63">IronPython language</a>; introduced the <a href="http://robertsoakes.brinkster.net/blog/?p=71">project</a> which will help me learn Python and .Net frameworks; and wrote a <a href="http://robertsoakes.brinkster.net/blog/?p=75">multithreaded "Hello World"</a> app. Seen in hindsight, these accomplishments seem small … but, for the first time in the last few months, I feel as though I have a foundation. Things which were once unfathomably difficult have started to become possible. I have even come to appreciate the structure of the MSDN documentation, which is an utterly horrifying development! Given my somewhat slow progress, I am very happy to say that this little tutorial will show how to do something useful: download files!</p>
<p>In this and the next article in this series, I will continue to work on my multithreaded download manager for PodCatcher (my WPF based podcast aggregator). As a way of quick review, there are several things that I would like in this download manager. First, it should allow for multiple downloads at once, with each download on a separate thread. Second, the user should be able to pause and resume downloads. The interface should be straightforward and elegant, yet provide the user with a great number of details including download progress, file name, etc. After reviewing a number of programs, I decided to use the Firefox download manager as a model for the GUI and functionality. I intend to use the <a href="http://msdn.microsoft.com/en-us/library/aa362708(VS.85).aspx">Background Intelligent Transfer Service (BITS)</a>, available in Windows Vista and XP, as the download engine. This article will focus on the "guts", namely: Interfacing with BITS through an OpenSource C# Wrapper, called <a href="http://www.codeplex.com/sharpbits">SharpBITS</a>.<span id="more-141"></span></p>
<h2>Extending IronPython</h2>
<p>Before making the jump into SharpBITS and downloads, it's probably good to review some basic principles. First and foremost: IronPython and its deep integration with .Net. In <a href="http://robertsoakes.brinkster.net/blog/?p=63">Part 1</a> of this series, I dithered on a great deal about the integration between .Net and IronPython. Since then, I've learned a little more regarding the way in which this integration was obtained.</p>
<p>IronPython is written in C# as a full implementation of the Python language. As it is implemented in C# and built on the Microsoft <a href="http://msdn.microsoft.com/en-us/library/8bs2ecf4(VS.71).aspx">Common Language Runtime (CLR)</a>, the IronPython engine plugs into the existing .Net/Mono platforms seamlessly. .Net assemblies and classes can be used as native Python classes. Though code is still dependent on the IronPython .dll files, the CLR sees IronPython as a true .Net assembly. This doesn't just apply to the standard .Net classes shipped by Microsoft as part of the .Net framework. Any assembly written in C# and meant for use in the .Net framework can be easily imported and used. This is hugely convenient as a number of C# wrappers have been written for many important tools, including wrappers for the <a href="http://code.google.com/p/manageditk/">Insight Toolkit (ITK)</a>, which happens to be of particular interest to me as a researcher and scientist.</p>
<p>The .Net assemblies can be imported through the CLR module, the magical component which gives IronPython the ability to talk with other members of .Net. The CLR module is imported with the code:</p>
<p><span style="font-family: Courier New;">import clr<br />
</span></p>
<p>After the module has been imported, it is then possible to reference specific assembly files by using the <span style="font-family: Courier New;">clr.AddReference('AssemblyName')</span> or the <span style="font-family: Courier New;">clr.AddReferenceToFile('AssemblyName.dll')</span> commands.</p>
<h2>BITS and SharpBITS</h2>
<p>Now onto the more useful tidbits of this post. As I described in <a href="http://robertsoakes.brinkster.net/blog/?p=71">Part 2</a> of this series, I need a robust download engine. Thus, the use of BITS. It is available on all Windows installations without the need for a user to download additional dependencies. It enables a number of very robust features, which extend far beyond my needs. In short, instead of ask, "Why BITS?" it is much easier to ask, "Why not BITS?"</p>
<p>One of the greatest advantages of BITS is its ability to transfer large files asynchronously between a client and a server. The transfers can occur in the background or foreground. Further, BITS uses idle network bandwidth to transfer the files. The transfer, therefore, has zero effect on the overall user experience.</p>
<p>As implied, it also just so happens that there is a managed wrapper for BITS, called SharpBITS. More importantly, due to the strong relationship between IronPython and the CLR, SharpBITS can be used with zero modifications to the underlying code or without additional wrappers. As a C# wrapper around the BITS service (BITS is implemented in C++), SharpBITS is primarily a communication layer and does not add any important functionality of its own. It is important to note, however, that any module written in a .Net compatible language can be used right out of the box. To quote a much overused mantra: "It just works."</p>
<p>This is a slightly different experience from using a C Python module. C Python extensions are code written in C against the <a href="http://www.python.org/doc/2.5.2/ext/intro.html">Python API</a>. While Python "bindings" for a number of important toolkits are available (including <a href="http://www.riverbankcomputing.co.uk/software/pyqt/intro">Qt</a>, <a href="http://www.pygtk.org/">GTK</a>, and <a href="http://code.google.com/p/wrapitk/">ITK</a>; among others), these bindings function in the same way that SharpBITS wraps the BITS service. That is, they are a communication layer. While this is convenient, it also adds complexity to the overall program. The wrappers are additional layers of code that must be maintained outside. Custom code written in pure C# or Visual Basic, in contrast, does not need any "communication layer." IronPython's easy extensibility and close relationship to other .Net languages is one advantage over the C Python flavor.</p>
<p>Even so, communication layers can be quite useful. Using the SharpBITS wrapper, it is possible to interact with BITS from any application by adding a reference to the 'SharpBITS.Base.dll'. In an IronPython application, this is done with the following:</p>
<p><span style="font-family: Courier New;">import clr<br />
clr.AddReferenceToFile('SharpBITS.Base.dll')</span></p>
<p><span style="font-family: Courier New;">import SharpBits.Base as SharpBits<br />
</span></p>
<h3>The BITS Classes</h3>
<p>Instructions to the BITS service are passed through an interface called the <strong>BitsManager</strong> (a detailed introduction on how to use the SharpBITS wrapper is available <a href="http://www.codeproject.com/KB/IP/sharpBITS.aspx">here</a>), which only needs to be created once. Downloads and uploads proceed via a <a href="http://msdn.microsoft.com/en-us/library/aa363132(VS.85).aspx"><strong>BitsJob</strong></a><strong>. </strong>A <strong>BitsJob </strong>may be either an upload, or a download. If it is a download, a BitsJob may contain multiple files. However, an upload may contain only a single file. Nearly all interaction occurs directly with the BitsJob or the BitsManager. This includes enumerating current jobs, creating and canceling jobs, as well as querying a job for its progress.</p>
<p>When using BITS, there are some <a href="http://msdn.microsoft.com/en-us/library/aa362783(VS.85).aspx">other important things</a> to keep in mind. Here are a few nuggets I found particularly useful:</p>
<ol>
<li>A BITS job queue is specific to a single user or to the system. The active queue is changed by modifying the property <strong>DownloadManager.EnumJobs</strong>. In the example below, I will be creating a job for a single user and the <strong>EnumJobs</strong> property is set to <strong>SharpBits.JobOwner.CurrentUser</strong>.</li>
<li>Jobs are persistent. A single job will remain in the queue until you call <strong>BitsJob.Complete()</strong> or <strong>BitsJob.Cancel()</strong>. This initially caused me a great deal of confusion as a job would be complete, yet I would be unable to find the files.</li>
<li>A download job runs through the BITS service. It therefore continues even after the program has been exited. Even so, it still needs to be cleared or completed before the files are available for use.</li>
</ol>
<h3>Using SharpBITS – The Interactive Interpreter</h3>
<p>To get started with SharpBITS, a BitsManager needs to be created. After the BitsManager has been created, you can then create new or interact with existing jobs. A simple example from the command line with the ipy interpreter might look like this:</p>
<div><span style="font-family: Courier New;">import clr<br />
clr.AddReferenceToFile('SharpBITS.Base.dll')    <span style="color: #76923c;">#1<br />
</span>import SharpBits.Base as SharpBits    <span style="color: #76923c;">#2<br />
</span><span style="color: #76923c;"><br />
# Create the Download Manager and set JobOwner to CurrentUser</span><br />
downloadManager = SharpBits.BitsManager()    <span style="color: #76923c;">#3</span><br />
downloadManager.EnumJobs(SharpBits.JobOwner.CurrentUser)</span> </div>
<div><span style="font-family: Courier New;"><span style="color: #76923c;"># Add Files to the Download Job</span><br />
downloadJob = downloadManager.CreateJob("Description", SharpBits.JobType.Download)    <span style="color: #76923c;">#4</span><br />
downloadJob.AddFile(DownloadUrl, DestUrl)    <span style="color: #76923c;">#5</span><br />
downloadJob.Priority = SharpBits.JobPriority.ForeGround    <span style="color: #76923c;">#6<span style="font-family: Courier New;"><span style="color: #76923c;"> </span></span></span></span><span style="font-family: Courier New;"><span style="color: #76923c;"></span><span style="font-family: Courier New;">  </p>
<p></span> </p>
<p></span></div>
<p><span style="font-family: Courier New;"><span style="font-family: Courier New;"><span style="font-family: Courier New;"><span style="font-family: Courier New;"><span style="font-family: Courier New;">downloadJob.Resume()    <span style="color: #76923c;">#7</span></span></span></span></span></span></p>
<p>The code is fairly straightforward. First, a reference is added to the SharpBITS.Base.dll assembly (#1) and the modules are imported into the session (#2). Next, an instance of the <strong>BitsManager</strong> is created (#3) and the <strong>JobOwner</strong> is set to the current user. Then, a new <strong>BitsJob</strong> is created, called downloadJob (#4), and files are added to the queue (#5). The file can be downloaded from http, https, or over a network by using the http://, https:// or file:// tags respectively. The Destination Url (DestUrl) must be a valid file path on the existing computer. Files can only be downloaded to already existing folders. As a reminder, since this job is a download, it can contain any number of files. Upload jobs are limited to a single file.</p>
<p>After the files are added, the JobPriority is set. In this example, the files will be downloaded in the foreground. For files downloaded in the background, BITS will automatically throttle the download speed so that they do not interfere with other programs using the network connection. For downloads in the foreground, no such throttling occurs (#6).</p>
<p>Last, the job is started (#7). When first created, all download jobs begin <a href="http://msdn.microsoft.com/en-us/library/aa363132(VS.85).aspx">life</a> in suspension. Once they are started, the job can then be paused by using <strong>downloadJob.Suspend()</strong> or canceled by using <strong>downloadJob.Cancel()</strong>. As noted above, the files are released by using <strong>downloadJob.Complete()</strong>.</p>
<h2>Conclusion</h2>
<p><strong>BITS</strong> is a fantastic download engine which can be manipulated by using the SharpBITS C# wrapper. In the next article, I will look at how to start a download job on a separate thread as well as how to bring the various bits and pieces together into a semi-elegant whole. After all, while a command line downloader is useful, we want both the download to start and to see its progress.</p>
<p>_____________________________________________________</p>
<p>For additional details about the integration of C# and .Net, see Chapter 1 of <a href="http://www.manning.com/foord/">IronPython in Action</a> by Michael Foord, which is available for <a href="http://www.manning.com/foord/meap_foordch1.pdf">preview</a>.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 3 – A Beautiful Start</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 2 – A Simple Project</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials" rel="bookmark" title="December 11, 2008">IronPython – Windows Presentation Foundation Tutorials</a></li>
</ul>
<p><!-- Similar Posts took 30.444 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4">Learning IronPython – Part 4 – BITS and Pieces</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning IronPython – Part 3 – A Beautiful Start</title>
		<link>http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3</link>
		<comments>http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3#comments</comments>
		<pubDate>Thu, 20 Nov 2008 03:12:37 +0000</pubDate>
		<dc:creator>Rob Oakes</dc:creator>
				<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://robertsoakes.brinkster.net/blog/?p=75</guid>
		<description><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+3+%E2%80%93+A+Beautiful+Start&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-11-19&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3&amp;rft.language=English"></span>
After a great deal of chatter, we finally arrive at the meat of this series. We can start talking about code and some specific things that I have started to pick up. For those coming late to the party though, it might be good to briefly summarize what I've already blogged about. In Part 1 [...]<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3">Learning IronPython – Part 3 – A Beautiful Start</a></p>
]]></description>
			<content:encoded><![CDATA[	
	<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.title=Learning+IronPython+%E2%80%93+Part+3+%E2%80%93+A+Beautiful+Start&amp;rft.aulast=Oakes&amp;rft.aufirst=Rob&amp;rft.subject=IronPython&amp;rft.subject=Programming&amp;rft.source=Apolitically+Incorrect&amp;rft.date=2008-11-19&amp;rft.type=blogPost&amp;rft.format=text&amp;rft.identifier=http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3&amp;rft.language=English"></span>
<p>After a great deal of chatter, we finally arrive at the meat of this series. We can start talking about code and some specific things that I have started to pick up. For those coming late to the party though, it might be good to briefly summarize what I've already blogged about. In <a href="http://robertsoakes.brinkster.net/blog/?p=63">Part 1</a> of this series, I talked about my recent decision to begin learning IronPython and some benefits over other options. In <a href="http://robertsoakes.brinkster.net/blog/?p=71">Part 2</a>, I briefly introduced the project which I will be working on. This article (as well as the next two in this series) will focus on my efforts to develop a Podcast download manager using <a href="http://msdn.microsoft.com/en-us/netframework/aa663326.aspx">Windows Presentation Foundation (WPF)</a> and IronPython. For those following along, the source files for the article can be downloaded <a href="http://www.oak-tree.us/Tutorials/TestApp_20081106.zip">here</a>.<span id="more-75"></span></p>
<h2>Some Goals and the End Product</h2>
<p>While I describe my overall goals in <a href="http://robertsoakes.brinkster.net/blog/?p=71">Part 2</a>, I think it is good to begin with the end in mind. So, I have decided to start this post with a few design considerations.</p>
<p>It will be important that my podcast client (PodCatcher) be able to download multiple files at once. While the actual download will happen in the background and will be controlled by the <a href="http://msdn.microsoft.com/en-us/library/bb968799(VS.85).aspx">Background Intelligent Transfer Service (BITS)</a> that is built into Windows, I still want to be able to interact with the download streams. I should be able to pause, resume and cancel downloads at will. I also want to know how much of a given transfer has occurred. These design goals insert a level of complexity into my program from the outset. Namely, it is necessary to use a multithreaded design.</p>
<p>Multithreaded applications are able to take advantage of multiple cores in newer hardware. A given data process can be split up and run in multiple threads at the same time. This type of parallel processing is able to crunch more data in a shorter time frame. Alternatively, it can be used to do multiple jobs without tying up the user interface (which is what I intend). The operating system handles the dirty job of deciding who gets time on the processor while avoiding fights and other issues.</p>
<p>Though multithreaded programs offer many benefits, there are also some difficulties. For example, when multiple jobs are running at the same time, it can become very difficult to communicate from one thread to another. This poses a particular problem in the case of updating the Progress Bar. WPF uses one thread for the main GUI. For various reasons, only jobs started on the GUI thread are capable of updating the user interface. Taken at face value, it appears impossible to update the status of a Progress Bar (on the GUI thread) from the Download Thread. However, we don't need to take the scenario at face value. Much of the difficulty is circumvented by a particular class in the WPF Application framework called the Dispatcher. In this example, I will be using a class type that inherits from (and is able to communicate with the dispatcher). This class is called the <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx">BackGroundWorker</a>.</p>
<p>This article will focus on the creation of a simple dialog window with a WPF ProgressBar and cancel button. For the first step, I will not be using information from BITS to drive the progress bar. Instead, I will use a simple function called CountTo100 (whose job is self explanatory) to demonstrate the BackGroundWorker and communication with the GUI thread.</p>
<h2>Step 1: Creating Windows While Avoiding Walls</h2>
<p>Before getting to the heart, I think it might be helpful to start with a simple HelloWorld. After all, what programming experience is complete without HelloWorld? In this case, I can demonstrate how a simple piece of XAML code (the language behind WPF) can be loaded and turned into a Window. As I am far from creative, this example has been largely stolen from <a href="http://www.manning.com/foord/">IronPython in Action</a>. A similar example can also be found in the <a href="http://www.ironpython.info/index.php/WPF_GUI_using_XamlReader">IronPython Cookbook</a>. Briefly, we will be using the <a href="http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader.aspx">XamlReader</a> to load a simple window with a button and Window Title. After loading the window, the button.Click event is connected to a simple function. We will use this simple function to launch multiple instances of our ProgressDialog, each on a separate thread (which will be discussed below). Here is the relevant code:</p>
<p><span style="font-family: Courier;">import clr        <span style="color: #76923c;"># 1</span><br />
clr.AddReference('PresentationFramework')<br />
clr.AddReference('PresentationCore')<br />
from System.IO import File<br />
from System.Windows.Markup import XamlReader        <span style="color: #76923c;"># 2</span><br />
from System.Windows import Application, Windowclass TestApp(object):<br />
    def __init__(self):<br />
        xamlStream = File.OpenRead('HelloWorld.xaml')    <span style="color: #76923c;"># 3</span><br />
        self.Root = XamlReader.Load(xamlStream)<br />
        self.buttonHelloWorld = self.Root.FindName('buttonHelloWorld')<br />
        self.buttonHelloWorld.Click = += self.btnHello_Click    <span style="color: #76923c;"># 4</span></span></p>
<p>    def btnHello_Click(self, sender, event):            <span style="color: #76923c;"># 5</span><br />
        ProgDialog = ProgressDialog(app.Dispatcher)<br />
        ProgDialog.RunWorkerThread(0, CountTo100)</p>
<p><span style="font-family: Courier;">mainWin = TestApp()<br />
app.Run(mainWin.Root)</span></p>
<ol>
<li>Comment 1. This is the line of code which imports the Common Language Runtime.</li>
<li>Comment 2. The XamlRader is imported from System.Windows.Markup.</li>
<li>Comment 3. The Xaml code is read from a file called 'HelloWorld.xaml' and then loaded as a Window element in the TestApp.Root.</li>
<li>Comment 4. The buttonHelloWorld.Click Event is connected to the btnHello_Click Function. This function will be used to launch the ProgressDialog.</li>
<li>Comment 5. The btnHello_Click function.</li>
</ol>
<p>The code can be run as a script and is started with the command:</p>
<p>C:\ipy TestApp_20081106.py</p>
<p style="text-align: center"><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/11/112008-0312-learningiro1.png" alt="" /></p>
<p>A similar method is used to create the dialog box that contains the progress bar. The XAML for the form is kept in a file and then read in when it is necessary to make a new instance. Once the window is created and the various events connected, he progress bar is managed programmatically.</p>
<p style="text-align: center"><img src="http://robertsoakes.brinkster.net/blog/wp-content/uploads/2008/11/112008-0312-learningiro2.png" alt="" /></p>
<h2>Step 2: The BackGroundWorker</h2>
<h3>Launching the BackgroundWorker</h3>
<p>When the "Push Me!" button of the main window is pressed, it launches a smaller dialog box. The smaller dialog box is an instance of a special class called <strong>ProgressDialog</strong>. The <strong>ProgressDialog </strong>class contains a ProgressBar and a CancelButton, it also creates an instance of a BackGroundWorker. A reference to the application Dispatcher is included (#2) so that GUI events can be used outside of the Worker_ProgressChanged event handler. This is only done in case of an error or other issue.</p>
<p><span style="font-family: Courier;">def btnHello_Click(self, sender, event):<br />
        ProgDialog = ProgressDialog(app.Dispatcher) <span style="color: #76923c;"># 1<br />
<span style="color: #000000;">        ProgDialog.RunWorkerThread(0, CountTo100) # 2</span></span></span></p>
<p>The BackGroundWorker thread is launched with the <strong>RunWorkerThread</strong> method of the dialog box. This is a special implementation that has been added to allow the BackGroundWorker to be started easily and for methods from other classes to be passed to the <strong>ProgressDialog</strong>. You might notice two arguments in being passed to the ProgDialog.RunWorkerThread in this example. The first is the number from the method will begin counting, the second is a simple function called CountTo100 (that has been defined in the TestApp_20081106.py script). In the implementation here, ProgressDialog can be used to launch any function or process via the <strong>BackGroundWorker</strong>. Consider the function, CountTo100 for a moment:</p>
<p><span style="font-family: Courier;">def CountTo100(sender, event):<br />
    worker = sender            <span style="color: #76923c;"># 1</span><br />
    startValue = event.Argument    for i in range(100):<br />
        Thread.Sleep(30)        <span style="color: #76923c;"># 2</span><br />
        worker.ReportProgress(i)    <span style="color: #76923c;"># 3</span><br />
        if worker.CancellationPending:    <span style="color: #76923c;"># 4</span><br />
            break</span></p>
<p><span style="font-family: Courier;">    print 'Completed'</span></p>
<p>While this method is very simple, it contains several points of interest. First, it creates a reference to the worker object in the first line of code (#1). It then briefly pauses the thread on which it runs by invoking <strong>Thread.Sleep </strong>method (#2). Last, it communicates with the BackGroundWorker (and thus the GUI) via the <strong>BackgroundWorker.ReportProgress</strong> event (#3). Any sort of quantifiable process can be run and reported in this manner. The<strong> worker.CancellationPending</strong> event allows for the for loop to be broken. This occurs if the user clicks the Cancel button while the thread is running.</p>
<h3>How Does the BackGroundWorker Function?</h3>
<p>The <strong>BackGroundWorker Class</strong> creates a separate dedicated thread with specific events which allow for the progress of the operation to be communicated back to the main GUI thread. The most important events include the <strong><em>DoWork</em></strong> event, the <strong><em>ProgressChanged</em></strong> event (touched on briefly above) and the <strong><em>RunWorkerCompleted</em></strong> event.</p>
<p>The file ProgressDialog.py contains the. As in the case of TestApp, the window is initialized by loading a xaml string and various properties are set. After this, the background worker is created, as shown in the code block below.</p>
<p><span style="font-family: Courier;">import clr<br />
clr.AddReference('WindowsBase')<br />
from System.Threading import *<br />
from System.Windows.Threading import *<br />
from System.Windows.Controls import ProgressBar, Button<span style="font-family: Courier;">class ProgressDialog(object):<br />
    def __init__(self, ThreadDispatcher):<br />
        ...<br />
        self.Worker = BackgroundWorker()                <span style="color: #76923c;"># 1<br />
</span>        self.Worker.WorkerReportsProgress = True            <span style="color: #76923c;"># 2<br />
</span>        self.Worker.WorkerSupportsCancellation = True        <span style="color: #76923c;"># 3<br />
</span>        self.Worker.DoWork += self.Worker_DoWork<br />
        self.Worker.ProgressChanged += self.Worker_ProgressChanged<br />
        self.Worker.RunWorkerCompleted += self.Worker_RunWorkerCompleted<br />
        ...<span style="font-family: Courier;"><span style="font-family: Courier;">    def RunWorkerThread(self, argument, workHandler):        <span style="color: #76923c;"># 4</span><br />
        ...<br />
        self.uiCulture = Globalization.CultureInfo.CurrentUICulture<br />
        self.WorkerCallback = workHandler                <span style="color: #76923c;"># 5</span><br />
        self.Worker.RunWorkerAsync(argument)            <span style="color: #76923c;"># 6<br />
</span>        self.Root.Show()                            <span style="color: #76923c;"># 7</span></p>
<p></span></span></span><span style="font-family: Courier;"> </p>
<p></span></span></p>
<p> </p>
<p>Comment 1 shows where <strong>BackGroundWorker</strong> is created and its subsequent configuration so the <strong><em>ProgressChanged</em></strong> (#2) and <strong><em>WorkerSupportsCancellation </em></strong>(#3)<strong><br />
</strong>events are both enabled. The <strong>RunWorkerThread</strong> method is also shown (#4). This allows for an argument and method from another class to be passed to the BackGroundWorker. The custom method is stored as <strong>self.WorkerCallback</strong> (#5) and the <strong>BackGroundWorker</strong> is started (#6). Lastly, the ProgressDialog window is shown by the <strong>Window.Show()</strong> method (#7).</p>
<p>After the <strong>BackGroundWorker</strong> is started by using RunWorkerAsync, the <strong>Worker_DoWork</strong> event handler is fired.</p>
<p><span style="font-family: Courier;">    def Worker_DoWork(self, sender, event):<br />
        try:<br />
            Thread.CurrentThread.CurrentUICulture = self.uiCulture<br />
            self.WorkerCallback(sender, event)            # 1<br />
        except:<br />
            self.Dispatcher.BeginInvoke(DispatcherPriority.Normal,<br />
                self.CancelButton.SetValue(Button.IsEnabledPropery, False), None)<br />
            print 'Error'<br />
</span></p>
<p>The <strong>BackGroundWorker</strong> attempts to fire the stored method in <strong>self.WorkerCallback</strong>. If an error occurrs, a smaller Dispatcher command is invoked and the <strong>Worker_RunWorkerCompleted</strong> event handler is then fired which will close the window.</p>
<h2>Updating the Progress Bar</h2>
<p>The progress bar (and other updates to the GUI) are done via the <strong>Worker_ProgressChanged</strong> event handler:</p>
<p><span style="font-family: Courier;">    def Worker_ProgressChanged(self, sender, event):<br />
        Progress = event.ProgressPercentage * 0.01    <span style="color: #76923c;"># 1<br />
</span>        self.DownloadProgressBar.Value = Progres        <span style="color: #76923c;"># 2</span><br />
</span></p>
<p>In this simple example, the variable Progress (#1) corresponds to the to the counter (i) in the event loop of CountTo100 (see above). It is converted from an integer to a ratio and then it is set as the value in the ProgressBar. While this example is simple, it shows the power and flexibility of the <strong>BackgroundWorker</strong>.</p>
<h2>Conclusion</h2>
<p>In this article, three different IronPython techniques are discussed. The first gave an example of loading Xaml from a file and creating a window with the <strong>XamlReader </strong>object. The second showed an example of how a <strong>BackGroundWorker</strong> may be used to run a secondary process on a background thread. The third showed how information from the background thread could be communicated to the main GUI thread via the <strong>BackGroundWorker.ProgressChanged</strong> event. In short, the BackgroundWorker class offers an elegant solution to running an operation on a thread separate from that of the GUI.<br />
_____________________________________________________</p>
<p>In the next article in this series, we will look at how SharpBITS can be used to download a file with the BITS service.<br />
_____________________________________________________</p>
<h2>Acknowledgements, References and Further Reading</h2>
<p>While putting together this entry, I am indebted to the many C# and IronPython tutorials which describe threading in the .Net framework and how to implement them. The multithreaded code for this example was translated from <a href="http://www.hardcodet.net/2008/01/wpf-progress-dialog">this C# tutorial</a>, by Phillipp Sumi.</p>
<p>For additional reading about threading and background worker objects, I suggest that you check out the IronPython Cookbook. <a href="http://www.voidspace.org.uk/ironpython/threading.shtml">Here</a>, is a great introduction to threading. The background worker object is discussed in greater detail <a href="http://www.voidspace.org.uk/ironpython/winforms/part9.shtml">here</a>.<br />
<h3>Similar Posts:</h3>
<ul class="similar-posts">
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/30/ironpython-part4" rel="bookmark" title="November 30, 2008">Learning IronPython – Part 4 – BITS and Pieces</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/01/ironpython-part5" rel="bookmark" title="December 1, 2008">Learning IronPython – Part 5 – A Rudimentary Download Manager</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/11/ironpython-wpf-tutorials" rel="bookmark" title="December 11, 2008">IronPython – Windows Presentation Foundation Tutorials</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/12/07/ironpython-part6" rel="bookmark" title="December 7, 2008">Learning IronPython - Part 6 - From Rudimentary to Functional</a></li>
<li><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part2" rel="bookmark" title="November 19, 2008">Learning IronPython – Part 2 – A Simple Project</a></li>
</ul>
<p><!-- Similar Posts took 24.254 ms --></p>
<p>Copywrite 2009: Rob Oakes.  <a href="http://www.oak-tree.us/blog">Apolitically Incorrect</a><br/><br/><a href="http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3">Learning IronPython – Part 3 – A Beautiful Start</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.oak-tree.us/blog/index.php/2008/11/19/ironpython-part3/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

