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