Какой самый простой способ создать фасонное окно в 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()
Другие вопросы по тегам