]>
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() 
  51         # Make a shape from an image and mask.  This one will demo 
  52         # dragging outside the window 
  53         bmp 
= images
.getTestStarBitmap() 
  54         shape 
= DragShape(bmp
) 
  56         shape
.fullscreen 
= True 
  57         self
.shapes
.append(shape
) 
  59         # Make a shape from some text 
  61         bg_colour 
= wx
.Colour(57, 115, 57)  # matches the bg image 
  62         font 
= wx
.Font(15, wx
.ROMAN
, wx
.NORMAL
, wx
.BOLD
) 
  63         textExtent 
= self
.GetFullTextExtent(text
, font
) 
  65         # create a bitmap the same size as our text 
  66         bmp 
= wx
.EmptyBitmap(textExtent
[0], textExtent
[1]) 
  68         # 'draw' the text onto the bitmap 
  71         dc
.SetBackground(wx
.Brush(bg_colour
, wx
.SOLID
)) 
  73         dc
.SetTextForeground(wx
.RED
) 
  75         dc
.DrawText(text
, (0, 0)) 
  76         dc
.SelectObject(wx
.NullBitmap
) 
  77         mask 
= wx
.MaskColour(bmp
, bg_colour
) 
  79         shape 
= DragShape(bmp
) 
  81         shape
.text 
= "Some dragging text" 
  82         self
.shapes
.append(shape
) 
  85         # Make some shapes from some playing card images. 
  88         for card 
in ['_01c_', '_12h_', '_13d_', '_10s_']: 
  89             bmpFunc 
= getattr(images
, "get%sBitmap" % card
) 
  91             shape 
= DragShape(bmp
) 
  93             self
.shapes
.append(shape
) 
  97         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
) 
  98         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
  99         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
) 
 100         self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
) 
 101         self
.Bind(wx
.EVT_MOTION
, self
.OnMotion
) 
 102         self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnLeaveWindow
) 
 105     # We're not doing anything here, but you might have reason to. 
 106     # for example, if you were dragging something, you might elect to 
 107     # 'drop it' when the cursor left the window. 
 108     def OnLeaveWindow(self
, evt
): 
 112     # tile the background bitmap 
 113     def TileBackground(self
, dc
): 
 114         sz 
= self
.GetClientSize() 
 115         w 
= self
.bg_bmp
.GetWidth() 
 116         h 
= self
.bg_bmp
.GetHeight() 
 124                 dc
.DrawBitmap(self
.bg_bmp
, (x
, y
)) 
 130     # Go through our list of shapes and draw them in whatever place they are. 
 131     def DrawShapes(self
, dc
): 
 132         for shape 
in self
.shapes
: 
 136     # This is actually a sophisticated 'hit test', but in this 
 137     # case we're also determining which shape, if any, was 'hit'. 
 138     def FindShape(self
, pt
): 
 139         for shape 
in self
.shapes
: 
 140             if shape
.HitTest(pt
): 
 144     # Remove a shape from the display 
 145     def EraseShape(self
, shape
, dc
): 
 147         dc
.SetClippingRect(r
) 
 148         self
.TileBackground(dc
) 
 150         dc
.DestroyClippingRegion() 
 152     # Clears the background, then redraws it. If the DC is passed, then 
 153     # we only do so in the area so designated. Otherwise, it's the whole thing. 
 154     def OnEraseBackground(self
, evt
): 
 158             dc 
= wxClientDC(self
) 
 159             rect 
= self
.GetUpdateRegion().GetBox() 
 160             dc
.SetClippingRect(rect
) 
 161         self
.TileBackground(dc
) 
 163     # Fired whenever a paint event occurs 
 164     def OnPaint(self
, evt
): 
 165         dc 
= wx
.PaintDC(self
) 
 169     # Left mouse button is down. 
 170     def OnLeftDown(self
, evt
): 
 171         # Did the mouse go down on one of our shapes? 
 172         shape 
= self
.FindShape(evt
.GetPosition()) 
 174         # If a shape was 'hit', then set that as the shape we're going to 
 175         # drag around. Get our start position. Dragging has not yet started. 
 176         # That will happen once the mouse moves, OR the mouse is released. 
 178             self
.dragShape 
= shape
 
 179             self
.dragStartPos 
= evt
.GetPosition() 
 181     # Left mouse button up. 
 182     def OnLeftUp(self
, evt
): 
 183         if not self
.dragImage 
or not self
.dragShape
: 
 184             self
.dragImage 
= None 
 185             self
.dragShape 
= None 
 188         # Hide the image, end dragging, and nuke out the drag image. 
 189         self
.dragImage
.Hide() 
 190         self
.dragImage
.EndDrag() 
 191         self
.dragImage 
= None 
 193         dc 
= wx
.ClientDC(self
) 
 196             self
.hiliteShape
.Draw(dc
) 
 197             self
