]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/DragImage.py
   5 #---------------------------------------------------------------------- 
   8     def __init__(self
, bmp
): 
  13         self
.fullscreen 
= False 
  15     def HitTest(self
, pt
): 
  17         return rect
.InsideXY(pt
.x
, pt
.y
) 
  20         return wx
.Rect(self
.pos
[0], self
.pos
[1], 
  21                       self
.bmp
.GetWidth(), self
.bmp
.GetHeight()) 
  23     def Draw(self
, dc
, op 
= wx
.COPY
): 
  26             memDC
.SelectObject(self
.bmp
) 
  28             dc
.Blit(self
.pos
[0], self
.pos
[1], 
  29                     self
.bmp
.GetWidth(), self
.bmp
.GetHeight(), 
  30                     memDC
, 0, 0, op
, True) 
  38 #---------------------------------------------------------------------- 
  40 class DragCanvas(wx
.ScrolledWindow
): 
  41     def __init__(self
, parent
, ID
): 
  42         wx
.ScrolledWindow
.__init
__(self
, parent
, ID
) 
  46         self
.hiliteShape 
= None 
  48         self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
)) 
  49         self
.bg_bmp 
= images
.getBackgroundBitmap() 
  50         self
.SetBackgroundStyle(wx
.BG_STYLE_CUSTOM
) 
  52         # Make a shape from an image and mask.  This one will demo 
  53         # dragging outside the window 
  54         bmp 
= images
.getTestStarBitmap() 
  55         #bmp = wx.Bitmap('bitmaps/toucan.png') 
  56         shape 
= DragShape(bmp
) 
  58         shape
.fullscreen 
= True 
  59         self
.shapes
.append(shape
) 
  61         bmp 
= images
.getTheKidBitmap() 
  62         shape 
= DragShape(bmp
) 
  64         self
.shapes
.append(shape
) 
  66         # Make a shape from some text 
  68         bg_colour 
= wx
.Colour(57, 115, 57)  # matches the bg image 
  69         font 
= wx
.Font(15, wx
.ROMAN
, wx
.NORMAL
, wx
.BOLD
) 
  70         textExtent 
= self
.GetFullTextExtent(text
, font
) 
  72         # create a bitmap the same size as our text 
  73         bmp 
= wx
.EmptyBitmap(textExtent
[0], textExtent
[1]) 
  75         # 'draw' the text onto the bitmap 
  78         dc
.SetBackground(wx
.Brush(bg_colour
, wx
.SOLID
)) 
  80         dc
.SetTextForeground(wx
.RED
) 
  82         dc
.DrawText(text
, 0, 0) 
  83         dc
.SelectObject(wx
.NullBitmap
) 
  84         mask 
= wx
.Mask(bmp
, bg_colour
) 
  86         shape 
= DragShape(bmp
) 
  88         shape
.text 
= "Some dragging text" 
  89         self
.shapes
.append(shape
) 
  92         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
) 
  93         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
  94         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
) 
  95         self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
) 
  96         self
.Bind(wx
.EVT_MOTION
, self
.OnMotion
) 
  97         self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnLeaveWindow
) 
 100     # We're not doing anything here, but you might have reason to. 
 101     # for example, if you were dragging something, you might elect to 
 102     # 'drop it' when the cursor left the window. 
 103     def OnLeaveWindow(self
, evt
): 
 107     # tile the background bitmap 
 108     def TileBackground(self
, dc
): 
 109         sz 
= self
.GetClientSize() 
 110         w 
= self
.bg_bmp
.GetWidth() 
 111         h 
= self
.bg_bmp
.GetHeight() 
 119                 dc
.DrawBitmap(self
.bg_bmp
, x
, y
) 
 125     # Go through our list of shapes and draw them in whatever place they are. 
 126     def DrawShapes(self
, dc
): 
 127         for shape 
in self
.shapes
: 
 131     # This is actually a sophisticated 'hit test', but in this 
 132     # case we're also determining which shape, if any, was 'hit'. 
 133     def FindShape(self
, pt
): 
 134         for shape 
in self
.shapes
: 
 135             if shape
.HitTest(pt
): 
 139     # Remove a shape from the display 
 140     def EraseShape(self
, shape
, dc
): 
 142         dc
.SetClippingRect(r
) 
 143         self
.TileBackground(dc
) 
 145         dc
.DestroyClippingRegion() 
 147     # Clears the background, then redraws it. If the DC is passed, then 
 148     # we only do so in the area so designated. Otherwise, it's the whole thing. 
 149     def OnEraseBackground(self
, evt
): 
 153             dc 
= wx
.ClientDC(self
) 
 154             rect 
= self
.GetUpdateRegion().GetBox() 
 155             dc
.SetClippingRect(rect
) 
 156         self
.TileBackground(dc
) 
 158     # Fired whenever a paint event occurs 
 159     def OnPaint(self
, evt
): 
 160         dc 
= wx
.PaintDC(self
) 
 164     # Left mouse button is down. 
 165     def OnLeftDown(self
, evt
): 
 166         # Did the mouse go down on one of our shapes? 
 167         shape 
= self
.FindShape(evt
.GetPosition()) 
 169         # If a shape was 'hit', then set that as the shape we're going to 
 170         # drag around. Get our start position. Dragging has not yet started. 
 171         # That will happen once the mouse moves, OR the mouse is released. 
 173             self
.dragShape 
= shape
 
 174             self
