wxpython制作splash记录

用wxpython制作启动画面。

资料收集阶段:

https://wiki.wxpython.org/Customized%20splash%20screen%20%28Phoenix%29

这个里面的例子很全,而且直接可用。主要问题在于,本文主要解决这些问题。

1)都是超过某个时间后,splash自动消失,而此时应用可能还没有启动完全。

 2) splash界面上按鼠标左键 splash画面直接退出。虽然已经将一些鼠标事件注释掉,但还是不行。

 3) spalsh 退出的出口不唯一,导致整个wx应用不能全部退出

4) 将应用到的图像一起打包成exe并尽量压缩。

采用的是其中一个代码,目前和原始代码相比,注释掉了一部分。

 

  如下这个帖子里面实例了os.spawn的情况 https://wiki.wxpython.org/Splash%20screen%20while%20loading%20%28Phoenix%29

 

这个例子示例了最简单的应用: https://dzone.com/

 

# sample_four.py

import os
import sys
import wx
from wx.adv import Animation, AnimationCtrl

# class MyFrame
# class MyCaptionBox
# class MyPanel
# class MySplash
# class MyApp

#---------------------------------------------------------------------------

class MyFrame(wx.Frame):
    """
    ...
    """
    def __init__(self):
        super(MyFrame, self).__init__(None,
                                      -1,
                                      title="")

        #------------

        # Return application name.
        self.app_name = wx.GetApp().GetAppName()
        # Return icons folder.
        self.icons_dir = wx.GetApp().GetIconsDir()

        #------------

        # Simplified init method.
        self.SetProperties()
        self.CreateCtrls()
        self.BindEvents()
        self.DoLayout()

        #------------

        self.CenterOnScreen(wx.BOTH)

        #------------

        self.Show(True)

    #-----------------------------------------------------------------------

    def SetProperties(self):
        """
        ...
        """

        self.SetTitle(self.app_name)
        self.SetSize((340, 250))

        #------------

        # frameIcon = wx.Icon(os.path.join(self.icons_dir,
                                         # "icon_wxWidgets.ico"),
                            # type=wx.BITMAP_TYPE_ICO)
        # self.SetIcon(frameIcon)


    def CreateCtrls(self):
        """
        ...
        """

        # Create a panel.
        self.panel = wx.Panel(self, -1)

        #------------

        # Add a buttons.
        self.btnClose = wx.Button(self.panel,
                                  -1,
                                  "&Close")


    def BindEvents(self):
        """
        Bind some events to an events handler.
        """

        # Bind events to an events handler.
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        self.Bind(wx.EVT_BUTTON, self.OnCloseMe, self.btnClose)


    def DoLayout(self):
        """
        ...
        """

        # MainSizer is the top-level one that manages everything.
        mainSizer = wx.BoxSizer(wx.VERTICAL)

        # wx.BoxSizer(window, proportion, flag, border)
        # wx.BoxSizer(sizer, proportion, flag, border)
        mainSizer.Add(self.btnClose, 1, wx.EXPAND | wx.ALL, 10)

        # Finally, tell the panel to use the sizer for layout.
        self.panel.SetAutoLayout(True)
        self.panel.SetSizer(mainSizer)

        mainSizer.Fit(self.panel)


    def OnCloseMe(self, event):
        """
        ...
        """

        self.Close(True)


    def OnCloseWindow(self, event):
        """
        ...
        """

        self.Destroy()

#---------------------------------------------------------------------------