.hiliteShape 
= None 
 199         # reposition and draw the shape 
 201         # Note by jmg 11/28/03  
 202         # Here's the original: 
 204         # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos 
 206         # So if there are any problems associated with this, use that as 
 207         # a starting place in your investigation. I've tried to simulate the 
 208         # wx.Point __add__ method here -- it won't work for tuples as we 
 209         # have now from the various methods 
 211         # There must be a better way to do this :-) 
 214         self
.dragShape
.pos 
= ( 
 215             self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0], 
 216             self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1] 
 219         self
.dragShape
.shown 
= True 
 220         self
.dragShape
.Draw(dc
) 
 221         self
.dragShape 
= None 
 223     # The mouse is moving 
 224     def OnMotion(self
, evt
): 
 225         # Ignore mouse movement if we're not dragging. 
 226         if not self
.dragShape 
or not evt
.Dragging() or not evt
.LeftIsDown(): 
 229         # if we have a shape, but haven't started dragging yet 
 230         if self
.dragShape 
and not self
.dragImage
: 
 232             # only start the drag after having moved a couple pixels 
 234             pt 
= evt
.GetPosition() 
 235             dx 
= abs(pt
.x 
- self
.dragStartPos
.x
) 
 236             dy 
= abs(pt
.y 
- self
.dragStartPos
.y
) 
 237             if dx 
<= tolerance 
and dy 
<= tolerance
: 
 240             # erase the shape since it will be drawn independently now 
 241             dc 
= wx
.ClientDC(self
) 
 242             self
.dragShape
.shown 
= False 
 243             self
.EraseShape(self
.dragShape
, dc
) 
 246             if self
.dragShape
.text
: 
 247                 self
.dragImage 
= wx
.DragString(self
.dragShape
.text
, 
 248                                               wx
.StockCursor(wx
.CURSOR_HAND
)) 
 250                 self
.dragImage 
= wx
.DragImage(self
.dragShape
.bmp
, 
 251                                              wx
.StockCursor(wx
.CURSOR_HAND
)) 
 253             hotspot 
= self
.dragStartPos 
- self
.dragShape
.pos
 
 254             self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
) 
 256             self
.dragImage
.Move(pt
) 
 257             self
.dragImage
.Show() 
 260         # if we have shape and image then move it, posibly highlighting another shape. 
 261         elif self
.dragShape 
and self
.dragImage
: 
 262             onShape 
= self
.FindShape(evt
.GetPosition()) 
 266             # figure out what to hilite and what to unhilite 
 268                 if onShape 
is None or self
.hiliteShape 
is not onShape
: 
 271             if onShape 
and onShape 
is not self
.hiliteShape 
and onShape
.shown
: 
 274             # if needed, hide the drag image so we can update the window 
 275             if unhiliteOld 
or hiliteNew
: 
 276                 self
.dragImage
.Hide() 
 279                 dc 
= wx
.ClientDC(self
) 
 280                 self
.hiliteShape
.Draw(dc
) 
 281                 self
.hiliteShape 
= None 
 284                 dc 
= wx
.ClientDC(self
) 
 285                 self
.hiliteShape 
= onShape
 
 286                 self
.hiliteShape
.Draw(dc
, wx
.INVERT
) 
 288             # now move it and show it again if needed 
 289             self
.dragImage
.Move(evt
.GetPosition()) 
 290             if unhiliteOld 
or hiliteNew
: 
 291                 self
.dragImage
.Show() 
 294 #---------------------------------------------------------------------- 
 296 def runTest(frame
, nb
, log
): 
 298     win 
= wx
.Panel(nb
, -1) 
 299     canvas 
= DragCanvas(win
, -1) 
 301     def onSize(evt
, panel
=win
, canvas
=canvas
):  
 302         canvas
.SetSize(panel
.GetSize()) 
 304     win
.Bind(wx
.EVT_SIZE
, onSize
) 
 307 #---------------------------------------------------------------------- 
 312 DragImage is used when you wish to drag an object on the screen, and a simple  
 313 cursor is not enough. 
 315 On Windows, the WIN32 API is used to do achieve smooth dragging. On other  
 316 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use  
 317 <code>GenericDragImage</code> on Windows, too. 
 319 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all  
 320 platforms, but uses the <code>DragImage</code> name. 
 322 To use this class, when you wish to start dragging an image, create a  
 323 <code>DragImage</code> object and store it somewhere you can access it as the  
 324 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move  
 325 the image, initially call Show and then Move. If you wish to update the screen  
 326 contents during the drag (for example, highlight an item as in the example), first  
 327 call Hide, update the screen, call Move, and then call Show. 
 329 You can drag within one window, or you can use full-screen dragging either across  
 330 the whole screen, or just restricted to one area of the screen to save resources.  
 331 If you want the user to drag between two windows, then you will need to use  
 332 full-screen dragging. 
 337 if __name__ 
== '__main__': 
 340     run
.main(['', os
.path
.basename(sys
.argv
[0])])