myWin_TkAgg.py 7.45 KB
Newer Older
1
2
3
4
5
6
7
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
#   myplotlib v1.0.1,
#
8
#   @file      myWin_TkAgg.py
9
10
11
#   @author    Yori 'AGy' Fournier
#   @licence   CC-BY-SA
#
12
13
14
#   MyWin_TkAgg class: Overlay of matplotlib FigureManagerTkAgg
#   class. It allows a cleaner and more confortable usage of windows
#   with the TkAgg Backend.
15
#
16
#   @Class MyWin_TkAgg
17
18
19
#
#   @Constructor
#
20
21
22
23
24
25
#                fig:           the MyFig object that need to be drawn
#                show:          a flag to show the window just after
#                               creation. (default: True)
#                fignum:        number of both the Window and the Figure.
#                debug:         flag for debugging, more verbatile.
#                (kw)args:      user defined arguments and keywords.
26
27
28
#
#   @section Functions
#
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#            - _boundFigure_:   bound a figure to the window (priv.)
#
#            - _unboundFigure_: unbound a figure to the window (priv.)
#
#            - set_figure:      a clean way of setting a new figure
#                               to the window.
#
#            - refresh:         redraw the window
#                               - clean the figure
#                               - plot the figure
#                               - draw the canvas
#
#            - drawFigure:      draw a given figure on the window
#                               - set the figure of needed
#                               - refresh
#
#            - close:           close the window
#
47
48
#   @section History
#
49
#   v 1.0.1 - MyWin_TkAgg class for the myplotlib module.
50
51
52
53
#
# ======================================================================
#
# IMPORT ---------------------------------------------------------------
54
55
56
57
from . import INFO, SEVR, WARN, DBUG, SPCE
from . import rcParams
from . import _G_WINDOWS
from . import np
58

59
60
# For the backend
from matplotlib.backends.backend_tkagg import FigureManagerTkAgg, FigureCanvasTkAgg
61
62
63
64
65
66
67
68
69

# Test mpl version:
from matplotlib import __version__ as mplvers
if int(mplvers.replace('.','')) < 150 :
    import six
    from six.moves import tkinter as Tk
else :
    from matplotlib.externals import six
    from matplotlib.externals.six.moves import tkinter as Tk
70
71


72
# Class MyWin Overwriting the disgusting Matplotlib.FigureManager class
73
74
class MyWin_TkAgg(FigureManagerTkAgg):
    
75
    # CONSTRUCTOR ------------------------------------------------------
76
77
    def __init__(self, fig, show=True, *args, **kwargs):
        
78
        # set the dpi to 75 (correct value for screen)
79
80
81
        if(fig.dpi != 75.):
            fig.dpi = 75.
        
82
83
84
        # Get the debug value
        debug = kwargs.get('debug', False)
        
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
        # Get the user specified ID of the window or set it to 0
        if 'fignum' in kwargs.keys():
            num = kwargs['fignum']
            fignumSpecifiedByUser = True
        else:
            num = 0
            fignumSpecifiedByUser = False
        
        # if ID already used
        if(num in [(window.num) for window in _G_WINDOWS]):
            
            # if user specified fignum then close former window and create new one
            if(fignumSpecifiedByUser):
                if(debug):
                    print(DBUG + "The fignum you specified already exists, I'll close the former window")
                # Close the window with the specified number
                _G_WINDOWS[np.where([(window.num == num) for window in _G_WINDOWS])[0][0]].close()
            else:
                # If user didn't specified a fignum
                # increase ID until found a free one
                while(num in [(window.num) for window in _G_WINDOWS]):
                    num = num + 1
107
        
108
109
110
111
        # If debug print the ID of the window
        if(debug):
            print(DBUG + "You choosed num = " + str(num))
        
112
113
        # before creating anything verify that the fig is not already
        # bounded to another window
114
        if fig.boundedToWin:
115
            # if it is the case close the bounded window.
116
            win = _G_WINDOWS[np.where([(window.num == fig.keywords['fignum']) for window in _G_WINDOWS])[0][0]]
117
118
            win.close()
        
119
        # Call FigureManagerTkAgg class
120
        # (already wondering if this is not a mistake...)
121
122
123
124
125
126
127
128
129
130
131
132
133
        if(debug):
            print(INFO + "Used TkAgg backend")
        
        # Create the master app
        window = Tk.Tk()
        window.withdraw()
        
        # create the canvas
        canvas = FigureCanvasTkAgg(fig, master=window)
        
        # create the Figure manager (what we call window)
        FigureManagerTkAgg.__init__(self, canvas, num, window)
        
134
        # bound the figure to the window
135
136
137
        self.canvas.figure.boundedToWin = True
        self.canvas.figure.keywords['fignum'] = num
        
138
139
140
        # add the window in the global variable _G_WINDOWS
        # this guarenty that you never loose a window
        # (see myTool.py getWindow(num))
141
        _G_WINDOWS.append(self)
142
143
        
        # if show is on, then show the window
144
        if show:
145
146
            self.refresh()
            self.show()
147
    
148
149
    
    # BOUND ------------------------------------------------------------
150
151
152
153
154
155
156
    def _boundFigure_(self, fig):
        
        fig.canvas = self.canvas
        self.canvas.figure = fig
        self.canvas.figure.boundedToWin = True
        self.canvas.figure.keywords['fignum'] = self.num
    
157
158
    
    # UNBOUND ----------------------------------------------------------
159
160
161
162
163
    def _unboundFigure_(self):
        
        self.canvas.figure.boundedToWin = False
        self.canvas.figure.keywords['fignum'] = -1
    
164
165
166
    
    # SETTERS ----------------------------------------------------------
    # SET FIGURE -------------------------------------------------------
167
168
    def set_figure(self, fig):
        
169
        # first unbound the former figure
170
171
        self._unboundFigure_()
        
172
173
        # if the new figure is already bounded close
        # its former container.
174
        if fig.boundedToWin:
175
            win = _G_WINDOWS[np.where([(window.num == fig.keywords['fignum']) for window in _G_WINDOWS])[0][0]]
176
            win.close()
177
178
        
        # bound the new figure
179
180
        self._boundFigure_(fig)
    
181
182
    
    # REFRESH ----------------------------------------------------------
183
    def refresh(self):
184
        
185
186
        # in the case the figure got another canvas
        # rebound the figure. This situation should not happend!!
187
        if self.canvas != self.canvas.figure.canvas:
188
            print(WARN + "Something weird happend, the canvas of the figure have been changed")
189
190
191
            self.set_figure(self.canvas.figure)
        
        # refresh
192
193
        self.canvas.figure.plot()
        self.canvas.draw()
194
195
        
        return(True)
196
    
197
198
    
    # DRAW -------------------------------------------------------------
199
    def drawFigure(self, fig):
200
201
        
        # if the figure is not the current one
202
        if(fig.keywords['fignum'] != self.num):
203
            # cleanly set the new figure
204
205
            self.set_figure(fig)
        
206
        # and refresh
207
208
        self.refresh()
    
209
210
    
    # CLOSE ------------------------------------------------------------
211
212
213
214
    def close(self):
        
        self._unboundFigure_()
        self.destroy()
215
        del _G_WINDOWS[np.where([(window == self) for window in _G_WINDOWS])[0][0]]
216
217
218
219
220
        # remark if you create the window like:
        # win = MyWin(fig)
        # then win is still refering the self
        # and therefore not yet freed
        # del win would free it entirely.