GUI icon in Tkinter #897

Merged
merged 6 commits into from Aug 1, 2012

Projects

None yet

4 participants

@pelson
Member
pelson commented May 24, 2012

I have implemented the matplotlib icon for the Tkinter backend (so that I can differentiate it from other Tk based tools easily).

I also tried implementing the icon in wx unsuccessfully, but have left my attempt in the hope of finding a wxPython wizz who can fix it. (I will put some in-line comments in the review changes)

Having looked over the Gtk backend's icon code I also made a couple of simplifications.

Finally, before looking at the backends who have already implemented icons I didn't realise there was already a matplotlib icon, therefore I produced one based on the documentation logo. FYI you can find the icon in an earlier commit but I do not propose using it (hence I have removed it from this pull) as when scaled down to 16x16 or 32x32 it starts to look like a cd burning icon.

@pelson pelson commented on the diff May 24, 2012
lib/matplotlib/backends/backend_wx.py
@@ -1592,7 +1599,6 @@ def destroy(self, *args):
DEBUG_MSG("destroy()", 1, self)
self.frame.Destroy()
#if self.tb is not None: self.tb.Destroy()
- import wx
@pelson
pelson May 24, 2012 Member

Already imported on line 67.

@pelson pelson commented on the diff May 24, 2012
lib/matplotlib/backends/backend_wx.py
@@ -1955,11 +1961,6 @@ def set_history_buttons(self):
class NavigationToolbarWx(wx.ToolBar):
def __init__(self, canvas, can_kill=False):
- """
- figure is the Figure instance that the toolboar controls
-
- win, if not None, is the wxWindow the Figure is embedded in
- """
@pelson
pelson May 24, 2012 Member

Looks like it was for an older interface or was a copy&paste error as it doesn't apply to this class.

@WeatherGod WeatherGod commented on an outdated diff May 24, 2012
lib/matplotlib/backends/backend_gtk3.py
- self.window.set_icon_from_file(window_icon)
- except:
- # some versions of gtk throw a glib.GError but not
- # all, so I am not sure how to catch it. I am unhappy
- # diong a blanket catch here, but an not sure what a
- # better way is - JDH
- verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
+ try:
+ self.window.set_icon_from_file(window_icon)
+ except (SystemExit, KeyboardInterrupt):
+ # re-raise exit type Exceptions
+ raise
+ except:
+ # some versions of gtk throw a glib.GError but not
+ # all, so I am not sure how to catch it. I am unhappy
+ # doing a blanket catch here, but an not sure what a
@WeatherGod
WeatherGod May 24, 2012 Member

"an" --> "am"

@WeatherGod WeatherGod commented on the diff May 24, 2012
lib/matplotlib/backends/backend_gtk3.py
@@ -1048,17 +1050,14 @@ def on_dialog_lineprops_okbutton_clicked(self, button):
def on_dialog_lineprops_cancelbutton_clicked(self, button):
self.dlg.hide()
-# set icon used when windows are minimized
-try:
@WeatherGod
WeatherGod May 24, 2012 Member

why remove this exception handling? At the very least we could use the verbose.report() there to provide us information and then re-raise (or maybe add a message to the exception and let it bubble up?)

@pelson
pelson May 24, 2012 Member

The comment needs removing, as far as I can see, this try block will never fail.

@mdboom
mdboom May 24, 2012 Member

I actually agree that this exception handling is unnecessary -- it really shouldn't fail here, unless something is seriously wrong. This is different from the try/excepts above where if the icon can't be set we should continue along without an icon.

@mdboom mdboom commented on the diff May 24, 2012
lib/matplotlib/backends/backend_tkagg.py
@@ -78,6 +78,16 @@ def new_figure_manager(num, *args, **kwargs):
FigureClass = kwargs.pop('FigureClass', Figure)
figure = FigureClass(*args, **kwargs)
window = Tk.Tk()
+
+ if Tk.TkVersion >= 8.5:
+ # put a mpl icon on the window rather than the default tk icon. Tkinter
+ # doesn't allow colour icons on linux systems, but tk >=8.5 has a iconphoto
+ # command which we call directly. Source:
+ # http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html
+ icon_fname = os.path.join(rcParams['datapath'], 'images', 'matplotlib.gif')
@mdboom
mdboom May 24, 2012 Member

It looks like matplotlib.gif didn't get committed. I tried changing this to .png -- it appears that Tkinter doesn't support png, so we'll need to include a gif version of the regular matplotlib icon.

@mdboom
Member
mdboom commented May 24, 2012

Where has this been tested? We should have someone (even if not yourself) test this for Tk, Gtk, Gtk3 and Wx under Linux, Windows and OS-X.

@pelson
Member
pelson commented May 24, 2012

Test matrix (I will update with people once they can confirm working):

