]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Joystick.py
03ba8e98c7cbc9b75c768f0f44e7b9cef6aab30f
   1 #---------------------------------------------------------------------------- 
   3 # Purpose:     Demonstrate use of wx.Joystick 
   5 # Author:      Jeff Grimmett (grimmtoo@softhome.net), adapted from original 
  11 # Licence:     wxWindows license 
  12 #---------------------------------------------------------------------------- 
  18 #---------------------------------------------------------------------------- 
  24 #---------------------------------------------------------------------------- 
  26 class Label(wx
.StaticText
): 
  27     # A derived StaticText that always aligns right and renders 
  29     def __init__(self
, parent
, label
): 
  30         wx
.StaticText
.__init
__(self
, parent
, -1, label
, style
=wx
.ALIGN_RIGHT
) 
  34                 parent
.GetFont().GetPointSize(), 
  35                 parent
.GetFont().GetFamily(), 
  36                 parent
.GetFont().GetStyle(), 
  40 #---------------------------------------------------------------------------- 
  43 class JoyGauge(wx
.Panel
): 
  44     def __init__(self
, parent
, stick
): 
  49         wx
.Panel
.__init
__(self
, parent
, -1, size
=size
) 
  51         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
  52         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
  53         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, lambda e
: None) 
  55         self
.buffer = wx
.EmptyBitmap(*size
) 
  56         dc 
= wx
.BufferedDC(None, self
.buffer) 
  61     def OnSize(self
, event
): 
  62         # The face Bitmap init is done here, to make sure the buffer is always 
  63         # the same size as the Window 
  64         w
, h  
= self
.GetClientSize() 
  65         self
.buffer = wx
.EmptyBitmap(w
,h
) 
  66         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
  71     def DrawFace(self
, dc
): 
  72         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour())) 
  76     def OnPaint(self
, evt
): 
  77         # When dc is destroyed it will blit self.buffer to the window, 
  78         # since no other drawing is needed we'll just return and let it 
  80         dc 
= wx
.BufferedPaintDC(self
, self
.buffer) 
  83     def DrawJoystick(self
, dc
): 
  84         # draw the guage as a maxed square in the center of this window. 
  85         w
, h 
= self
.GetClientSize() 
  88         xorigin 
= (w 
- edgeSize
) / 2 
  89         yorigin 
= (h 
- edgeSize
) / 2 
  92         # Restrict our drawing activities to the square defined 
  94         dc
.SetClippingRegion((xorigin
, yorigin
), (edgeSize
, edgeSize
)) 
  96         # Optimize drawing a bit (for Win) 
  99         dc
.SetBrush(wx
.Brush(wx
.Colour(251, 252, 237))) 
 100         dc
.DrawRectangle((xorigin
, yorigin
), (edgeSize
, edgeSize
)) 
 102         dc
.SetPen(wx
.Pen(wx
.BLACK
, 1, wx
.DOT_DASH
)) 
 104         dc
.DrawLine((xorigin
, yorigin 
+ center
), (xorigin 
+ edgeSize
, yorigin 
+ center
)) 
 105         dc
.DrawLine((xorigin 
+ center
, yorigin
), (xorigin 
+ center
, yorigin 
+ edgeSize
)) 
 108             # Get the joystick position as a float 
 109             joyx 
=  float(self
.stick
.GetPosition().x
) 
 110             joyy 
=  float(self
.stick
.GetPosition().y
) 
 112             # Get the joystick range of motion 
 113             xrange = self
.stick
.GetXMax() - self
.stick
.GetXMin() 
 114             yrange 
= self
.stick
.GetYMax() - self
.stick
.GetYMin() 
 116             # calc a ratio of our range versus the joystick range 
 117             xratio 
= float(edgeSize
) / xrange 
 118             yratio 
= float(edgeSize
) / yrange
 
 120             # calc the displayable value based on position times ratio 
 121             xval 