.dragStartPos 
= evt
.GetPosition() 
 176     # Left mouse button up. 
 177     def OnLeftUp(self
, evt
): 
 178         if not self
.dragImage 
or not self
.dragShape
: 
 179             self
.dragImage 
= None 
 180             self
.dragShape 
= None 
 183         # Hide the image, end dragging, and nuke out the drag image. 
 184         self
.dragImage
.Hide() 
 185         self
.dragImage
.EndDrag() 
 186         self
.dragImage 
= None 
 189             self
.RefreshRect(self
.hiliteShape
.GetRect()) 
 190             self
.hiliteShape 
= None 
 192         # reposition and draw the shape 
 194         # Note by jmg 11/28/03  
 195         # Here's the original: 
 197         # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos 
 199         # So if there are any problems associated with this, use that as 
 200         # a starting place in your investigation. I've tried to simulate the 
 201         # wx.Point __add__ method here -- it won't work for tuples as we 
 202         # have now from the various methods 
 204         # There must be a better way to do this :-) 
 207         self
.dragShape
.pos 
= ( 
 208             self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0], 
 209             self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1] 
 212         self
.dragShape
.shown 
= True 
 213         self
.RefreshRect(self
.dragShape
.GetRect()) 
 214         self
.dragShape 
= None 
 217     # The mouse is moving 
 218     def OnMotion(self
, evt
): 
 219         # Ignore mouse movement if we're not dragging. 
 220         if not self
.dragShape 
or not evt
.Dragging() or not evt
.LeftIsDown(): 
 223         # if we have a shape, but haven't started dragging yet 
 224         if self
.dragShape 
and not self
.dragImage
: 
 226             # only start the drag after having moved a couple pixels 
 228             pt 
= evt
.GetPosition() 
 229             dx 
= abs(pt
.x 
- self
.dragStartPos
.x
) 
 230             dy 
= abs(pt
.y 
- self
.dragStartPos
.y
) 
 231             if dx 
<= tolerance 
and dy 
<= tolerance
: 
 234             # erase the shape since it will be drawn independently now 
 235             dc 
= wx
.ClientDC(self
) 
 236             self
.dragShape
.shown 
= False 
 237             self
.EraseShape(self
.dragShape
, dc
) 
 240             if self
.dragShape
.text
: 
 241                 self
.dragImage 
= wx
.DragString(self
.dragShape
.text
, 
 242                                               wx
.StockCursor(wx
.CURSOR_HAND
)) 
 244                 self
.dragImage 
= wx
.DragImage(self
.dragShape
.bmp
, 
 245                                              wx
.StockCursor(wx
.CURSOR_HAND
)) 
 247             hotspot 
= self
.dragStartPos 
- self
.dragShape
.pos
 
 248             self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
) 
 250             self
.dragImage
.Move(pt
) 
 251             self
.dragImage
.Show() 
 254         # if we have shape and image then move it, posibly highlighting another shape. 
 255         elif self
.dragShape 
and self
.dragImage
: 
 256             onShape 
= self
.FindShape(evt
.GetPosition()) 
 260             # figure out what to hilite and what to unhilite 
 262                 if onShape 
is None or self
.hiliteShape 
is not onShape
: 
 265             if onShape 
and onShape 
is not self
.hiliteShape 
and onShape
.shown
: 
 268             # if needed, hide the drag image so we can update the window 
 269             if unhiliteOld 
or hiliteNew
: 
 270                 self
.dragImage
.Hide() 
 273                 dc 
= wx
.ClientDC(self
) 
 274                 self
.hiliteShape
.Draw(dc
) 
 275                 self
.hiliteShape 
= None 
 278                 dc 
= wx
.ClientDC(self
) 
 279                 self
.hiliteShape 
= onShape
 
 280                 self
.hiliteShape
.Draw(dc
, wx
.INVERT
) 
 282             # now move it and show it again if needed 
 283             self
.dragImage
.Move(evt
.GetPosition()) 
 284             if unhiliteOld 
or hiliteNew
: 
 285                 self
.dragImage
.Show() 
 288 #---------------------------------------------------------------------- 
 290 def runTest(frame
, nb
, log
): 
 292     win 
= wx
.Panel(nb
, -1) 
 293     canvas 
= DragCanvas(win
, -1) 
 295     def onSize(evt
, panel
=win
, canvas
=canvas
):  
 296         canvas
.SetSize(panel
.GetSize()) 
 298     win
.Bind(wx
.EVT_SIZE
, onSize
) 
 301 #---------------------------------------------------------------------- 
 306 DragImage is used when you wish to drag an object on the screen, and a simple  
 307 cursor is not enough. 
 309 On Windows, the WIN32 API is used to do achieve smooth dragging. On other  
 310 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use  
 311 <code>GenericDragImage</code> on Windows, too. 
 313 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all  
 314 platforms, but uses the <code>DragImage</code> name. 
 316 To use this class, when you wish to start dragging an image, create a  
 317 <code>DragImage</code> object and store it somewhere you can access it as the  
 318 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move  
 319 the image, initially call Show and then Move. If you wish to update the screen  
 320 contents during the drag (for example, highlight an item as in the example), first  
 321 call Hide, update the screen, call Move, and then call Show. 
 323 You can drag within one window, or you can use full-screen dragging either across  
 324 the whole screen, or just restricted to one area of the screen to save resources.  
 325 If you want the user to drag between two windows, then you will need to use  
 326 full-screen dragging. 
 331 if __name__ 
== '__main__': 
 334     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])