<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>wxPython (wxForty-Two Blog)</title><link>https://wxpython.org/</link><description>wxForty-Two, a.k.a Robin's Ramblings</description><atom:link href="https://wxpython.org/blog.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2025 &lt;a href="mailto:robin@alldunn.com"&gt;The wxPython Team&lt;/a&gt; </copyright><lastBuildDate>Wed, 29 Oct 2025 14:07:52 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Hire a wxPython Pro!</title><link>https://wxpython.org/blog/hire-wxpython-pro/index.html</link><dc:creator>Robin</dc:creator><description>&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2&lt;/strong&gt;: In one of the great ironies of life, just a few day after I remembered to finally update this post to let you know that I'm working again, I found out that my job would be ending due to our tiny company being acquired by a mega-company. So I'm looking for full-time work yet again. Fun fun fun.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: Hi all, I am on the steady income train once again, however I am still interested in learning about opportunities that I may be well suited for. So send 'em if you've got 'em.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Hi all,&lt;/p&gt;
&lt;p&gt;Once again I find myself in between full-time employment, and so, once again, I'm informing the wxPython community about it in case anybody knows of opportunities that might be a good fit for me. I'm sure you all have a good idea of my qualifications, but if you need more details please contact me directly. I'm open to direct-hire, contract, or contract-to-hire opportunities. Preferably as a remote worker.&lt;/p&gt;
&lt;p&gt;Until the next full-time gig comes along, I'm also open to smaller, one-off wxPython-related jobs. Either some feature or fix within wxPython itself that you want to ensure shows up in a near-future release, or helping out with your own projects using wxPython.&lt;/p&gt;
&lt;p&gt;I can be contacted about possible opportunities either by email, or via a direct message at &lt;a class="reference external" href="https://discuss.wxpython.org/u/robin/summary"&gt;Discuss wxPython&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks! &lt;br&gt;
Robin&lt;/p&gt;</description><guid>https://wxpython.org/blog/hire-wxpython-pro/index.html</guid><pubDate>Tue, 24 Mar 2020 18:00:00 GMT</pubDate></item><item><title>Avoiding Window IDs</title><link>https://wxpython.org/blog/avoiding-window-ids/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;Due to some changes upstream in wxWidgets the &lt;code class="docutils literal"&gt;wxNewId&lt;/code&gt; function has been
deprecated. This deprecation first took effect in wxPython in the recent &lt;a class="reference external" href="https://wxpython.org/news/wxpython-4.0.2-release/index.html"&gt;4.0.2&lt;/a&gt; release, and has triggered some
discussions in the wxPython-users group about window IDs. This post will give a
little more context and background, and also list some examples and advice I
gave in wxPython-users so it can be more easily found than just being buried in
a message archive.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;h4&gt;Background&lt;/h4&gt;
&lt;p&gt;About 20 years ago wxWidgets was rearchitected to use event tables to dispatch
events to event handlers. Prior to this change, when events arrived in the
application they were handled by calling the C++ virtual method intended to handle
that kind of event. In other words, C++'s virtual method dispatch mechanism
handled it. This worked well, but it was very inflexible and cumbersome.
Switching to event tables simplified many things, increased the flexibility, and
made it easier to add new kinds of events to the library as needed without
redesigning base classes, etc.&lt;/p&gt;
&lt;p&gt;The items in the event tables consisted of an event type ID, the source widget
ID, a pointer to the member function to be called when the event arrives, and
some additional housekeeping items. Originally the tables were all constructed
at compile time and are a member of the class whose members are the event
handler methods. Since they are built at compile-time then these tables are
static (unchangeable) at runtime. A little later on dynamic event tables were
added and that allowed wxPython to be born, but even then it was a very long
time before it was common practice for wxWidgets C++ program to use dynamic
event tables to any great extent.&lt;/p&gt;
&lt;p&gt;Since the event tables were defined statically at compile time that meant that
the table items which needed window IDs to properly route the event would also
need to have the ID defined at compile time as well. That led to the common
practice for wxWidgets users to create a bunch of &lt;code class="docutils literal"&gt;ID_FOO&lt;/code&gt; constants and
manually managing their values and worrying about whether there were overlaps
between sets of IDs. This works fine, but can be cumbersome at times.&lt;/p&gt;
&lt;p&gt;In the early days of wxPython it quickly became obvious that following the same
C++ patterns was not a very fun way to work with the library. Once wxWidgets
adopted the practice that widgets would generate their own ID if &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;-1&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal"&gt;wxID_ANY&lt;/code&gt; was passed to the constructor then several Python-only enhancements
naturally fell into place as well, such as the &lt;code class="docutils literal"&gt;wx.PyEventBinder&lt;/code&gt; objects and
the &lt;code class="docutils literal"&gt;wx.EvtHandler.Bind&lt;/code&gt; method. I'll show some of the ways that wxPython can
be used without IDs in the next section.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;h4&gt;Writing ID-free wxPython&lt;/h4&gt;
&lt;p&gt;There are a few things that have been done to minimize the need to have
preallocated IDs in wxPython. In fact, back in the early days of this project
there were a number of advocates for eliminating, or at least hiding the ID
parameters throughout all of the wxPython API. The reasoning was that they
aren't really necessary in most cases, and the remaining cases could likely be
worked around easily. When you boil it all down to the nitty-gritty, the primary
purpose of window IDs is for identifying the source of events when searching for
matching handlers, but there are many cases where it simply doesn't matter.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Many consider it more pythonic to &lt;code class="docutils literal"&gt;Bind()&lt;/code&gt; an event handler directly to the
widget that produces the event, such as binding &lt;code class="docutils literal"&gt;EVT_BUTTON&lt;/code&gt; to the button
object itself. In this case, the button's ID does not matter since there can
only be one source of button events seen at that point in the hierarchy. So
the following works and no specific IDs need to be dealt with at all:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_SOMETHING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building on that concept a little more, if there is only ever one source of a
particular kind event in some containment hierarchy (up to the point of the
object the handler is bound to) then again, the ID of that source doesn't
matter, at least for the purpose of binding and finding event handlers for
that event type. And it definitely doesn't matter if the same ID is used in
another containment hierarchy because that other one will never be seen here.
Again, the specific ID of the widget is not needed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_SOMETHING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When there can be multiple sources of the same event type within a
containment hierarchy which need to be routed to different handlers then the
third parameter of &lt;code class="docutils literal"&gt;Bind()&lt;/code&gt; (named 'source') can be used to accomplish that,
and still there is no need to use and know specific ID values.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="n"&gt;objA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;objB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_SOMETHING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myAHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_SOMETHING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myBHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thanks to the magic of Python the source parameter of the &lt;code class="docutils literal"&gt;Bind()&lt;/code&gt; method can
take any kind of object which has a &lt;code class="docutils literal"&gt;GetId()&lt;/code&gt; method. That includes all
windows/widgets, menu and toolbar items (which are returned by the methods which
add the items to the menu or toolbar), timers, and so forth. If there is
anything that can be the source of an event that does not have a &lt;code class="docutils literal"&gt;GetId()&lt;/code&gt; method
then I would consider that to be a bug and it should be reported. Since it's
Python then it can also be non-UI objects that have a &lt;code class="docutils literal"&gt;GetId()&lt;/code&gt; method, if that
makes sense for the design of your application.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;amp;Foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Do some foo stuff"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_MENU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onDoFoo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you ever do need to know the ID of an item then you can just call it's
&lt;code class="docutils literal"&gt;GetId()&lt;/code&gt; instead of creating a preset constant.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID_ANY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;amp;Foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Do some foo stuff"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;toolbar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetId&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;"Foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fooBmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Do Some Foo stuff"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVT_MENU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onDoFoo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# works for both items&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One other common place where I've seen people wanting to use specific IDs is
in event handlers to differentiate behavior based on the source of the event.
For example:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;OnHandleButtons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ID_A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ID_B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doSomethingElse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However it's just as easy to compare the event's source object itself, and is
also a stronger way to dispatch based on source in the rare case where there
might be a duplicate ID conflict.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code python"&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;OnHandleButtons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetEventObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetEventObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doSomethingElse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On the other hand, it is also simple to bind a separate handler for each of
the cases above and that would also be a better OOP design.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This obviously doesn't cover all use cases now and forever, but it should show
that the need to use and reuse preset ID values is lower than some people may
think, and that the desire is that they should not be needed at all.&lt;/p&gt;</description><guid>https://wxpython.org/blog/avoiding-window-ids/index.html</guid><pubDate>Thu, 21 Jun 2018 03:25:52 GMT</pubDate></item><item><title>Linux Build Post Updated</title><link>https://wxpython.org/blog/2018-02-03-linux-build-info-updated/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;This is just a quick post to let everyone know that the previous post in this blog,
&lt;a href="https://wxpython.org/blog/2017-08-17-builds-for-linux-with-pip/index.html"&gt;Building wxPython for Linux via Pip&lt;/a&gt;
has been updated to include a simple set of build steps detailing how you can build your
own wxPython wheel on Linux or other Unix-like systems.&lt;/p&gt;</description><category>Build</category><category>Linux</category><guid>https://wxpython.org/blog/2018-02-03-linux-build-info-updated/index.html</guid><pubDate>Sat, 03 Feb 2018 22:06:40 GMT</pubDate></item><item><title>Building wxPython for Linux via Pip</title><link>https://wxpython.org/blog/2017-08-17-builds-for-linux-with-pip/index.html</link><dc:creator>Mesalu and Robin</dc:creator><description>&lt;p&gt;[ Post updated 2018-02-03, see new &lt;strong&gt;Build Steps&lt;/strong&gt; section below. ]&lt;/p&gt;
&lt;h4&gt;wxPython Wheels for Linux?&lt;/h4&gt;
&lt;p&gt;Before reading further, you may want to check and see if there are already
some wxPython wheels available for your flavor of Linux. A few are built as
part of the release process and are available from one of wxPython's
servers. More details and some links are on the 
&lt;a href="https://wxpython.org/pages/downloads/"&gt;download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If there are no existing wheels there for your distro, (or perhaps a close
relative,) then read on to find out why we can't just provide wheels for
all Linuxes, and what you need to build one for yourself.&lt;/p&gt;
&lt;h4&gt;The Problem&lt;/h4&gt;
&lt;p&gt;There have been some issues flowing into Phoenix's issue tracker since the
release of wxPython 4.0.0b1 related to installation issues on Linux using
pip, which have caused some overhead and soaked up unnecessary amounts of
time. So lets start with getting some of the basics out of the way. There
are a lot of flavors of linux. To name a few there's the Debian family,
Debian, Ubuntu, Kubuntu, Elementary, Mint, etc., Arch, Gentoo, RHEL and CentOS,
and so on. Each flavor has differences which can make binary distributions
incompatible across flavors.&lt;/p&gt;
&lt;p&gt;Why does this affect wxPython you may ask? It's just a Python package, and
Python source is independent across operating systems after all, right?.
Well, not all Python packages are just Python. wxPython as an example
contains binary extension modules (compiled C or C++ code that is platform
and architecture dependent.)  wxPython by default also contains a copy of
the compiled version of the wxWidgets library written in C++, which also
depends on other 3rd party libraries which need to not only be present at
runtime, but also have their development-related files present at
wxWidgets' and wxPython's compile time.&lt;/p&gt;
&lt;p&gt;Pip in its infinite wisdom can detect this, and knows how to select the
appropriate binary wheel for the following criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS (Windows, macOS, Linux)&lt;/li&gt;
&lt;li&gt;Architecture (i386, x86_64, etc)&lt;/li&gt;
&lt;li&gt;Python Version (2.7, 3.5, 3.6, etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See how pip doesn't care about the specific linux distribution? That's the
issue. The binary content and dependencies of wxPython can't be delivered
consistently via pip. There are some efforts to get around this (eg.  &lt;a href="https://www.python.org/dev/peps/pep-0513/"&gt;PEP
513&lt;/a&gt; a.k.a. &lt;code&gt;manylinux1&lt;/code&gt;) but
they don't quite work for wxPython yet. Packages that are able to fit into
the very narrow &lt;code&gt;manylinux1&lt;/code&gt; requirements can be hosted on PyPI and will
install with pip just as smoothly as pure-python packages do. Unfortunately
the &lt;code&gt;manylinux1&lt;/code&gt; spec does not include a version of GTK+ and its
dependencies that are new enough to be able to provide all the features
that wxWidgets requires.&lt;/p&gt;
&lt;h4&gt;The Fix&lt;/h4&gt;
&lt;p&gt;In order to deploy to linux systems wxPython4 (Phoenix) simply builds
itself from a source tarball as part of the pip setup process. All of the
code generated by wxPython's build system is already present in the
tarball, it merely needs to be compiled. This causes a very lengthy
installation times, but is a necessary evil. Because the build is just
that, a build, you will need all of wxWidgets and wxPython's binary
dependencies present at build time. wxWidgets' configure will be run, and
if it detects missing libraries the whole build, and therefore the pip
installation, will fail.&lt;/p&gt;
&lt;h4&gt;What You Need&lt;/h4&gt;
&lt;p&gt;You will need the following packages (please consult your distribution's
package list for the appropriate package names) and their dependencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;python-dev (for your version of python)&lt;/li&gt;
&lt;li&gt;gtk (preferably version 3, but depends on your needs)&lt;/li&gt;
&lt;li&gt;gstreamer &lt;/li&gt;
&lt;li&gt;gstreamer-plugins-base&lt;/li&gt;
&lt;li&gt;glut&lt;/li&gt;
&lt;li&gt;libwebkitgtk (matching your gtk version)&lt;/li&gt;
&lt;li&gt;libjpeg&lt;/li&gt;
&lt;li&gt;libpng&lt;/li&gt;
&lt;li&gt;libtiff&lt;/li&gt;
&lt;li&gt;libsdl&lt;/li&gt;
&lt;li&gt;libnotify&lt;/li&gt;
&lt;li&gt;libsm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;on Debian based systems, or other systems that separate development
packages from standard packages, you will need the corresponding &lt;code&gt;-dev&lt;/code&gt; or
&lt;code&gt;-devel&lt;/code&gt; package in addition to the standard package.&lt;/p&gt;
&lt;p&gt;Once the appropriate packages are present on your system then wxPython
should build with no problems, either with pip or from a source tree
extracted from the source tarball. If it still doesn't work for you then be
sure to look closely at the build log as there will likely be some clues
there that may point you in the right direction.  For example, this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OpenGL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;headers&lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;found&lt;/span&gt;
&lt;span class="nv"&gt;checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;GL&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;gl&lt;/span&gt;.&lt;span class="nv"&gt;h&lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;
&lt;span class="nv"&gt;configure&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;error&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;OpenGL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;libraries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;available&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;will tell you that the OpenGL libraries are missing. They are usually a
dependency of the glut or freeglut packages and should have been installed
along with that library, but perhaps your system's dependencies are
different and you'll need to do a little investigation to determine the
proper system packages that need to be installed.&lt;/p&gt;
&lt;h4&gt;Build Steps&lt;/h4&gt;
&lt;p&gt;Once you have installed the required depenency libraries, it should take
just a few steps to build a wxPython that will work on your system with
your Python. The steps shown here are just one option, but seems to be one
of the simpler approaches to take, and will require nothing extra to be
installed in your system Python. These instructions assume that you will be
using a 3.4+ version of Python and that the executable is called "python3".
If you are using 2.7 or the binary is called something else then adapt
accordingly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; The first thing we'll do is create and activate a new virtual
environment for the build and the initial testing. This is optional, but
highly recommended as it will ensure that there is nothing left over from a
previous build that could trip things up. The last two commands shown here
are just so you can verify that the python and pip commands are now being
found in the new virtual environment instead of from the system or other
Python environment.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;cd [some tmp folder]

python3 -m venv builder_py
source builder_py/bin/activate

which python
which pip
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Next, you'll want to update pip and add a few more packages.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;
&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;six&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wheel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;setuptools&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Use pip to download the latest source archive from PyPI.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wxPython&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Use pip to build a wxPython wheel file. We'll also redirect the
build output to a file so you can review it later if needed. This step will
take a while to complete, as it will be compiling all the wxWidgets and
wxPython source code, but you'll be able to watch the build output to
monitor the progress. Be sure to use the actual name of the downloaded
source archive file, which may be different than the one shown here.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pip wheel -v wxPython-4.0.1.tar.gz  2&amp;gt;&amp;amp;1 | tee build.log
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; If the build was successful then you should now have a wxPython
wheel file in the current working directory. If there was a problem then
review the &lt;code&gt;build.log&lt;/code&gt; file and see if you can spot any clues as to what
dependencies may be missing or out of date. (Build problems from wxPython
release sources are almost always due to missing dependencies.) Once you
think you have solved the problem go back to step 4 and try the build
again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; The next step is to install the wheel file in the virtual
environment and give it a quick test run. (Use the actual name of the wheel
file you built, which may be different than the one shown here.)&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;wxPython&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;4.0.1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cp35&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cp35m&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux_x86_64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;whl&lt;/span&gt;

&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="s2"&gt;"import wx; a=wx.App(); wx.Frame(None,title='hello world').Show(); a.MainLoop();"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see a new window open with a "hello world" title bar, which will
indicate that this build was successful and this wxPython wheel can be used
on your system. You can now use pip to install the wheel file in other
Python environments or virtual environments that use the same base Python
executable that you used for this build.&lt;/p&gt;
&lt;h4&gt;Known Issues&lt;/h4&gt;
&lt;p&gt;wxPython's build tools on Linux assume that the Python being used was configured
with the &lt;code&gt;--enable-shared&lt;/code&gt; flag. That is usually true for Pythons installed from
the Linux distro's repositories, as well as for most known 3rd Party Python
distributions for Linux. However, that flag is not enabled by default. So if
your Python is one that you've configured and built yourself, then double-check
that you used the flag. If it wasn't then you'll likely see a configuration
error when the build gets to the wxPython portion (after it has built
wxWidgets).&lt;/p&gt;
&lt;p&gt;Similarly, the &lt;strong&gt;&lt;a href="https://github.com/pyenv/pyenv"&gt;pyenv&lt;/a&gt;&lt;/strong&gt; does not use the
&lt;code&gt;--enable-shared&lt;/code&gt; flag when it builds a Python environment for you. 
There is a note in the 
&lt;a href="https://github.com/pyenv/pyenv/wiki#how-to-build-cpython-with---enable-shared"&gt;pyenv wiki&lt;/a&gt; 
that shows how to add the flag when it builds a new Python environment.&lt;/p&gt;
&lt;h4&gt;FAQ&lt;/h4&gt;
&lt;p&gt;Q1: "Why can't you just install the necessary packages as part of
wxPython's installation"&lt;/p&gt;
&lt;p&gt;A1: Lots of good reasons, among them are: Pip is NOT your linux package
manager, Phoenix is not responsible for maintaining your system.&lt;/p&gt;
&lt;p&gt;Q2: "I can install PyQt(4/5) just fine via pip! Why can't wxPython do the
same?"&lt;/p&gt;
&lt;p&gt;A2: Qt does not depend on system provided libraries other than the low-
level basic libs. wxWidgets does, it's one of the defining differences of
the two toolkits. As such PyQt can deliver to all linuxes in the same
manner.&lt;/p&gt;</description><category>Build</category><category>Linux</category><guid>https://wxpython.org/blog/2017-08-17-builds-for-linux-with-pip/index.html</guid><pubDate>Thu, 17 Aug 2017 19:14:19 GMT</pubDate></item><item><title>Fun with QtWebKit HTML5 Video</title><link>https://wxpython.org/blog/fun-with-qtwebkit-html5-video-2/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;See 
&lt;a href="http://blog.enthought.com/open-source/fun-with-qtwebkit-html5-video/"&gt;my post&lt;/a&gt;
at the &lt;a href="http://blog.enthought.com/"&gt;Enthought Blog&lt;/a&gt; about one of the
things I've been working on there.&lt;/p&gt;</description><category>General</category><guid>https://wxpython.org/blog/fun-with-qtwebkit-html5-video-2/index.html</guid><pubDate>Mon, 01 Apr 2013 14:43:00 GMT</pubDate></item><item><title>New Horizons</title><link>https://wxpython.org/blog/new-horizons/index.html</link><dc:creator>Robin</dc:creator><description>&lt;div&gt;&lt;p&gt;For the past few months I have been working for
&lt;a href="http://enthought.com"&gt;Enthought&lt;/a&gt; and helping out with a new upcoming
product. Since that is about to transition to a more long term
employment opportunity for me I figured it would be a good idea to let
the &lt;a href="http://wxPython.org"&gt;wxPython&lt;/a&gt; community know about it, and also to
let you know about some aspects of the job that some may find a little
surprising, before you hear about it as rumors or gossip.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://wxpython.org/blog/new-horizons/index.html"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Life</category><category>Software</category><category>Work</category><guid>https://wxpython.org/blog/new-horizons/index.html</guid><pubDate>Wed, 27 Mar 2013 16:12:00 GMT</pubDate></item><item><title>We'll miss you Neil</title><link>https://wxpython.org/blog/well-miss-you-neil/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;&lt;img alt="Neil Armstrong" src="https://wxpython.org/images/2012/08/neil_armstrong.jpeg" title="Neil Armstrong"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Neil Armstrong&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We'll miss you Neil.  Breathe free.  Fly high.&lt;/p&gt;</description><category>Life</category><guid>https://wxpython.org/blog/well-miss-you-neil/index.html</guid><pubDate>Mon, 27 Aug 2012 10:51:00 GMT</pubDate></item><item><title>It's Alive!</title><link>https://wxpython.org/blog/its-alive/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;Watch as the Phoenix spreads her wings over Python 3:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wxpython.org/Phoenix/ItsAlive/"&gt;http://wxpython.org/Phoenix/ItsAlive/&lt;/a&gt;&lt;/p&gt;</description><category>General</category><guid>https://wxpython.org/blog/its-alive/index.html</guid><pubDate>Thu, 24 May 2012 09:52:00 GMT</pubDate></item><item><title>Need any wxWidgets or wxPython Help?</title><link>https://wxpython.org/blog/need-any-wxwidgets-or-wxpython-help/index.html</link><dc:creator>Robin</dc:creator><description>&lt;p&gt;My current long-term consulting project will be coming to an end soon,
so I am currently looking for some short-term paying projects to fill in
while I'm looking for my next long-term gig.  Anything ranging from a
few days to several weeks worth of work would be fine. So if you would
like some help with your wx-related projects, would like to have
specific bugs fixed or new features added to
&lt;a href="http://wxWidgets.org"&gt;wxWidgets&lt;/a&gt; or &lt;a href="http://wxPython.org"&gt;wxPython&lt;/a&gt;, or
would like to sponsor some of my work on
&lt;a href="http://wiki.wxpython.org/ProjectPhoenix"&gt;Phoenix&lt;/a&gt;, then please send me
an email and we can discuss the details.&lt;/p&gt;
&lt;p&gt;Of course if you have or know of a long-term position available that
would fit my skill set then please let me know about that as well.&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;</description><category>General</category><guid>https://wxpython.org/blog/need-any-wxwidgets-or-wxpython-help/index.html</guid><pubDate>Tue, 13 Mar 2012 15:02:00 GMT</pubDate></item><item><title>OS X Lion Was My Idea</title><link>https://wxpython.org/blog/os-x-lion-was-my-idea/index.html</link><dc:creator>Robin</dc:creator><description>&lt;div&gt;&lt;p&gt;Several months ago Microsoft had an ad campaign where they would have an
average Joe or Jane talk about some cool wizbang feature of Windows 7
and how it was all their idea.  It was one of Microsoft's better ad
campaigns, and was actually understandable by the average person without
requiring the viewer to know industry inside jokes, or to understand
Jerry Seinfeld, to be able to "get" the gist of the commercial.  It also
employed some cute gimmicks, such as when the person was remembering
back to how they thought up the wonderful new idea the directors used a
different actor who was younger, thinner, cuter, handsomer, and had way
better hair than the real person.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://wxpython.org/blog/os-x-lion-was-my-idea/index.html"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Life</category><category>Mac</category><category>Software</category><guid>https://wxpython.org/blog/os-x-lion-was-my-idea/index.html</guid><pubDate>Fri, 10 Feb 2012 16:35:00 GMT</pubDate></item></channel></rss>