]>
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         ##bmp = wx.Bitmap('bitmaps/toucan.png') 
  55         shape 
= DragShape(bmp
) 
  57         shape
.fullscreen 
= True 
  58         self
.shapes
.append(shape
) 
  60         # Make a shape from some text 
  62         bg_colour 
= wx
.Colour(57, 115, 57)  # matches the bg image 
  63         font 
= wx
.Font(15, wx
.ROMAN
, wx
.NORMAL
, wx
.BOLD
) 
  64         textExtent 
= self
.GetFullTextExtent(text
, font
) 
  66         # create a bitmap the same size as our text 
  67         bmp 
= wx
.EmptyBitmap(textExtent
[0], textExtent
[1]) 
  69         # 'draw' the text onto the bitmap 
  72         dc
.SetBackground(wx
.Brush(bg_colour
, wx
.SOLID
)) 
  74         dc
.SetTextForeground(wx
.RED
) 
  76         dc
.DrawText(text
, (0, 0)) 
  77         dc
.SelectObject(wx
.NullBitmap
) 
  78         mask 
= wx
.MaskColour(bmp
, bg_colour
) 
  80         shape 
= DragShape(bmp
) 
  82         shape
.text 
= "Some dragging text" 
  83         self
.shapes
.append(shape
) 
  86         # Make some shapes from some playing card images. 
  89         for card 
in ['_01c_', '_12h_', '_13d_', '_10s_']: 
  90             bmpFunc 
= getattr(images
, "get%sBitmap" % card
) 
  92             shape 
= DragShape(bmp
) 
  94             self
.shapes
.append(shape
) 
  98         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
) 
  99         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 100         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
) 
 101         self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
) 
 102         self
.Bind(wx
.EVT_MOTION
, self
.OnMotion
) 
 103         self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnLeaveWindow
) 
 106     # We're not doing anything here, but you might have reason to. 
 107     # for example, if you were dragging something, you might elect to 
 108     # 'drop it' when the cursor left the window. 
 109     def OnLeaveWindow(self
, evt
): 
 113     # tile the background bitmap 
 114     def TileBackground(self
, dc
): 
 115         sz 
= self
.GetClientSize() 
 116         w 
= self
.bg_bmp
.GetWidth() 
 117         h 
= self
.bg_bmp
.GetHeight() 
 125                 dc
.DrawBitmap(self
.bg_bmp
, (x
, y
)) 
 131     # Go through our list of shapes and draw them in whatever place they are. 
 132     def DrawShapes(self
, dc
): 
 133         for shape 
in self
.shapes
: 
 137     # This is actually a sophisticated 'hit test', but in this 
 138     # case we're also determining which shape, if any, was 'hit'. 
 139     def FindShape(self
, pt
): 
 140         for shape 
in self
.shapes
: 
 141             if shape
.HitTest(pt
): 
 145     # Remove a shape from the display 
 146     def EraseShape(self
, shape
, dc
): 
 148         dc
.SetClippingRect(r
) 
 149         self
.TileBackground(dc
) 
 151         dc
.DestroyClippingRegion() 
 153     # Clears the background, then redraws it. If the DC is passed, then 
 154     # we only do so in the area so designated. Otherwise, it's the whole thing. 
 155     def OnEraseBackground(self
, evt
): 
 159             dc 
= wxClientDC(self
) 
 160             rect 
= self
.GetUpdateRegion().GetBox() 
 161             dc
.SetClippingRect(rect
) 
 162         self
.TileBackground(dc
) 
 164     # Fired whenever a paint event occurs 
 165     def OnPaint(self
, evt
): 
 166         dc 
= wx
.PaintDC(self
) 
 170     # Left mouse button is down. 
 171     def OnLeftDown(self
, evt
): 
 172         # Did the mouse go down on one of our shapes? 
 173         shape 
= self
.FindShape(evt
.GetPosition()) 
 175         # If a shape was 'hit', then set that as the shape we're going to 
 176         # drag around. Get our start position. Dragging has not yet started. 
 177         # That will happen once the mouse moves, OR the mouse is released. 
 179             self
.dragShape 
= shape
 
 180             self
.dragStartPos 
= evt
.GetPosition() 
 182     # Left mouse button up. 
 183     def OnLeftUp(self
, evt
): 
 184         if not self
.dragImage 
or not self
.dragShape
: 
 185             self
.dragImage 
= None 
 186             self
.dragShape 
= None 
 189         # Hide the image, end dragging, and nuke out the drag image. 
 190         self
.dragImage
.Hide() 
 191         self
.dragImage
.EndDrag() 
 192         self
.dragImage 
= None 
 194         dc 
= wx
.ClientDC(self
) 
 197             self
.hiliteShape
.Draw(dc
) 
 198             self