OSTkinterGtkGtk3Wx
Linux (Ubuntu 12.04)pelson & mdboommdboommdboompelson & mdboom
Windows
OS-Xjkseppanjkseppanjkseppan (with a warning)jkseppan

Test process:

import matplotlib
# set the appropriate backend for your test
matplotlib.use('TkAgg')
matplotlib.use('GTKAgg')
matplotlib.use('GTK3Agg')
matplotlib.use('WXAgg')

import matplotlib.pyplot as plt
plt.plot(range(10))
plt.show()

Check the icon displays in the toolbar & in the title bar.

@mdboom
Member
mdboom commented May 24, 2012

Thanks. The .gif file is still not getting installed. You need to add a line for mpl-data/images/*.gif to the package_data list in setup.py.

@mdboom
Member
mdboom commented May 24, 2012

Tested (successfully) all backends on Linux.

@jkseppan
Member
jkseppan commented Jun 9, 2012

On OS X, under ipython, with TkAgg, I get

TclError: can't use "pyimage1" as iconphoto: not a photo image

from the line

---> 89         window.tk.call('wm', 'iconphoto', window._w, icon_img)

In pdb it does look like icon_img is a PhotoImage:

ipdb> window.tk
<tkapp object at 0x103ff1370>
ipdb> window._w
'.'
ipdb> icon_img
<Tkinter.PhotoImage instance at 0x103ff4e60>
@pelson
Member
pelson commented Jun 20, 2012

Thanks @jkseppan. I've put a try except around that line to catch the failure on some OSes.
By the way, which backends were you able to test on?

@jkseppan
Member

OS X 10.6.8, Python 2.7.3 via MacPorts:

TkAgg: crashes (probably unrelated to this change)
GtkAgg: shows the X11 logo as the icon
Gtk3Agg: couldn't install pygobject
Qt4Agg: shows a yellow sine wave as the title bar icon, a box with "exec" when you press Cmd+Tab and in the dock (this is usual when you run a binary that opens a window but is not a proper application)

@jkseppan
Member
jkseppan commented Jul 2, 2012

Trying again, OS X 10.6.8, Python 2.7.3 via Homebrew:

GtkAgg: shows the X11 logo in the window title bar

backend GTKAgg version 2.24.0
Could not load matplotlib icon: Couldn't recognize the image file format for file '/opt/homebrew/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib-1.2.x-py2.7-macosx-10.6-x86_64.egg/matplotlib/mpl-data/images/matplotlib.svg'

OSX, TkAgg, WxAgg: nothing in the title bar

Qt4Agg: sine wave in the title bar

The icon shown in the Dock and when you press Cmd-Tab is the Python starship icon, except with GtkAgg it's the X11 icon (which is what OS X always shows for X11.app).

Actually I'm not sure if title bar icons are the right thing on OS X. Apple's user interface guidelines says title bars can have what they call a proxy icon "after the user has given a document a name and save location for the first time", and users can drag-and-drop the icon to e.g. attach the document in an email, or cmd-click the icon to navigate the file system hierarchy up from the save location. I don't think a matplotlib plot window is a document like that - it's an interactive view into the object, and you can save a png or pdf representation of the plot, but you can't save the program state that corresponds to what's visible in the window.

One thing that would be nice is a matplotlib icon for the Dock and Cmd-Tab, but I think that's a different task altogether.

@pelson
Member
pelson commented Jul 5, 2012

Thanks @jkseppan. I didn't get that warning for GtkAgg backend (gtk 2.24 installed via homebrew on osx 10.7).

Out of interest, did you get Gtk3 and wx from homebrew? I haven't been as successful with those dependencies.

Other than perhaps addressing the warning (which I am unable to reproduce), I don't see any blockers on this, any objections?

@jkseppan
Member
jkseppan commented Jul 6, 2012

Sorry, I didn't mean that Gtk3 prints a warning - I meant that I couldn't install Gtk3Agg at all, because I can't find a way to install pygobject via homebrew (or MacPorts). I found someone's homebrew branch with an attempt, but it had diverged so far from mainstream homebrew that I feared it would break my Gtk3 installation. There's some information about the problems at https://trac.macports.org/ticket/33877 (basically you have to build various dependencies with --enable-introspection, but both MacPorts and Homebrew use --disable-introspection on everything, because introspection breaks something else).

I installed wxpython via brew install wxmac --python --devel and it seems to work fine.

@pelson
Member
pelson commented Jul 28, 2012

@jkseppan: It appears you are the only one who has seen any issues with this, is there any action that needs to be done? or are we at a stage where you would be happy to merge?

@jkseppan
Member

I'm happy with merging this. It just doesn't show the icon on my system with GtkAgg, but it's no worse than before.

@pelson
Member
pelson commented Jul 29, 2012

@jkseppan I've rebased. Would you mind doing the merge?

@WeatherGod
Member

Merging...

@WeatherGod WeatherGod merged commit 2ded37a into matplotlib:master Aug 1, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment