1""" 2I needed a simple gauge, so I've made on with Pmw. 3It might be useful for others to use as a base to develop more comples 4gauges with. 5 6Is it worth cleaning up and submitting? 7 8cheers and thanks 9 10chris 11 12Dr. Chris Wright 13Intensive Care Unit 14Monash Medical Centre 15Clayton. VIC Australia 16""" 17 18import sys 19import Tkinter 20import Pmw 21import time 22 23 24if sys.platform == 'win32': 25 # MS-Windows specific fonts 26 label_font = "-family Ariel -size 12" 27 value_font = "-family Ariel -size 12" 28 small_font = "-family {MS Sans Serif} -size 9 -weight bold" 29 header_font = "-family {MS Sans Serif} -weight bold" 30else: 31 # X-Windows specific fonts 32 label_font = "-*-helvetica-*-r-*-*-*-160-*-*-*-*-*-*" 33 value_font = "-*-courier-*-r-*-*-*-160-*-*-*-*-*-*" 34 small_font = "-*-helvetica-*-r-*-*-*-130-*-*-*-*-*-*" 35 header_font = "-*-helvetica-bold-r-*-*-*-150-*-*-*-*-*-*" 36 37class VerticalGauge(Pmw.MegaWidget): 38 """Vertical gauge with actual and desired settings""" 39 40 def __init__(self, parent = None, **kw): 41 optiondefs = ( 42 ('min', 0, None), 43 ('max', 100, None), 44 ('majortickinterval', 10, None), 45 ('minortickinterval', 5, None), 46 ('units', '', None), 47 ('bg', 'grey', self._backgroundSet), 48 ('actualvalue', 50, self._actualSet), 49 ('desiredvalue', 50, self._desiredSet), 50 ('actualcolour', 'yellow1', None), 51 ('desiredcolour', 'turquoise1', None), 52 ('label', 'Label', None), 53 ) 54 self.defineoptions(kw, optiondefs) 55 Pmw.MegaWidget.__init__(self, parent) 56 57 interior = self.interior() 58 interior.grid_rowconfigure(1, weight = 1) 59 for r in range(3): 60 interior.grid_columnconfigure(r, weight = 1) 61 62 self.actuallabel = self.createcomponent('actualLabel', 63 (), None, 64 Tkinter.Label, (interior,), 65 text = '', 66 width = 3, 67 relief = 'sunken', 68 bd = 1, 69 fg = self['actualcolour'], 70 font = value_font) 71 self.actuallabel.grid(sticky = "nswe", row = 0, column = 0) 72 73 self.label = self.createcomponent('label', 74 (), None, 75 Tkinter.Label, (interior,), 76 text = self['label'], 77 relief = 'raised', 78 font = label_font, 79 fg = 'navy', 80 bd = 2) 81 self.label.grid(sticky = "nsew", row = 0, column = 1) 82 83 self.desiredlabel = self.createcomponent('desiredLabel', 84 (), None, 85 Tkinter.Label, (interior,), 86 text = '', 87 width = 3, 88 relief = 'sunken', 89 bd = 1, 90 fg = self['desiredcolour'], 91 font = value_font) 92 self.desiredlabel.grid(sticky = "nswe", row = 0, column = 2) 93 94 self.canvas = self.createcomponent('canvas', 95 (), None, 96 Tkinter.Canvas, (interior,), 97 width = 100, 98 height = 300, 99 bg = 'grey') 100 101 self.canvas.grid(sticky = "nsew", columnspan = 3, pady = 1) 102 self.canvas.bind("<Configure>", self._createGaugeAxes) 103 104 self._createGaugeAxes() 105 106 self.initialiseoptions() 107 108 def _createGaugeAxes(self, event = None): 109 min = self['min'] 110 max = self['max'] 111 units = self['units'] 112 majortickinterval = self['majortickinterval'] 113 114 gauge_range = max - min 115 116 c = self.canvas 117 c.delete("all") 118 if event: 119 h, w = event.height, event.width 120 else: 121 h = int(c.configure("height")[4]) 122 w = int(c.configure("width")[4]) 123 124 self.lower = h - 15 125 self.upper = 15 126 self.middle = w / 2 127 c.create_line(self.middle, self.lower, self.middle, self.upper) 128 129 majortickcount = int((max - min) / majortickinterval) 130 self.axislength = self.lower - self.upper 131 self.majortickdistance = float(self.axislength) / majortickcount 132 self.majortickwidth = w / 5 133 labeloffset = (w / 4) + 10 134 135 for i in range(majortickcount + 1): 136 v = min + i * majortickinterval 137 d = self.lower - i * self.majortickdistance 138 c.create_line(self.middle, d, self.middle + self.majortickwidth, d) 139 c.create_text(self.middle + labeloffset, d, font = small_font, text = str(v)) 140 141 self._desiredSet(event) 142 self._actualSet(event) 143 144 def _backgroundSet(self): 145 self.canvas.configure(bg = self['bg']) 146 147 def _desiredSet(self, event = None): 148 c = self.canvas 149 desired = self['desiredvalue'] 150 desiredcolour = self['desiredcolour'] 151 152 min = self['min'] 153 max = self['max'] 154 155 if desired > max: desired = max 156 if desired < min: desired = min 157 gauge_range = max - min 158 159 c = self.canvas 160 if event: 161 h, w = event.height, event.width 162 else: 163 h = int(c.configure("height")[4]) 164 w = int(c.configure("width")[4]) 165 166 167 desired_y = self.lower - (float(desired - min) / gauge_range) * self.axislength 168 169 try: 170 c.delete('desiredBar') 171 except: 172 pass 173 174 c.create_line(self.middle - self.majortickwidth, desired_y, 175 self.middle + self.majortickwidth, desired_y, 176 fill = desiredcolour, stipple = 'gray50', 177 width = 10, tag = 'desiredBar') 178 self.desiredlabel.configure(text = desired) 179 180 def setActual(self, value): 181 self.configure(actualvalue = value) 182 183 def getActual(self): 184 return self.cget('actualvalue') 185 186 def _actualSet(self, event = None): 187 c = self.canvas 188 actual = self['actualvalue'] 189 actualcolour = self['actualcolour'] 190 191 min = self['min'] 192 max = self['max'] 193 194 if actual > max: actual = max 195 if actual < min: actual = min 196 gauge_range = max - min 197 198 c = self.canvas 199 if event: 200 h, w = event.height, event.width 201 else: 202 h = int(c.configure("height")[4]) 203 w = int(c.configure("width")[4]) 204 205 actual_y = self.lower - (float(actual - min) / gauge_range) * self.axislength 206 207 try: 208 c.delete('actualPointer') 209 except: 210 pass 211 212 triangle = ((self.middle, actual_y), 213 (self.middle - 1.4 * self.majortickwidth, actual_y - self.majortickwidth / 2), 214 (self.middle - 1.4 * self.majortickwidth, actual_y + self.majortickwidth / 2)) 215 216 c.create_polygon(triangle, fill = actualcolour, tag = 'actualPointer') 217 self.actuallabel.configure(text = actual) 218 219 220Pmw.forwardmethods(VerticalGauge, Tkinter.Canvas, 'canvas') 221 222if __name__ == '__main__': 223 224 225 # Initialise Tkinter and Pmw. 226 root = Pmw.initialise() 227 root.title('Pmw VerticalGauge demonstration') 228 229 230 def increase(): 231 av = g1.getActual() 232 g1.setActual(av + 1) 233 234 def decrease(): 235 av = g1.getActual() 236 g1.setActual(av - 1) 237 238 g1 = VerticalGauge(min = 0, 239 max = 30, 240 actualvalue = 15, 241 desiredvalue = 22, 242 majortickinterval = 2, 243 label = "Pms") 244 g1.grid(sticky = "nsew") 245 root.grid_rowconfigure(0, weight = 1) 246 root.grid_columnconfigure(0, weight = 1) 247 b1 = Tkinter.Button(text = "Increase", command = increase) 248 b1.grid() 249 b2 = Tkinter.Button(text = "Decrease", command = decrease) 250 b2.grid() 251 252 # Let's go. 253 root.mainloop() 254