= int(joyx 
* xratio
) 
 122             yval 
= int(joyy 
* xratio
) 
 124             # and normalize the value from our brush's origin 
 129             dc
.SetPen(wx
.Pen(wx
.RED
, 2)) 
 132         # Turn off drawing optimization 
 137         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
 139         self
.DrawJoystick(dc
) 
 142 #---------------------------------------------------------------------------- 
 144 class JoyPanel(wx
.Panel
): 
 145     def __init__(self
, parent
, stick
): 
 149         wx
.Panel
.__init
__(self
, parent
, -1) 
 151         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 154                 parent
.GetFont().GetPointSize() + 3, 
 155                 parent
.GetFont().GetFamily(), 
 156                 parent
.GetFont().GetStyle(), 
 160         t 
= wx
.StaticText(self
, -1, "X - Y Axes", style 
= wx
.ALIGN_CENTRE
) 
 162         sizer
.Add(t
, 0, wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER | wx
.ALIGN_CENTER_HORIZONTAL
, 1) 
 164         self
.control 
= JoyGauge(self
, self
.stick
) 
 165         sizer
.Add(self
.control
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER | wx
.ALIGN_CENTER_HORIZONTAL
, 1) 
 171         self
.control
.Update() 
 174 #---------------------------------------------------------------------------- 
 176 class POVGauge(wx
.Panel
): 
 178     # Display the current postion of the POV control 
 180     def __init__(self
, parent
, stick
): 
 183         self
.size 
= (100, 100) 
 188         wx
.Panel
.__init
__(self
, parent
, -1, size
=self
.size
) 
 190         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 191         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
 192         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, lambda e
: None) 
 194         self
.buffer = wx
.EmptyBitmap(*self
.size
) 
 195         dc 
= wx
.BufferedDC(None, self
.buffer) 
 200     def OnSize(self
, event
): 
 201         # calculate the size of our display and make a buffer for it. 
 202         w
, h  
= self
.GetClientSize() 
 205         self
.buffer = wx
.EmptyBitmap(w
,h
) 
 206         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
 211     def DrawFace(self
, dc
): 
 212         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour())) 
 216     def OnPaint(self
, evt
): 
 217         # When dc is destroyed it will blit self.buffer to the window, 
 218         # since no other drawing is needed we'll just return and let it 
 220         dc 
= wx
.BufferedPaintDC(self
, self
.buffer) 
 223     def DrawPOV(self
, dc
): 
 224         # draw the guage as a maxed circle in the center of this window. 
 225         w
, h 
= self
.GetClientSize() 
 228         xorigin 
= (w 
- diameter
) / 2 
 229         yorigin 
= (h 
- diameter
) / 2 
 230         xcenter 
= xorigin 
+ diameter 
/ 2 
 231         ycenter 
= yorigin 
+ diameter 
/ 2 
 233         # Optimize drawing a bit (for Win) 
 237         dc
.SetBrush(wx
.Brush(wx
.WHITE
)) 
 238         dc
.DrawCircle((xcenter
, ycenter
), diameter
/2) 
 239         dc
.SetBrush(wx
.Brush(wx
.BLACK
)) 
 240         dc
.DrawCircle((xcenter
, ycenter
), 10) 
 243         dc
.SetPen(wx
.Pen(wx
.BLACK
, 1, wx
.DOT_DASH
)) 
 244         dc
.DrawLine((xorigin
, ycenter
), (xorigin 
+ diameter
, ycenter
)) 
 245         dc
.DrawLine((xcenter
, yorigin
), (xcenter
, yorigin 
+ diameter
)) 
 252                 # use the appropriate function to get the POV position 
 254                     pos 
= self
.stick
.GetPOVPosition() 
 257                     pos 
= self
.stick
.GetPOVCTSPosition() 
 259                 # trap invalid values 
 260                 if 0 <= pos 
<= 36000: 
 265                 # rotate CCW by 90 so that 0 is up. 
 266                 pos 
