]>
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:])