class MyCaptionBox(wx.Panel):
    """
    ...
    """
    def __init__(self, parent, caption):
        super(MyCaptionBox, self).__init__(parent,
                                           style=wx.NO_BORDER |
                                                 wx.TAB_TRAVERSAL)

        #------------

        self.SetBackgroundColour("white")

        #------------

        # Attributes.
        self._caption = caption
        self._csizer = wx.BoxSizer(wx.VERTICAL)

        #------------

        # Simplified init method.
        self.BindEvents()
        self.DoLayout()

    #-----------------------------------------------------------------------

    def BindEvents(self):
        """
        ...
        """

        # Bind events to an events handler.
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def DoLayout(self):
        """
        ...
        """

        msizer = wx.BoxSizer(wx.HORIZONTAL)
        self._csizer.AddSpacer(15) # Extra space for caption.
        msizer.Add(self._csizer, 0, wx.EXPAND)
        self.SetSizer(msizer)


    def DoGetBestSize(self):
        """
        ...
        """

        size = super(MyCaptionBox, self).DoGetBestSize()
        # Compensate for wide caption labels.
        tw = self.GetTextExtent(self._caption)[0]
        size.SetWidth(max(size.width, tw))
        return size


    def AddItem(self, item):
        """
        Add a window or sizer item to the caption box.
        """

        self._csizer.Add(item, 0, wx.ALL, 10)


    def OnPaint(self, event):
        """
        Draws the Caption and border around the controls.
        """

        dc = wx.BufferedPaintDC(self)
        dc.SetBackground(wx.Brush(wx.Colour(255, 255, 255, 255)))
        dc.Clear()
        gcdc = wx.GCDC(dc)
        dc.Clear()

        # Get the working rectangle we can draw in.
        rect = self.GetClientRect()

        # Get the sytem color to draw the caption.
        ss = wx.SystemSettings
        color = ss.GetColour(wx.SYS_COLOUR_3DDKSHADOW)
        gcdc.SetTextForeground(wx.BLACK)

        # Draw the border.
        rect.Inflate(-0, -0)
        gcdc.SetPen(wx.Pen(color))
        gcdc.SetBrush(wx.Brush(wx.Colour(52, 64, 80, 255)))

        # Font size and style.
        font = self.GetFont().GetPointSize()
        font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
        font.SetWeight(wx.BOLD)

        # Add the Caption.
        rect = wx.Rect(rect.x, rect.y, rect.width, 20)
        rect.Inflate(-5, 0)
        gcdc.SetFont(font)
        gcdc.DrawLabel(self._caption, rect, wx.ALIGN_CENTER)

#---------------------------------------------------------------------------

class MyPanel(wx.Panel):
    """
    ...
    """
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        #------------

        self.SetBackgroundColour("white")

        #------------

        # Return bitmaps folder.
        self.bitmaps_dir = wx.GetApp().GetBitmapsDir()

        # Load a background bitmap.
        self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
                                          "gloss.png"),
                             type=wx.BITMAP_TYPE_PNG)

        #------------

        # Attributes.
        self.box1 = MyCaptionBox(self, "Loading...")

        #------------

        # Pick the filename of an animated GIF file you have ...
        # Give it the full path and file name.
        animatedGif = Animation(os.path.join(self.bitmaps_dir,
                                             "loader.gif"))
        self.ag = AnimationCtrl(self.box1,
                                -1,
                                animatedGif)

        # Clears the background.
        self.ag.SetBackgroundColour(self.GetBackgroundColour())

        # Continuously loop through the frames of
        # the gif file (default).
        self.ag.Play()

        self.box1.AddItem(self.ag)

        #------------

        # Simplified init method.
        self.BindEvents()
        self.DoLayout()

        #------------

        self.SetClientSize((262, 282))
        #self.SetClientSize((800, 534))

    #-----------------------------------------------------------------------

    def BindEvents(self):
        """
        ...
        """

        # Bind some events to an events handler.
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
        #如下已经 不和鼠标事件绑定,但是按左键还会退出。怀疑基类的默认行为 。
        # self.box1.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)
        # self.ag.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvents)


    def DoLayout(self):
        """
        ...
        """

        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        vsizer = wx.BoxSizer(wx.VERTICAL)

        #------------

        # Add the box to the panel.
        hsizer.AddStretchSpacer()
        hsizer.Add(self.box1, 0, wx.ALIGN_CENTER)
        vsizer.AddStretchSpacer(40)
        vsizer.Add(hsizer, 0, wx.ALIGN_CENTER)
        vsizer.AddStretchSpacer()

        self.SetSizer(vsizer)


    def OnPaint(self, event):
        """
        ...
        """

        dc = wx.BufferedPaintDC(self)
        dc.Clear()
        gcdc = wx.GCDC(dc)
        gcdc.Clear()

        # Draw a bitmap with an alpha channel
        # on top of the last group.
        gcdc.DrawBitmap(self.bmp, 0, 0, False)


    def OnMouseEvents(self, event):
        """
        Handles the wx.EVT_MOUSE_EVENTS for AdvancedSplash.
        This reproduces the behavior of wx.SplashScreen.
        """

        if event.LeftDown() or event.RightDown():
            splash = wx.GetApp().GetTopWindow()
            #splash.OnClose(event)

        event.Skip()


    def OnDestroy(self, event):
        """
        ...
        """

        event.Skip()

