如何在我的python框架和任务栏图标之间进行通信

时间:2017-03-01 14:50:54

标签: python wxpython

情况

我是python和wxPython的新手,目前正在开发一个小型(仅限linux的目标)脚本,其中包含一个托盘图标(任务栏图标)和一个主窗口(Frame)。

我现在意识到一个问题,我不知道如何处理。

  • 左键单击我的托盘图标应该切换主UI的可见性(.Show()& .Hide()),但我不知道如何处理框架对象。
  • 左键单击当前正在触发 on_left_down 方法,该方法充当假人。

我试着尽量减少这篇文章的代码,希望它有所帮助。

代码

import wx

TRAY_TOOLTIP = 'demo'
TRAY_ICON = 'gfx/core/bt_appIcon_16.png'
appName = 'demo'
windowWidth=350
windowHeight=200

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(windowWidth,windowHeight), style=wx.NO_BORDER) # Frame without borders
        self.SetSizeHintsSz( wx.Size( windowWidth,windowHeight ), wx.Size( windowWidth,windowHeight ) ) # forcing min and max size to same values - prevents resizing option
        appIcon = wx.Icon('gfx/core/bt_appIcon_16.png', wx.BITMAP_TYPE_PNG)
        self.SetIcon(appIcon) # set an application icon
        # Preference button of main ui
        img_preferences = wx.Bitmap('gfx/core/bt_prefs_16.png', wx.BITMAP_TYPE_BMP)
        self.bt_preferences = wx.BitmapButton(self, id = wx.ID_ANY, style=wx.NO_BORDER, bitmap = img_preferences, size = (img_preferences.GetWidth()+10, img_preferences.GetHeight()+10))
        self.bt_preferences.SetLabel('Preferences')
        bSizer1 = wx.BoxSizer( wx.VERTICAL ) # define layout container
        bSizer1.Add( self.bt_preferences, 0, wx.ALIGN_RIGHT, 100) # preferences
        self.SetSizer( bSizer1 )
        self.Center() # open window centered
        self.bt_preferences.Bind(wx.EVT_BUTTON, self.OnClicked) 
        self.Show(True) # show main UI

    def OnClickedOptionButton(self, event): 
        self.launchExternalApplication()

    def OnClicked(self, event): 
        btn = event.GetEventObject().GetLabel() 
        if (btn =='Preferences'):
            print('clicked preference button in main-window/frame')

def create_menu_item(menu, label, func):
    item = wx.MenuItem(menu, -1, label)
    menu.Bind(wx.EVT_MENU, func, id=item.GetId())
    menu.AppendItem(item)
    return item

class TaskBarIcon(wx.TaskBarIcon, MyFrame):
    def __init__(self, frame):
        self.frame = frame
        super(TaskBarIcon, self).__init__()
        self.set_icon(TRAY_ICON)
        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_left_down)

    def CreatePopupMenu(self):
        menu = wx.Menu()
        create_menu_item(menu, 'Preferences', self.openPrefsFromMenu)
        create_menu_item(menu, 'Exit', self.on_exit)
        return menu

    def set_icon(self, path):
        icon = wx.IconFromBitmap(wx.Bitmap(path))
        self.SetIcon(icon, TRAY_TOOLTIP)

    def on_left_down(self, event):
        print('on_left_down of tray icon')
        # NEED HELP HERE
        # should check if main-window is visible or not
        # then toggle it

    def openPrefsFromMenu(self, event):
        print('open prefs from menu')

    def on_exit(self, event):
        wx.CallAfter(self.Destroy) # close the tray icon
        self.frame.Close()
        # AND SOME MORE HELP HERE
        # should close the main UI as well
        #exit()

class App(wx.App):
    def OnInit(self):
        frame=wx.Frame(None)
        self.SetTopWindow(frame)
        TaskBarIcon(frame)
        return True

def main():
    app = App(False)
    frame = MyFrame(None, appName)
    app.MainLoop()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:2)

首先,请查看this example,了解您要完成的工作样本。

这里有一些问题,

  • 您需要注册wx.EVT_CLOSE 并正确处理该结束活动。
  • 要为主框架设置样式,您应在默认样式之上应用 wx.NO_BORDER。否则,您的窗口根本不会最小化。
  • 在托盘图标的on_exit范围内,您应通过wx.CallAfter(self.frame.Close)
  • 指示主框架已关闭

有关上述提示的应用,请参阅以下代码:

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(windowWidth,windowHeight), style=wx.DEFAULT_FRAME_STYLE | wx.NO_BORDER) # Frame without borders
        self.tbicon = TaskBarIcon(self)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

    def OnCloseWindow(self, evt):
        self.tbicon.RemoveIcon()
        self.tbicon.Destroy()

        self.Destroy()
        wx.GetApp().ExitMainLoop()

        evt.Skip()

TaskBarIcon的修改:

class TaskBarIcon(wx.TaskBarIcon):
    def on_left_down(self, event):
        print('on_left_down of tray icon')
        if self.frame.IsIconized():
            self.frame.Iconize(False)
        if not self.frame.IsShown():
            self.frame.Show(True)
        self.frame.Raise()

    def openPrefsFromMenu(self, event):
        print('open prefs from menu')

    def on_exit(self, event):
        wx.CallAfter(self.frame.Close)