]>
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         # Make a shape from some text 
  63         bg_colour 
= wx
.Colour(57, 115, 57)  # matches the bg image 
  64         font 
= wx
.Font(15, wx
.ROMAN
, wx
.NORMAL
, wx
.BOLD
) 
  65         textExtent 
= self
.GetFullTextExtent(text
, font
) 
  67         # create a bitmap the same size as our text 
  68         bmp 
= wx
.EmptyBitmap(textExtent
[0], textExtent
[1]) 
  70         # 'draw' the text onto the bitmap 
  73         dc
.SetBackground(wx
.Brush(bg_colour
, wx
.SOLID
)) 
  75         dc
.SetTextForeground(wx
.RED
) 
  77         dc
.DrawText(text
, 0, 0) 
  78         dc
.SelectObject(wx
.NullBitmap
) 
  79         mask 
= wx
.Mask(bmp
, bg_colour
) 
  81         shape 
= DragShape(bmp
) 
  83         shape
.text 
= "Some dragging text" 
  84         self
.shapes
.append(shape
) 
  87         bmp 
= images
.getTheKidBitmap() 
  88         shape 
= DragShape(bmp
) 
  90         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 
= wxClientDC(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 
 188         dc 
= wx
.ClientDC(self
) 
 191             self
.hiliteShape
.Draw(dc
) 
 192             self
.hiliteShape 
= None 
 194         # reposition and draw the shape 
 196         # Note by jmg 11/28/03  
 197         # Here's the original: 
 199         # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos 
 201         # So if there are any problems associated with this, use that as 
 202         # a starting place in your investigation. I've tried to simulate the 
 203         # wx.Point __add__ method here -- it won't work for tuples as we 
 204         # have now from the various methods 
 206         # There must be a better way to do this :-) 
 209         self
.dragShape
.pos 
= ( 
 210             self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0], 
 211             self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1] 
 214         self
.dragShape
.shown 
= True 
 215         self
.dragShape
.Draw(dc
) 
 216         self
.dragShape 
= None 
 218     # The mouse is moving 
 219     def OnMotion(self
, evt
): 
 220         # Ignore mouse movement if we're not dragging. 
 221         if not self
.dragShape 
or not evt
.Dragging() or not evt
.LeftIsDown(): 
 224         # if we have a shape, but haven't started dragging yet 
 225         if self
.dragShape 
and not self
.dragImage
: 
 227             # only start the drag after having moved a couple pixels 
 229             pt 
= evt
.GetPosition() 
 230             dx 
= abs(pt
.x 
- self
.dragStartPos
.x
) 
 231             dy 
= abs(pt
.y 
- self
.dragStartPos
.y
) 
 232             if dx 
<= tolerance 
and dy 
<= tolerance
: 
 235             # erase the shape since it will be drawn independently now 
 236             dc 
= wx
.ClientDC(self
) 
 237             self
.dragShape
.shown 
= False 
 238             self
.EraseShape(self
.dragShape
, dc
) 
 241             if self
.dragShape
.text
: 
 242                 self
.dragImage 
= wx
.DragString(self
.dragShape
.text
, 
 243                                               wx
.StockCursor(wx
.CURSOR_HAND
)) 
 245                 self
.dragImage 
= wx
.DragImage(self
.dragShape
.bmp
, 
 246                                              wx
.StockCursor(wx
.CURSOR_HAND
)) 
 248             hotspot 
= self
.dragStartPos 
- self
.dragShape
.pos
 
 249             self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
) 
 251             self
.dragImage
.Move(pt
) 
 252             self
.dragImage
.Show() 
 255         # if we have shape and image then move it, posibly highlighting another shape. 
 256         elif self
.dragShape 
and self
.dragImage
: 
 257             onShape 
= self
.FindShape(evt
.GetPosition()) 
 261             # figure out what to hilite and what to unhilite 
 263                 if onShape 
is None or self
.hiliteShape 
is not onShape
: 
 266             if onShape 
and onShape 
is not self
.hiliteShape 
and onShape
.shown
: 
 269             # if needed, hide the drag image so we can update the window 
 270             if unhiliteOld 
or hiliteNew
: 
 271                 self
.dragImage
.Hide() 
 274                 dc 
= wx
.ClientDC(self
) 
 275                 self
.hiliteShape
.Draw(dc
) 
 276                 self
.hiliteShape 
= None 
 279                 dc 
= wx
.ClientDC(self
) 
 280                 self
.hiliteShape 
= onShape
 
 281                 self
.hiliteShape
.Draw(dc
, wx
.INVERT
) 
 283             # now move it and show it again if needed 
 284             self
.dragImage
.Move(evt
.GetPosition()) 
 285             if unhiliteOld 
or hiliteNew
: 
 286                 self
.dragImage
.Show() 
 289 #---------------------------------------------------------------------- 
 291 def runTest(frame
, nb
, log
): 
 293     win 
= wx
.Panel(nb
, -1) 
 294     canvas 
= DragCanvas(win
, -1) 
 296     def onSize(evt
, panel
=win
, canvas
=canvas
):  
 297         canvas
.SetSize(panel
.GetSize()) 
 299     win
.Bind(wx
.EVT_SIZE
, onSize
) 
 302 #---------------------------------------------------------------------- 
 307 DragImage is used when you wish to drag an object on the screen, and a simple  
 308 cursor is not enough. 
 310 On Windows, the WIN32 API is used to do achieve smooth dragging. On other  
 311 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use  
 312 <code>GenericDragImage</code> on Windows, too. 
 314 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all  
 315 platforms, but uses the <code>DragImage</code> name. 
 317 To use this class, when you wish to start dragging an image, create a  
 318 <code>DragImage</code> object and store it somewhere you can access it as the  
 319 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move  
 320 the image, initially call Show and then Move. If you wish to update the screen  
 321 contents during the drag (for example, highlight an item as in the example), first  
 322 call Hide, update the screen, call Move, and then call Show. 
 324 You can drag within one window, or you can use full-screen dragging either across  
 325 the whole screen, or just restricted to one area of the screen to save resources.  
 326 If you want the user to drag between two windows, then you will need to use  
 327 full-screen dragging. 
 332 if __name__ 
== '__main__': 
 335     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])