#---------------------------------------------------------------------------

class MySplash(wx.Frame):
    """
    ...
    """
    def __init__(self):

        #--------------

        screen = wx.ScreenDC()

        # Screen size.
        ws, hs = screen.GetSize()

        #------------

        # Return bitmaps folder.
        self.bitmaps_dir = wx.GetApp().GetBitmapsDir()

        # Load a background bitmap.
        self.bmp = wx.Bitmap(os.path.join(self.bitmaps_dir,
                                          "gloss.png"),
                             type=wx.BITMAP_TYPE_PNG)

        mask = wx.Mask(self.bmp, wx.RED)
        self.bmp.SetMask(mask)

        # Determine size of bitmap.
        wi, hi = self.bmp.GetWidth(), self.bmp.GetHeight()
        print("\n... Bitmap size : %sx%s px" % (wi, hi))

        x = int((ws-wi)/2)
        y = int((hs-hi)/2)

        #--------------

        super(MySplash, self).__init__(parent=None,
                                       id=-1,
                                       title="SplashScreen",
                                       pos=(x, y),
                                       size=(wi, hi),
                                       style=wx.FRAME_SHAPED |
                                             wx.BORDER_NONE |
                                             wx.FRAME_NO_TASKBAR |
                                             wx.STAY_ON_TOP)

        #--------------

        self.SetBackgroundColour("white")

        #--------------

        # Attributes.
        self.SetTransparent(0)
        self.opacity_in = 0
        self.deltaN = -30
        self.hasShape = False

        #--------------

        if wx.Platform != "__WXMAC__":
            # wxMac clips the tooltip to the window shape, YUCK!!!
            self.SetToolTip("Right-click to close the window\n"
                            "Double-click the image to set/unset the window shape")

        if wx.Platform == "__WXGTK__":
            # wxGTK requires that the window be created before you can
            # set its shape, so delay the call to SetWindowShape until
            # this event.
            self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
        else:
            # On wxMSW and wxMac the window has already
            # been created, so go for it.
            self.SetWindowShape()

        #--------------
        #以下注释掉,让splash一直运行,不退出,具体退出的实际在实际应用加载完毕后。
        # Starts the Timer. Once Expired, splash is Destroyed.
        self.timer = wx.Timer(self)

        # Simulate long startup time.
        # self.timer.Start(4000)

        # self.Bind(wx.EVT_TIMER, self.TimeOut, self.timer)

        #--------------

        # Show main frame after 3000 ms.
        # self.fc = wx.CallLater(3000, self.ShowMainFrame)

        #--------------

        self.CenterOnScreen(wx.BOTH)
        self.Show(True)

        #--------------

        # Simplified init method.
        self.OnTimerIn(self)
        self.CreateCtrls()
        self.DoLayout()

        #--------------

        print("\n... Display the splashScreen")

        #--------------

        self.SetClientSize((wi, hi))
        wx.BeginBusyCursor()

    #-----------------------------------------------------------------------

    def OnTimerIn(self, evt):
        """
        Thanks to Pascal Faut.
        """

        self.timer1 = wx.Timer(self, -1)
        self.timer1.Start(1)
        self.Bind(wx.EVT_TIMER, self.AlphaCycle1, self.timer1)

        print("Fade-in was launched.")


    def AlphaCycle1(self, *args):
        """
        Thanks to Pascal Faut.
        """

        self.opacity_in += self.deltaN
        if self.opacity_in <= 0:
            self.deltaN = -self.deltaN
            self.opacity_in = 0

        if self.opacity_in >= 255:
            self.deltaN = -self.deltaN
            self.opacity_in = 255

            self.timer1.Stop()

        self.SetTransparent(self.opacity_in)

        print("Fade in = {}/255".format(self.opacity_in))


    def CreateCtrls(self):
        """
        ...
        """


        self.panel = MyPanel(self)


    def BindEvents(self):
        """
        Bind all the events related to my app.
        """

        # Bind some events to an events handler.
        self.Bind(wx.EVT_CHAR, self.OnCharEvents)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.panel.Bind(wx.EVT_LEFT_DOWN, self.OnClose)
        self.Bind(wx.EVT_CLOSE, self.CloseWindow)


    def DoLayout(self):
        """
        ...
        """

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel, 1, wx.EXPAND, 20)
        self.SetSizer(sizer)


    def SetWindowShape(self, *evt):
        """
        ...
        """

        # Use the bitmap's mask to determine the region.
        r = wx.Region(self.bmp)
        self.hasShape = self.SetShape(r)


    def OnCharEvents(self, event):
        """
        Handles the wx.EVT_CHAR for Splash.
        This reproduces the behavior of wx.SplashScreen.
        """

        self.OnClose(event)


    def TimeOut(self, event):
        """
        ...
        """

        self.Close(True)


    def OnClose(self, event):
        """
        Handles the wx.EVT_CLOSE event for SplashScreen.
        """

        # Make sure the default handler runs
        # too so this window gets destroyed.
        # Tell the event system to continue
        # looking for an event handler, so the
        # default handler will get called.
        # event.Skip()  # ?????
        self.Hide()

        #------------

        # If the timer is still running then go
        # ahead and show the main frame now.
        # if self.fc.IsRunning():
            # # Stop the wx.CallLater timer.
            # # Stop the splash screen timer
            # # and close it.
            # self.fc.Stop()
            # self.ShowMainFrame()


    def ShowMainFrame(self):
        """
        ...
        """

        print("\n... Close the splash screen")
        print("\n... Create and display the main frame")

        #------------

        wx.CallAfter(wx.EndBusyCursor)

        #------------

        if self.fc.IsRunning():
            # Stop the splash screen
            # timer and close it.
            self.Raise()

        #------------

        # Create an instance of the MyFrame class.
        frame = MyFrame()


    def CloseWindow(self, event):
        """
        ...
        """

        self.timer.Stop()
        self.Destroy()

