Какой самый простой способ создать фасонное окно в wxPython?
Я хотел бы создать простое окно формы в wxPython. Более или менее я хочу сделать wx, эквивалентный self.overrideredirect(1) Tkinter (он избавляется от границы ОС по умолчанию), а затем закруглить углы в окне.
2 ответа
В демонстрациях wxPython есть демонстрация рамочной формы. Я прошу прощения за косвенный источник. Они изначально пришли как установщик Windows здесь:
Возможно, вы захотите взглянуть на shape_frame_mobile.py или shape_frame.py, которые оба вызывают images.py из этого списка для растрового изображения окна примера. Это не точный эквивалент overrideredirect
так как вам придется предоставить изображение, которое будет нарисовано для кадра, но оно все равно может помочь вам сделать что-то подобное.
Важными частями являются функции, которые устанавливают форму окна на основе растрового изображения и обрабатывают событие wx.EVT_PAINT:
def SetWindowShape(self, evt=None):
r = wx.RegionFromBitmap(self.bmp)
self.hasShape = self.SetShape(r)
def OnPaint(self, evt):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
Редактировать - вот измененный shaped_frame_mobile.py
загружает изображение.png, указанное в переменной IMAGE_PATH. Измените это, чтобы указать на ваше изображение:
import wx
# Create a .png image with something drawn on a white background
# and put the path to it here.
IMAGE_PATH = '/python26/projects/shapedwin/image.png'
class ShapedFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Shaped Window",
style = wx.FRAME_SHAPED | wx.SIMPLE_BORDER )
self.hasShape = False
self.delta = wx.Point(0,0)
# Load the image
image = wx.Image(IMAGE_PATH, wx.BITMAP_TYPE_PNG)
image.SetMaskColour(255,255,255)
image.SetMask(True)
self.bmp = wx.BitmapFromImage(image)
self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
dc = wx.ClientDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
self.SetWindowShape()
self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_RIGHT_UP, self.OnExit)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
def SetWindowShape(self, evt=None):
r = wx.RegionFromBitmap(self.bmp)
self.hasShape = self.SetShape(r)
def OnDoubleClick(self, evt):
if self.hasShape:
self.SetShape(wx.Region())
self.hasShape = False
else:
self.SetWindowShape()
def OnPaint(self, evt):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
def OnExit(self, evt):
self.Close()
def OnLeftDown(self, evt):
self.CaptureMouse()
pos = self.ClientToScreen(evt.GetPosition())
origin = self.GetPosition()
self.delta = wx.Point(pos.x - origin.x, pos.y - origin.y)
def OnMouseMove(self, evt):
if evt.Dragging() and evt.LeftIsDown():
pos = self.ClientToScreen(evt.GetPosition())
newPos = (pos.x - self.delta.x, pos.y - self.delta.y)
self.Move(newPos)
def OnLeftUp(self, evt):
if self.HasCapture():
self.ReleaseMouse()
if __name__ == '__main__':
app = wx.PySimpleApp()
ShapedFrame().Show()
app.MainLoop()
Ребята, я знаю, что есть принятый ответ, я использовал этот ответ в ubuntu с python 2.x, однако, когда я попытался использовать его на Windows python 3.x, это не сработало. Поэтому я исправил это после небольшого исследования (wx.Region нужен прозрачный цвет, см. Код ниже). И поменял несколько амортизированных методов:
import wx
IMAGE_PATH = ".\Images\myImageFile.png"
class ShapedFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Shaped Window",
style = wx.FRAME_SHAPED | wx.SIMPLE_BORDER )
self.hasShape = False
self.delta = wx.Point(0,0)
# Load the image
self.bmp = wx.Image(IMAGE_PATH, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
#self.bmp = wx.Bitmap(image)
self.transparentColour = wx.Colour(255, 255, 255, alpha=wx.ALPHA_OPAQUE)
self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
dc = wx.ClientDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
self.SetWindowShape()
self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_RIGHT_UP, self.OnExit)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
def SetWindowShape(self, evt=None):
r = wx.Region(self.bmp , self.transparentColour)
self.hasShape = self.SetShape(r)
def OnDoubleClick(self, evt):
if self.hasShape:
self.SetShape(wx.Region())
self.hasShape = False
else:
self.SetWindowShape()
def OnPaint(self, evt):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0, True)
def OnExit(self, evt):
self.Close()
def OnLeftDown(self, evt):
self.CaptureMouse()
pos = self.ClientToScreen(evt.GetPosition())
origin = self.GetPosition()
self.delta = wx.Point(pos.x - origin.x, pos.y - origin.y)
def OnMouseMove(self, evt):
if evt.Dragging() and evt.LeftIsDown():
pos = self.ClientToScreen(evt.GetPosition())
newPos = (pos.x - self.delta.x, pos.y - self.delta.y)
self.Move(newPos)
def OnLeftUp(self, evt):
if self.HasCapture():
self.ReleaseMouse()
if __name__ == '__main__':
app = wx.App()
ShapedFrame().Show()
app.MainLoop()