Python drawing on screen
Question: I'm coding an application that needs to select an area of the screen. I need
to change the cursor to a cross and then draw a rectangle on the user
selection. The first thing I searched for is how to manipulate the cursor and
I came across wxPython. With wxPython I could easily do this on a Frame with a
Panel, the thing is that I'd need the window to be transparent so the user can
see his screen while is selecting the desired area, but if I make the Frame
and the Panel objects transparent everything gets buggy.

So, I'm open to any solution, either using wxPython or not using it because I
don't really know if I'm using it right.

I'm new to Python and I'm not a native english speaker, so I'm sorry if you
can't understand something.

This is what I coded

    
    
    import wx
    
    class SelectableFrame(wx.Frame):
    
        c1 = None
        c2 = None
    
        def __init__(self, parent=None, id=-1, title=""):
            wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize(), style=wx.TRANSPARENT_WINDOW)
    
            self.panel = wx.Panel(self, size=self.GetSize(), style=wx.TRANSPARENT_WINDOW)
    
            self.panel.Bind(wx.EVT_MOTION, self.OnMouseMove)
            self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
            self.panel.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
            self.panel.Bind(wx.EVT_PAINT, self.OnPaint)
    
            self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
    
        def OnMouseMove(self, event):
            if event.Dragging() and event.LeftIsDown():
                self.c2 = event.GetPosition()
                self.Refresh()
    
        def OnMouseDown(self, event):
            self.c1 = event.GetPosition()
    
        def OnMouseUp(self, event):
            self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
    
        def OnPaint(self, event):
            if self.c1 is None or self.c2 is None: return
    
            dc = wx.PaintDC(self.panel)
            dc.SetPen(wx.Pen('red', 1))
            dc.SetBrush(wx.Brush(wx.Color(0, 0, 0), wx.TRANSPARENT))
    
            dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
    
        def PrintPosition(self, pos):
            return str(pos.x) + " " + str(pos.y)
    
    
    class MyApp(wx.App):
    
        def OnInit(self):
            frame = SelectableFrame()
            frame.Show(True)
            self.SetTopWindow(frame)
    
            return True
    
    
    
    app = MyApp(0)
    app.MainLoop()
    


Answer: You shouldn't be using wx.TRANSPARENT in window creation, that is mostly used
for wxDC paint commands. To make a window transparent just call
win.SetTransparent(amount), where amount is from 0-255, 255 means opaque, 0
means totally transparent. see <http://www.wxpython.org/docs/api/wx.Window-
class.html#SetTransparent>

I have modified your code, it will work only if your platform supports
transparent windows, you can check that by CanSetTransparent. I tested it on
windows XP.

    
    
    import wx
    
    class SelectableFrame(wx.Frame):
    
        c1 = None
        c2 = None
    
        def __init__(self, parent=None, id=-1, title=""):
            wx.Frame.__init__(self, parent, id, title, size=wx.DisplaySize())
    
            self.panel = wx.Panel(self, size=self.GetSize())
    
            self.panel.Bind(wx.EVT_MOTION, self.OnMouseMove)
            self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
            self.panel.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
            self.panel.Bind(wx.EVT_PAINT, self.OnPaint)
    
            self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
    
            self.SetTransparent(50)
    
        def OnMouseMove(self, event):
            if event.Dragging() and event.LeftIsDown():
                self.c2 = event.GetPosition()
                self.Refresh()
    
        def OnMouseDown(self, event):
            self.c1 = event.GetPosition()
    
        def OnMouseUp(self, event):
            self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
    
        def OnPaint(self, event):
            if self.c1 is None or self.c2 is None: return
    
            dc = wx.PaintDC(self.panel)
            dc.SetPen(wx.Pen('red', 1))
            dc.SetBrush(wx.Brush(wx.Color(0, 0, 0), wx.TRANSPARENT))
    
            dc.DrawRectangle(self.c1.x, self.c1.y, self.c2.x - self.c1.x, self.c2.y - self.c1.y)
    
        def PrintPosition(self, pos):
            return str(pos.x) + " " + str(pos.y)
    
    
    class MyApp(wx.App):
    
        def OnInit(self):
            frame = SelectableFrame()
            frame.Show(True)
            self.SetTopWindow(frame)
    
            return True
    
    
    app = MyApp(0)
    app.MainLoop()
    