= (pos 
/ 100) - 90 
 272                 # Stolen from wx.lib.analogclock :-) 
 273                 radiansPerDegree 
= math
.pi 
/ 180 
 274                 pointX 
= int(round(vector 
* math
.cos(pos 
* radiansPerDegree
))) 
 275                 pointY 
= int(round(vector 
* math
.sin(pos 
* radiansPerDegree
))) 
 277                 # normalise value to match our actual center. 
 278                 nx 
= pointX 
+ xcenter
 
 279                 ny 
= pointY 
+ ycenter
 
 282                 dc
.SetPen(wx
.Pen(wx
.BLUE
, 2)) 
 283                 dc
.DrawLine((xcenter
, ycenter
), (nx
, ny
)) 
 285                 # And a little thing to show the endpoint 
 286                 dc
.SetBrush(wx
.Brush(wx
.BLUE
)) 
 287                 dc
.DrawCircle((nx
, ny
), 8) 
 289         # Turn off drawing optimization 
 294         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
 301         self
.avail 
= s
.HasPOV() 
 302         self
.fourDir 
= s
.HasPOV4Dir() 
 303         self
.cts 
= s
.HasPOVCTS() 
 306 #---------------------------------------------------------------------------- 
 308 class POVStatus(wx
.Panel
): 
 310     # Displays static info about the POV control 
 312     def __init__(self
, parent
, stick
): 
 316         wx
.Panel
.__init
__(self
, parent
, -1, size
=(100, 100)) 
 318         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 321         self
.avail 
= wx
.CheckBox(self
, -1, "Available") 
 322         sizer
.Add(self
.avail
, 0, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 2) 
 324         self
.fourDir 
= wx
.CheckBox(self
, -1, "4-Way Only") 
 325         sizer
.Add(self
.fourDir
, 0, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 2) 
 327         self
.cts 
= wx
.CheckBox(self
, -1, "Continuous") 
 328         sizer
.Add(self
.cts
, 0, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 2) 
 333         # Effectively makes the checkboxes read-only. 
 334         self
.Bind(wx
.EVT_CHECKBOX
, self
.Calibrate
) 
 337     def Calibrate(self
, evt
=None): 
 339         self
.avail
.SetValue(s
.HasPOV()) 
 340         self
.fourDir
.SetValue(s
.HasPOV4Dir()) 
 341         self
.cts
.SetValue(s
.HasPOVCTS()) 
 344 #---------------------------------------------------------------------------- 
 346 class POVPanel(wx
.Panel
): 
 347     def __init__(self
, parent
, stick
): 
 351         wx
.Panel
.__init
__(self
, parent
, -1, size
=(100, 100)) 
 353         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 354         gsizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 359                 parent
.GetFont().GetPointSize() + 3, 
 360                 parent
.GetFont().GetFamily(), 
 361                 parent
.GetFont().GetStyle(), 
 364         t 
= wx
.StaticText(self
, -1, "POV Control", style 
= wx
.ALIGN_CENTER
) 
 366         gsizer
.Add(t
, 0, wx
.ALL | wx
.EXPAND
, 1) 
 368         self
.display 
= POVGauge(self
, stick
) 
 369         gsizer
.Add(self
.display
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER
, 1) 
 370         sizer
.Add(gsizer
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER
, 1) 
 372         self
.status 
= POVStatus(self
, stick
) 
 373         sizer
.Add(self
.status
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER
, 1) 
 380         self
.display
.Calibrate() 
 381         self
.status
.Calibrate() 
 385         self
.display
.Update() 
 388 #---------------------------------------------------------------------------- 
 391     def __init__(self
, parent
, number
): 
 398                 parent
.GetFont().GetPointSize() - 1, 
 399                 parent
.GetFont().GetFamily(), 
 400                 parent
.GetFont().GetStyle(), 
 404         wx