#---------------------------------------------------------------------------

class MyApp(wx.App):
    """
    ...
    """
    def OnInit(self):

        #------------

        self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)

        #------------

        self.SetAppName("Main frame")

        #------------

        self.installDir = os.path.split(os.path.abspath(sys.argv[0]))[0]

        #------------

        splash = MySplash()
        splash.BindEvents()
        splash.CenterOnScreen(wx.BOTH)

        return True

    #-----------------------------------------------------------------------

    def GetInstallDir(self):
        """
        Returns the installation directory for my application.
        """

        return self.installDir


    def GetIconsDir(self):
        """
        Returns the icons directory for my application.
        """

        # icons_dir = os.path.join(self.installDir, "icons")
        # return icons_dir


    def GetBitmapsDir(self):
        """
        Returns the bitmaps directory for my application.
        """

        bitmaps_dir = os.path.join(self.installDir, "bitmaps")
        return bitmaps_dir

#---------------------------------------------------------------------------

def main():
    app = MyApp(False)
    app.MainLoop()

#---------------------------------------------------------------------------

if __name__ == "__main__" :
    main()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的 wxPython 实现的数据库登录窗口示例: ```python import wx import pymysql class LoginFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, 'Database Login', size=(300, 200)) panel = wx.Panel(self, -1) vbox = wx.BoxSizer(wx.VERTICAL) hbox1 = wx.BoxSizer(wx.HORIZONTAL) self.host_label = wx.StaticText(panel, -1, 'Host:', size=(50, -1)) hbox1.Add(self.host_label, flag=wx.RIGHT, border=10) self.host_text = wx.TextCtrl(panel, -1, 'localhost') hbox1.Add(self.host_text, proportion=1) vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10) hbox2 = wx.BoxSizer(wx.HORIZONTAL) self.user_label = wx.StaticText(panel, -1, 'User:', size=(50, -1)) hbox2.Add(self.user_label, flag=wx.RIGHT, border=10) self.user_text = wx.TextCtrl(panel, -1, '') hbox2.Add(self.user_text, proportion=1) vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10) hbox3 = wx.BoxSizer(wx.HORIZONTAL) self.password_label = wx.StaticText(panel, -1, 'Password:', size=(50, -1)) hbox3.Add(self.password_label, flag=wx.RIGHT, border=10) self.password_text = wx.TextCtrl(panel, -1, '', style=wx.TE_PASSWORD) hbox3.Add(self.password_text, proportion=1) vbox.Add(hbox3, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10) hbox4 = wx.BoxSizer(wx.HORIZONTAL) self.database_label = wx.StaticText(panel, -1, 'Database:', size=(50, -1)) hbox4.Add(self.database_label, flag=wx.RIGHT, border=10) self.database_text = wx.TextCtrl(panel, -1, '') hbox4.Add(self.database_text, proportion=1) vbox.Add(hbox4, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10) hbox5 = wx.BoxSizer(wx.HORIZONTAL) self.connect_button = wx.Button(panel, -1, 'Connect') hbox5.Add(self.connect_button, flag=wx.RIGHT, border=10) self.cancel_button = wx.Button(panel, -1, 'Cancel') hbox5.Add(self.cancel_button) vbox.Add(hbox5, flag=wx.ALIGN_RIGHT|wx.RIGHT|wx.BOTTOM, border=10) panel.SetSizer(vbox) self.connect_button.Bind(wx.EVT_BUTTON, self.on_connect) self.cancel_button.Bind(wx.EVT_BUTTON, self.on_cancel) def on_connect(self, event): host = self.host_text.GetValue() user = self.user_text.GetValue() password = self.password_text.GetValue() database = self.database_text.GetValue() try: conn = pymysql.connect(host=host, user=user, password=password, database=database) print('Connected to database.') conn.close() except pymysql.Error as e: print('Error connecting to database:', e) def on_cancel(self, event): self.Close() if __name__ == '__main__': app = wx.App() frame = LoginFrame() frame.Show() app.MainLoop() ``` 在这个示例中,我们使用 wxPython 的各种布局管理器来创建一个简单的登录窗口,包括四个文本框和两个按钮,其中 Connect 按钮用于连接数据库,Cancel 按钮用于关闭窗口。 当用户单击 Connect 按钮时,我们通过 pymysql 模块连接到数据库。如果连接成功,则在控制台输出 "Connected to database.",否则输出错误消息。 注意,这个示例中的数据库连接是非常简单的,只是用于演示 wxPython 中如何创建登录窗口和连接到数据库。在实际应用中,需要根据实际需求进行更复杂的错误处理和安全措施。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

proware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值