.hiliteShape 
= None 
 200         # reposition and draw the shape 
 202         # Note by jmg 11/28/03  
 203         # Here's the original: 
 205         # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos 
 207         # So if there are any problems associated with this, use that as 
 208         # a starting place in your investigation. I've tried to simulate the 
 209         # wx.Point __add__ method here -- it won't work for tuples as we 
 210         # have now from the various methods 
 212         # There must be a better way to do this :-) 
 215         self
.dragShape
.pos 
= ( 
 216             self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0], 
 217             self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1] 
 220         self
.dragShape
.shown 
= True 
 221         self
.dragShape
.Draw(dc
) 
 222         self
.dragShape 
= None 
 224     # The mouse is moving 
 225     def OnMotion(self
, evt
): 
 226         # Ignore mouse movement if we're not dragging. 
 227         if not self
.dragShape 
or not evt
.Dragging() or not evt
.LeftIsDown(): 
 230         # if we have a shape, but haven't started dragging yet 
 231         if self
.dragShape 
and not self
.dragImage
: 
 233             # only start the drag after having moved a couple pixels 
 235             pt 
= evt
.GetPosition() 
 236             dx 
= abs(pt
.x 
- self
.dragStartPos
.x
) 
 237             dy 
= abs(pt
.y 
- self
.dragStartPos
.y
) 
 238             if dx 
<= tolerance 
and dy 
<= tolerance
: 
 241             # erase the shape since it will be drawn independently now 
 242             dc 
= wx
.ClientDC(self
) 
 243             self
.dragShape
.shown 
= False 
 244             self
.EraseShape(self
.dragShape
, dc
) 
 247             if self
.dragShape
.text
: 
 248                 self
.dragImage 
= wx
.DragString(self
.dragShape
.text
, 
 249                                               wx
.StockCursor(wx
.CURSOR_HAND
)) 
 251                 self
.dragImage 
= wx
.DragImage(self
.dragShape
.bmp
, 
 252                                              wx
.StockCursor(wx
.CURSOR_HAND
)) 
 254             hotspot 
= self
.dragStartPos 
- self
.dragShape
.pos
 
 255             self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
) 
 257             self
.dragImage
.Move(pt
) 
 258             self
.dragImage
.Show() 
 261         # if we have shape and image then move it, posibly highlighting another shape. 
 262         elif self
.dragShape 
and self
.dragImage
: 
 263             onShape 
= self
.FindShape(evt
.GetPosition()) 
 267             # figure out what to hilite and what to unhilite 
 269                 if onShape 
is None or self
.hiliteShape 
is not onShape
: 
 272             if onShape 
and onShape 
is not self
.hiliteShape 
and onShape
.shown
: 
 275             # if needed, hide the drag image so we can update the window 
 276             if unhiliteOld 
or hiliteNew
: 
 277                 self
.dragImage
.Hide() 
 280                 dc 
= wx
.ClientDC(self
) 
 281                 self
.hiliteShape
.Draw(dc
) 
 282                 self
.hiliteShape 
= None 
 285                 dc 
= wx
.ClientDC(self
) 
 286                 self
.hiliteShape 
= onShape
 
 287                 self
.hiliteShape
.Draw(dc
, wx
.INVERT
) 
 289             # now move it and show it again if needed 
 290             self
.dragImage
.Move(evt
.GetPosition()) 
 291             if unhiliteOld 
or hiliteNew
: 
 292                 self
.dragImage
.Show() 
 295 #---------------------------------------------------------------------- 
 297 def runTest(frame
, nb
, log
): 
 299     win 
= wx
.Panel(nb
, -1) 
 300     canvas 
= DragCanvas(win
, -1) 
 302     def onSize(evt
, panel
=win
, canvas
=canvas
):  
 303         canvas
.SetSize(panel
.GetSize()) 
 305     win
.Bind(wx
.EVT_SIZE
, onSize
) 
 308 #---------------------------------------------------------------------- 
 313 DragImage is used when you wish to drag an object on the screen, and a simple  
 314 cursor is not enough. 
 316 On Windows, the WIN32 API is used to do achieve smooth dragging. On other  
 317 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use  
 318 <code>GenericDragImage</code> on Windows, too. 
 320 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all  
 321 platforms, but uses the <code>DragImage</code> name. 
 323 To use this class, when you wish to start dragging an image, create a  
 324 <code>DragImage</code> object and store it somewhere you can access it as the  
 325 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move  
 326 the image, initially call Show and then Move. If you wish to update the screen  
 327 contents during the drag (for example, highlight an item as in the example), first  
 328 call Hide, update the screen, call Move, and then call Show. 
 330 You can drag within one window, or you can use full-screen dragging either across  
 331 the whole screen, or just restricted to one area of the screen to save resources.  
 332 If you want the user to drag between two windows, then you will need to use  
 333 full-screen dragging. 
 338 if __name__ 
== '__main__': 
 341     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])