我想创建一个带有可见边框的透明框架。我根据hasenj的'shape-frame'(http://hasenj.wordpress.com/2009/04/14/making-a-fancy-window-in-wxpython/)的工作编写的代码如下。但我仍然有问题。我一定错过了什么。有人能指出这个程序有什么问题吗?感谢。
import wx
class FancyFrame(wx.Frame):
def __init__(self, width, height):
wx.Frame.__init__(self, None, style = wx.STAY_ON_TOP |
wx.FRAME_NO_TASKBAR | wx.FRAME_SHAPED,
size=(width, height))
self.SetTransparent(50)
b = wx.EmptyBitmap(width, height)
dc = wx.MemoryDC()
dc.SelectObject(b)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetPen(wx.Pen('red', 2))
dc.DrawRectangle(0, 0, width, height)
dc.SelectObject(wx.NullBitmap)
self.SetShape(wx.RegionFromBitmap(b))
self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
self.Show(True)
def OnKeyDown(self, event):
"""quit if user pressEsc"""
if event.GetKeyCode() == 27: #27 is the Esc key
self.Close(force=True)
else:
event.Skip()
if __name__ == "__main__":
app = wx.App()
FancyFrame(300, 300)
app.MainLoop()
答案 0 :(得分:2)
在MainLoop之外绘制东西并不是一个好主意。你应该设置你的wx应用程序,因为它是事件驱动的。应处理事件EVT_PAINT和EVT_SIZE。 wx.Timer
可用于基本移动。
import wx
#=============================================================================
class DrawPanelDB(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
self.ballPosition = [20, 20]
self.ballDelta = [1, 1]
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTime, self.timer)
self.timer.Start(20)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
#-------------------------------------------------------------------------
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
dc.SetBackground(wx.Brush(wx.BLACK))
dc.Clear()
dc.DrawCirclePoint(self.ballPosition, 20)
#-------------------------------------------------------------------------
def OnSize(self, event):
self.Refresh()
self.Update()
#-------------------------------------------------------------------------
def OnEraseBackground(self, event):
pass # Or None
#-------------------------------------------------------------------------
def OnTime(self, event):
self.ballPosition[0] += self.ballDelta[0]
self.ballPosition[1] += self.ballDelta[1]
w, h = self.GetClientSizeTuple()
if self.ballPosition[0] > w:
self.ballPosition[0] = w
self.ballDelta[0] *= -1
if self.ballPosition[1] > h:
self.ballPosition[1] = h
self.ballDelta[1] *= -1
if self.ballPosition[0] < 0:
self.ballPosition[0] = 0
self.ballDelta[0] *= -1
if self.ballPosition[1] < 0:
self.ballPosition[1] = 0
self.ballDelta[1] *= -1
self.Refresh()
#=============================================================================
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = DrawPanelDB(self)
self.Show()
#=============================================================================
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
编辑:使用xor函数进行不可破坏绘图的ScreenDC示例。
import wx
#=============================================================================
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.ballPosition = [20, 20]
self.lastPosition = None
self.ballDelta = [1, 1]
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTime, self.timer)
self.timer.Start(20)
#-------------------------------------------------------------------------
def OnTime(self, event):
self.ballPosition[0] += self.ballDelta[0]
self.ballPosition[1] += self.ballDelta[1]
w, h = wx.DisplaySize()
if self.ballPosition[0] > w:
self.ballPosition[0] = w
self.ballDelta[0] *= -1
if self.ballPosition[1] > h:
self.ballPosition[1] = h
self.ballDelta[1] *= -1
if self.ballPosition[0] < 0:
self.ballPosition[0] = 0
self.ballDelta[0] *= -1
if self.ballPosition[1] < 0:
self.ballPosition[1] = 0
self.ballDelta[1] *= -1
dc = wx.ScreenDC()
dc.StartDrawingOnTop()
dc.SetLogicalFunction(wx.XOR)
if self.lastPosition is not None:
dc.DrawRectangle(self.lastPosition[0], self.lastPosition[1], 15, 15)
self.lastPosition = (self.ballPosition[0], self.ballPosition[1])
dc.DrawRectangle(self.ballPosition[0], self.ballPosition[1], 15, 15)
dc.EndDrawingOnTop()
#=============================================================================
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
编辑:另一种可能性是保留该部分屏幕的备份副本。
import wx
#=============================================================================
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.ballPosition = [20, 20]
self.lastPosition = None
self.ballDelta = [1, 1]
self.patch = wx.EmptyBitmap(20, 20)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTime, self.timer)
self.timer.Start(20)
#-------------------------------------------------------------------------
def OnTime(self, event):
self.ballPosition[0] += self.ballDelta[0]
self.ballPosition[1] += self.ballDelta[1]
w, h = wx.DisplaySize()
if self.ballPosition[0] > w:
self.ballPosition[0] = w
self.ballDelta[0] *= -1
if self.ballPosition[1] > h:
self.ballPosition[1] = h
self.ballDelta[1] *= -1
if self.ballPosition[0] < 0:
self.ballPosition[0] = 0
self.ballDelta[0] *= -1
if self.ballPosition[1] < 0:
self.ballPosition[1] = 0
self.ballDelta[1] *= -1
dc = wx.ScreenDC()
dc.StartDrawingOnTop()
bdc = wx.MemoryDC(self.patch)
if self.lastPosition is not None:
dc.Blit(self.lastPosition[0] - 2, self.lastPosition[1] - 2, 20, 20, bdc, 0, 0)
bdc.Blit(0, 0, 20, 20, dc, self.ballPosition[0] - 2, self.ballPosition[1] - 2)
self.lastPosition = (self.ballPosition[0], self.ballPosition[1])
dc.DrawRectangle(self.ballPosition[0], self.ballPosition[1], 15, 15)
dc.EndDrawingOnTop()
#=============================================================================
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
答案 1 :(得分:0)
我建议您创建一个透明窗口(window.SetTransparent(0)
),并在其上放置一个您自己绘制的位图(例如,请参阅this answer)。
然后,您将为鼠标移动设置一个事件处理程序,并使用光标在窗口中移动。还要设置一个计时器,这样如果鼠标不移动x秒,你就可以淡出位图。