.Panel
.__init
__(self
, parent
, -1, size
=self
.size
) 
 406         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 407         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
 408         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, lambda e
: None) 
 410         self
.buffer = wx
.EmptyBitmap(*self
.size
) 
 411         dc 
= wx
.BufferedDC(None, self
.buffer) 
 416     def OnSize(self
, event
): 
 417         # calculate the size of our display. 
 418         w
, h  
= self
.GetClientSize() 
 421         self
.buffer = wx
.EmptyBitmap(*self
.size
) 
 422         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
 427     def DrawFace(self
, dc
): 
 428         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour())) 
 432     def OnPaint(self
, evt
): 
 433         # When dc is destroyed it will blit self.buffer to the window, 
 434         # since no other drawing is needed we'll just return and let it 
 436         dc 
= wx
.BufferedPaintDC(self
, self
.buffer) 
 439     def DrawLED(self
, dc
): 
 446         # calc the 0, 0 origin of the bitmap 
 447         xorigin 
= center 
- (bw 
/ 2) 
 448         yorigin 
= center 
- (bh 
/ 2) 
 450         # Optimize drawing a bit (for Win) 
 455             dc
.SetBrush(wx
.Brush(wx
.RED
)) 
 456         elif self
.state 
== 1: 
 457             dc
.SetBrush(wx
.Brush(wx
.GREEN
)) 
 459             dc
.SetBrush(wx
.Brush(wx
.BLACK
)) 
 461         dc
.DrawCircle((center
, center
), bw
/2) 
 463         txt 
= str(self
.number
) 
 465         # Set the font for the DC ... 
 467         # ... and calculate how much space our value 
 469         fw
, fh 
= dc
.GetTextExtent(txt
) 
 471         # Calc the center of the LED, and from that 
 472         # derive the origin of our value. 
 476         # I draw the value twice so as to give it a pseudo-shadow. 
 477         # This is (mostly) because I'm too lazy to figure out how 
 478         # to blit my text onto the gauge using one of the logical 
 479         # functions. The pseudo-shadow gives the text contrast 
 480         # regardless of whether the bar is under it or not. 
 481         dc
.SetTextForeground(wx
.WHITE
) 
 482         dc
.DrawText(txt
, (tx
, ty
)) 
 484         # Turn off drawing optimization 
 489         dc 
= wx
.BufferedDC(wx
.ClientDC(self
), self
.buffer) 
 494 #---------------------------------------------------------------------------- 
 496 class JoyButtons(wx
.Panel
): 
 497     def __init__(self
, parent
, stick
): 
 502         wx
.Panel
.__init
__(self
, parent
, -1) 
 504         tsizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 507                 parent
.GetFont().GetPointSize() + 3, 
 508                 parent
.GetFont().GetFamily(), 
 509                 parent
.GetFont().GetStyle(), 
 513         t 
= wx
.StaticText(self
, -1, "Buttons", style 
= wx
.ALIGN_LEFT
) 
 515         tsizer
.Add(t
, 0, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 1) 
 517         sizer 
= wx
.FlexGridSizer(4, 16, 2, 2) 
 519         fn
.SetPointSize(parent
.GetFont().GetPointSize() + 1) 
 521         for i 
in range(0, MAX_BUTTONS
): 
 524             sizer
.Add(t
, 1, wx
.ALL|wx
.ALIGN_CENTER|wx
.ALIGN_CENTER_VERTICAL
, 1) 
 525             sizer
.AddGrowableCol(i
) 
 527         tsizer
.Add(sizer
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 1) 
 529         self
.SetSizer(tsizer
) 
 533         for i 
in range(0, MAX_BUTTONS
): 
 534             self
.leds
[i
].state 
= -1 
 536         t 
= self
.stick
.GetNumberButtons() 
 538         for i 
in range(0, t
): 
 539             self
.leds
[i
].state 
= 0 
 542         t 
= self
.stick
.GetButtonState() 
 544         for i 
