]>
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
): 
 140     # Clears the background, then redraws it. If the DC is passed, then 
 141     # we only do so in the area so designated. Otherwise, it's the whole thing. 
 142     def OnEraseBackground(self
, evt
): 
 145             dc 
= wx
.ClientDC(self
) 
 146             rect 
= self
.GetUpdateRegion().GetBox() 
 147             dc
.SetClippingRect(rect
) 
 148         self
.TileBackground(dc
) 
 150     # Fired whenever a paint event occurs 
 151     def OnPaint(self
, evt
): 
 152         dc 
= wx
.PaintDC(self
) 
 156     # Left mouse button is down. 
 157     def OnLeftDown(self
, evt
): 
 158         # Did the mouse go down on one of our shapes? 
 159         shape 
= self
.FindShape(evt
.GetPosition()) 
 161         # If a shape was 'hit', then set that as the shape we're going to 
 162         # drag around. Get our start position. Dragging has not yet started. 
 163         # That will happen once the mouse moves, OR the mouse is released. 
 165             self
.dragShape 
= shape
 
 166             self
.dragStartPos 
= evt
.GetPosition() 
 168     # Left mouse button up. 
 169     def OnLeftUp(self
, evt
): 
 170         if not self
.dragImage 
or not self
.dragShape
: 
 171             self
.dragImage 
= None 
 172             self
.dragShape 
= None 
 175         # Hide the image, end dragging, and nuke out the drag image. 
 176         self
.dragImage
.Hide() 
 177         self
.dragImage
.EndDrag() 
 178         self
.dragImage 
= None 
 181             self
.RefreshRect(self
.hiliteShape
.GetRect()) 
 182             self
.hiliteShape 
= None 
 184         # reposition and draw the shape 
 186         # Note by jmg 11/28/03  
 187         # Here's the original: 
 189         # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos 
 191         # So if there are any problems associated with this, use that as 
 192         # a starting place in your investigation. I've tried to simulate the 
 193         # wx.Point __add__ method here -- it won't work for tuples as we 
 194         # have now from the various methods 
 196         # There must be a better way to do this :-) 
 199         self
.dragShape
.pos 
= ( 
 200             self
.dragShape
.pos
[0] + evt
.GetPosition()[0] - self
.dragStartPos
[0], 
 201             self
.dragShape
.pos
[1] + evt
.GetPosition()[1] - self
.dragStartPos
[1] 
 204         self
.dragShape
.shown 
= True 
 205         self
.RefreshRect(self
.dragShape
.GetRect()) 
 206         self
.dragShape 
= None 
 209     # The mouse is moving 
 210     def OnMotion(self
, evt
): 
 211         # Ignore mouse movement if we're not dragging. 
 212         if not self
.dragShape 
or not evt
.Dragging() or not evt
.LeftIsDown(): 
 215         # if we have a shape, but haven't started dragging yet 
 216         if self
.dragShape 
and not self
.dragImage
: 
 218             # only start the drag after having moved a couple pixels 
 220             pt 
= evt
.GetPosition() 
 221             dx 
= abs(pt
.x 
- self
.dragStartPos
.x
) 
 222             dy 
= abs(pt
.y 
- self
.dragStartPos
.y
) 
 223             if dx 
<= tolerance 
and dy 
<= tolerance
: 
 226             # refresh the area of the window where the shape was so it 
 228             self
.dragShape
.shown 
= False 
 229             self
.RefreshRect(self
.dragShape
.GetRect(), True) 
 232             if self
.dragShape
.text
: 
 233                 self
.dragImage 
= wx
.DragString(self
.dragShape
.text
, 
 234                                               wx
.StockCursor(wx
.CURSOR_HAND
)) 
 236                 self
.dragImage 
= wx
.DragImage(self
.dragShape
.bmp
, 
 237                                              wx
.StockCursor(wx
.CURSOR_HAND
)) 
 239             hotspot 
= self
.dragStartPos 
- self
.dragShape
.pos
 
 240             self
.dragImage
.BeginDrag(hotspot
, self
, self
.dragShape
.fullscreen
) 
 242             self
.dragImage
.Move(pt
) 
 243             self
.dragImage
.Show() 
 246         # if we have shape and image then move it, posibly highlighting another shape. 
 247         elif self
.dragShape 
and self
.dragImage
: 
 248             onShape 
= self
.FindShape(evt
.GetPosition()) 
 252             # figure out what to hilite and what to unhilite 
 254                 if onShape 
is None or self
.hiliteShape 
is not onShape
: 
 257             if onShape 
and onShape 
is not self
.hiliteShape 
and onShape
.shown
: 
 260             # if needed, hide the drag image so we can update the window 
 261             if unhiliteOld 
or hiliteNew
: 
 262                 self
.dragImage
.Hide() 
 265                 dc 
= wx
.ClientDC(self
) 
 266                 self
.hiliteShape
.Draw(dc
) 
 267                 self
.hiliteShape 
= None 
 270                 dc 
= wx
.ClientDC(self
) 
 271                 self
.hiliteShape 
= onShape
 
 272                 self
.hiliteShape
.Draw(dc
, wx
.INVERT
) 
 274             # now move it and show it again if needed 
 275             self
.dragImage
.Move(evt
.GetPosition()) 
 276             if unhiliteOld 
or hiliteNew
: 
 277                 self
.dragImage
.Show() 
 280 #---------------------------------------------------------------------- 
 282 def runTest(frame
, nb
, log
): 
 284     win 
= wx
.Panel(nb
, -1) 
 285     canvas 
= DragCanvas(win
, -1) 
 287     def onSize(evt
, panel
=win
, canvas
=canvas
):  
 288         canvas
.SetSize(panel
.GetSize()) 
 290     win
.Bind(wx
.EVT_SIZE
, onSize
) 
 293 #---------------------------------------------------------------------- 
 298 DragImage is used when you wish to drag an object on the screen, and a simple  
 299 cursor is not enough. 
 301 On Windows, the WIN32 API is used to do achieve smooth dragging. On other  
 302 platforms, <code>GenericDragImage</code> is used. Applications may also prefer to use  
 303 <code>GenericDragImage</code> on Windows, too. 
 305 <b>wxPython note</b>: wxPython uses <code>GenericDragImage</code> on all  
 306 platforms, but uses the <code>DragImage</code> name. 
 308 To use this class, when you wish to start dragging an image, create a  
 309 <code>DragImage</code> object and store it somewhere you can access it as the  
 310 drag progresses. Call BeginDrag to start, and EndDrag to stop the drag. To move  
 311 the image, initially call Show and then Move. If you wish to update the screen  
 312 contents during the drag (for example, highlight an item as in the example), first  
 313 call Hide, update the screen, call Move, and then call Show. 
 315 You can drag within one window, or you can use full-screen dragging either across  
 316 the whole screen, or just restricted to one area of the screen to save resources.  
 317 If you want the user to drag between two windows, then you will need to use  
 318 full-screen dragging. 
 323 if __name__ 
== '__main__': 
 326     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])