in range(0, MAX_BUTTONS
): 
 545             if self
.leds
[i
].state 
== 1: 
 546                 self
.leds
[i
].state 
= 0 
 549                 self
.leds
[i
].state 
= 1 
 551             self
.leds
[i
].Update() 
 554 #---------------------------------------------------------------------------- 
 556 class InfoPanel(wx
.Panel
): 
 557     def __init__(self
, parent
, stick
): 
 561         wx
.Panel
.__init
__(self
, parent
, -1) 
 563         sizer 
= wx
.GridBagSizer(1, 1) 
 565         sizer
.Add(Label(self
, 'Mfr ID: '), (0, 0), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 566         self
.MfgID 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 567         sizer
.Add(self
.MfgID
, (0, 1), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 569         sizer
.Add(Label(self
, 'Prod Name: '), (0, 2), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 570         self
.ProdName 
= wx
.TextCtrl(self
, -1, value
='', style
=wx
.TE_READONLY
) 
 571         sizer
.Add(self
.ProdName
, (0, 3), (1, 3), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 573         sizer
.Add(Label(self
, 'Threshold: '), (0, 6), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 574         self
.Threshold 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 575         sizer
.Add(self
.Threshold
, (0, 7), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 577         #---------------------------------------------------------------------------- 
 578         b 
= wx
.Button(self
, -1, "Calibrate") 
 579         sizer
.Add(b
, (1, 0), (2, 2), wx
.ALL | wx
.ALIGN_CENTER
, 2) 
 581         sizer
.Add(Label(self
, '# of Sticks: '), (1, 2), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 582         self
.NumJoysticks 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 583         sizer
.Add(self
.NumJoysticks
, (1, 3), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 585         sizer
.Add(Label(self
, '# of Axes: '), (1, 4), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 586         self
.NumAxis 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 587         sizer
.Add(self
.NumAxis
, (1, 5), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 589         sizer
.Add(Label(self
, 'Max # Axes: '), (1, 6), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 590         self
.MaxAxis 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 591         sizer
.Add(self
.MaxAxis
, (1, 7), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 593         #---------------------------------------------------------------------------- 
 595         sizer
.Add(Label(self
, 'Polling -- '), (2, 3), (1, 1), wx
.ALL | wx
.GROW
, 2) 
 597         sizer
.Add(Label(self
, 'Min: '), (2, 4), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 598         self
.PollMin 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 599         sizer
.Add(self
.PollMin
, (2, 5), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 601         sizer
.Add(Label(self
, 'Max: '), (2, 6), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_RIGHT
, 2) 
 602         self
.PollMax 
= wx
.TextCtrl(self
, -1, value
='', size
=(45, -1), style
=wx
.TE_READONLY
) 
 603         sizer
.Add(self
.PollMax
, (2, 7), (1, 1), wx
.ALL | wx
.GROW | wx
.ALIGN_LEFT
, 2) 
 605         #---------------------------------------------------------------------------- 
 617         self
.MfgID
.SetValue(str(s
.GetManufacturerId())) 
 618         self
.ProdName
.SetValue(str(s
.GetProductName())) 
 619         self
.Threshold
.SetValue(str(s
.GetMovementThreshold())) 
 620         self
.NumJoysticks
.SetValue(str(s
.GetNumberJoysticks())) 
 621         self
.NumAxis
.SetValue(str(s
.GetNumberAxes())) 
 622         self
.MaxAxis
.SetValue(str(s
.GetMaxAxes())) 
 623         self
.PollMin
.SetValue(str(s
.GetPollingMin())) 
 624         self
.PollMax
.SetValue(str(s
.GetPollingMax())) 
 627 #---------------------------------------------------------------------------- 
 629 class AxisBar(wx
.Gauge
): 
 631     # This class allows us to use a wx.Gauge to display the axis value 
 632     # with a fancy label overlayed onto the guage itself. Two values are 
 633     # used to do things: first of all, since the gauge is limited to 
 634     # positive numbers, the scale is fixed at 0 to 1000. We will receive 
 635     # an adjusted value to use to render the gauge itself. The other value 
 636     # is a raw value and actually reflects the value from the joystick itself, 
 637     # which is then drawn over the gauge. 
 639     def __init__(self
, parent
): 
 640         wx
.Gauge
.__init
__(self
, parent
, -1, 1000, size
=(-1, 20), style 
= wx
.GA_HORIZONTAL | wx
.GA_SMOOTH 
) 
 642         # This is the value we will display. 
 645         self
.SetBackgroundColour('light blue') 
 646         self
.SetForegroundColour('orange') 
 648         # Capture paint events for purpose of updating 
 649         # the displayed value. 
 650         self
.Bind(wx
.EVT_PAINT
, self
.onPaint
) 
 652     def Update(self
, value
, rawvalue
): 
 653         # Updates the gauge itself, sets the raw value for 
 656         self
.rawvalue 
= rawvalue
 
 658     def onPaint(self
, evt
): 
 659         # Must always create a PaintDC when capturing 
 661         self
.ShowValue(wx
.PaintDC(self
), evt
) 
 663     def ShowValue(self
, dc
, evt
): 
 664         # This method handles actual painting of and drawing 
 667         # Clear out the gauge 
 669         # and then carry out business as usual 
 670         wx
.Gauge
.OnPaint(self
, evt
) 
 672         # This is the size available to us. 
 675         # This is what we will overlay on the gauge. 
 676         # It reflects the actual value received from the 
 678         txt 
= str(self
.rawvalue
) 
 680         # Copy the default font, make it bold. 
 682                 self
.GetFont().GetPointSize(), 
 683                 self
.GetFont().GetFamily(), 
 684                 self
.GetFont().GetStyle(), 
 688         # Set the font for the DC ... 
 690         # ... and calculate how much space our value 
 692         fw
, fh 
= dc
.GetTextExtent(txt
) 
 694         # Calc the center of the gauge, and from that 
 695         # derive the origin of our value. 
 702         # I draw the value twice so as to give it a pseudo-shadow. 
 703         # This is (mostly) because I'm too lazy to figure out how 
 704         # to blit my text onto the gauge using one of the logical 
 705         # functions. The pseudo-shadow gives the text contrast 
 706         # regardless of whether the bar is under it or not. 
 707         dc
.SetTextForeground(wx
.BLACK
) 
 708         dc
.DrawText(txt
, (tx
, ty
)) 
 710         dc
.SetTextForeground('white') 
 711         dc
.DrawText(txt
, (tx
-1, ty
-1)) 
 714 #---------------------------------------------------------------------------- 
 716 class Axis(wx
.Panel
): 
 718     # This class is a container for the min, max, and current 
 719     # values of the joystick axis in question. It contains 
 720     # also special features to render a 'dummy' if the axis 
 721     # in question is not available. 
 723     def __init__(self
, parent
, token
, stick
): 
 728         # token represents the type of axis we're displaying. 
 733         # Create a call to the 'Has*()' method for the stick. 
 734         # X and Y are always there, so we tie the Has* method 
 735         # to a hardwired True value. 
 737         if token 
not in ['X', 'Y']: 
 738             self
.HasFunc 
= eval('stick.Has%s' % token
) 
 740             self
.HasFunc 
= self
.alwaysTrue
 
 742         # Now init the panel. 
 743         wx
.Panel
.__init
__(self
, parent
, -1) 
 745         sizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 749             # Tie our calibration functions to the appropriate 
 750             # stick method. If we don't have the axis in question, 
 751             # we won't need them. 
 753             self
.GetMin 
= eval('stick.Get%sMin' % token
) 
 754             self
.GetMax 
= eval('stick.Get%sMax' % token
) 
 756             # Create our displays and set them up. 
 757             self
.Min 
= wx
.StaticText(self
, -1, str(self
.GetMin()), 
 758                                      size
=(40,-1), style
=wx
.ALIGN_RIGHT | wx
.ST_NO_AUTORESIZE
) 
 759             self
.Max 
= wx
.StaticText(self
, -1, str(self
.GetMax()), 
 760                                      size
=(40,-1), style
=wx
.ALIGN_LEFT | wx
.ST_NO_AUTORESIZE
) 
 761             self
.bar 
= AxisBar(self
) 
 763             sizer
.Add(self
.Min
, 0, wx
.ALL | wx
.ALIGN_RIGHT | wx
.ALIGN_CENTER_VERTICAL
, 1) 
 764             sizer
.Add(self
.bar
, 1, wx
.ALL | wx
.ALIGN_CENTER | wx
.ALIGN_CENTER_VERTICAL
, 1) 
 765             sizer
.Add(self
.Max
, 0, wx
.ALL | wx
.ALIGN_LEFT | wx
.ALIGN_CENTER_VERTICAL
, 1) 
 768             # We go here if the axis in question is not available. 
 769             self
.control 
= wx
.StaticText(self
, -1, '       *** Not Present ***') 
 770             sizer
.Add(self
.control
, 1, wx
.ALL | wx
.ALIGN_CENTER | wx
.ALIGN_CENTER_VERTICAL
, 1) 
 772         #---------------------------------------------------------------------------- 
 776         wx
.CallAfter(self
.Update
) 
 780         if not self
.HasFunc(): 
 783         self
.Min
.SetLabel(str(self
.GetMin())) 
 784         self
.Max
.SetLabel(str(self
.GetMax())) 
 788         # Don't bother if the axis doesn't exist. 
 789         if not self
.HasFunc(): 
 792         min = int(self
.Min
.GetLabel()) 
 793         max = int(self
.Max
.GetLabel()) 
 796         # Not all values are available from a wx.JoystickEvent, so I've elected 
 797         # to not use it at all. Therefore, we are getting our values direct from 
 798         # the stick. These values also seem to be more stable and reliable than 
 799         # those received from the event itself, so maybe it's a good idea to 
 800         # use the stick directly for your program. 
 802         # Here we either select the appropriate member of stick.GetPosition() or 
 803         # apply the appropriate Get*Position method call. 
 805         if self
.token 
== 'X': 
 806             val 
= self
.stick
.GetPosition().x
 
 807         elif self
.token 
== 'Y': 
 808             val 
= self
.stick
.GetPosition().y
 
 810             val 
= eval('self.stick.Get%sPosition()' % self
.token
) 
 813         # While we might be able to rely on a range of 0-FFFFFF on Win, that might 
 814         # not be true of all drivers on all platforms. Thus, calc the actual full 
 817         range = float(max - min) 
 820         # The relative value is used by the derived wx.Gauge since it is a 
 821         # positive-only control. 
 825             relative 
= int(val 
/ range * 1000) 
 828         # Pass both the raw and relative values to the derived Gauge 
 830         self
.bar
.Update(relative
, val
) 
 833     def alwaysTrue(self
): 
 834         # a dummy method used for X and Y axis. 
 838 #---------------------------------------------------------------------------- 
 840 class AxisPanel(wx
.Panel
): 
 842     # Contained herein is a panel that offers a graphical display 
 843     # of the levels for all axes supported by wx.Joystick. If 
 844     # your system doesn't have a particular axis, it will be 
 845     # 'dummied' for transparent use. 
 847     def __init__(self
, parent
, stick
): 
 851         # Defines labels and 'tokens' to identify each 
 854             ('X Axis ', 'X'),   ('Y Axis ', 'Y'), 
 855             ('Z Axis ', 'Z'),   ('Rudder ', 'Rudder'), 
 856             ('U Axis ', 'U'),   ('V Axis ', 'V') 
 859         # Contains a list of all axis initialized. 
 862         wx
.Panel
.__init
__(self
, parent
, -1) 
 864         sizer 
= wx
.FlexGridSizer(3, 4, 1, 1) 
 865         sizer
.AddGrowableCol(1) 
 866         sizer
.AddGrowableCol(3) 
 868         #---------------------------------------------------------------------------- 
 870         # Go through the list of labels and tokens and add a label and 
 871         # axis display to the sizer for each. 
 872         for label
, token 
in axesList
: 
 873             sizer
.Add(Label(self
, label
), 0, wx
.ALL | wx
.ALIGN_RIGHT
, 2) 
 874             t 
= Axis(self
, token
, self
.stick
) 
 876             sizer
.Add(t
, 1, wx
.ALL | wx
.EXPAND | wx
.ALIGN_LEFT
, 2) 
 878         #---------------------------------------------------------------------------- 
 882         wx
.CallAfter(self
.Update
) 
 893 #---------------------------------------------------------------------------- 
 895 class JoystickDemoPanel(wx
.Panel
): 
 897     def __init__(self
, parent
, log
): 
 901         wx
.Panel
.__init
__(self
, parent
, -1) 
 903         # Try to grab the control. If we get it, capture the stick. 
 904         # Otherwise, throw up an exception message and play stupid. 
 906             self
.stick 
= wx
.Joystick() 
 907             self
.stick
.SetCapture(self
) 
 908             # Calibrate our controls 
 909             wx
.CallAfter(self
.Calibrate
) 
 910             wx
.CallAfter(self
.OnJoystick
) 
 911         except NotImplementedError, v
: 
 912             wx
.MessageBox(str(v
), "Exception Message") 
 915         # One Sizer to Rule Them All... 
 916         sizer 
= wx
.GridBagSizer(2,2) 
 918         self
.info 
= InfoPanel(self
, self
.stick
) 
 919         sizer
.Add(self
.info
, (0, 0), (1, 3), wx
.ALL | wx
.GROW
, 2) 
 921         self
.info
.Bind(wx
.EVT_BUTTON
, self
.Calibrate
) 
 923         self
.joy 
= JoyPanel(self
, self
.stick
) 
 924         sizer
.Add(self
.joy
, (1, 0), (1, 1), wx
.ALL | wx
.GROW
, 2) 
 926         self
.pov 
= POVPanel(self
, self
.stick
) 
 927         sizer
.Add(self
.pov
, (1, 1), (1, 2), wx
.ALL | wx
.GROW
, 2) 
 929         self
.axes 
= AxisPanel(self
, self
.stick
) 
 930         sizer
.Add(self
.axes
, (2, 0), (1, 3), wx
.ALL | wx
.GROW
, 2) 
 932         self
.buttons 
= JoyButtons(self
, self
.stick
) 
 933         sizer
.Add(self
.buttons
, (3, 0), (1, 3), wx
.ALL | wx
.EXPAND | wx
.ALIGN_CENTER | wx
.ALIGN_CENTER_VERTICAL
, 1) 
 938         # Capture Joystick events (if they happen) 
 939         self
.Bind(wx
.EVT_JOYSTICK_EVENTS
, self
.OnJoystick
) 
 941         self
.stick
.SetMovementThreshold(10) 
 943     def Calibrate(self
, evt
=None): 
 944         # Do not try this without a stick 
 948         self
.info
.Calibrate() 
 949         self
.axes
.Calibrate() 
 951         self
.buttons
.Calibrate() 
 953     def OnJoystick(self
, evt
=None): 
 960         self
.buttons
.Update() 
 963 #---------------------------------------------------------------------------- 
 965 def runTest(frame
, nb
, log
): 
 966     win 
= JoystickDemoPanel(nb
, log
) 
 969 #---------------------------------------------------------------------------- 
 976 #---------------------------------------------------------------------------- 
 978 if __name__ 
== '__main__': 
 981     run
.main(['', os
.path
.basename(sys
.argv
[0])])