タスクバーな例

シンプルなタスクバーアプリケーション

tags:gui, tips
created:2007-02-05T20:24:24

タスクバーアプリを作成してみました。

ファイルリスト

  • resource.xrc
  • sample.py
  • wx_utils.py
  • setup.py
  • main_icon.ico
  • main_icon.py

例によっておなじ構成です。

スクリーンショット

タスクバーアイコンの様子:

../../../_images/taskbar.png

表示したメインフレーム:

../../../_images/taskbar_frame.png

リソース内容

これはXRCedを使って編集した結果です。

resource.xrc

<?xml version="1.0" encoding="utf-8"?>
<resource>
  <object class="wxFrame" name="MainFrame">
    <title>wxPython Sample [TaskbarIconApplication]</title>
    <object class="wxBoxSizer">
      <orient>wxVERTICAL</orient>
      <object class="sizeritem">
        <object class="wxStaticText">
          <label>テキストボックス</label>
        </object>
        <flag>wxTOP|wxLEFT|wxRIGHT</flag>
        <border>4</border>
      </object>
      <object class="sizeritem">
        <object class="wxTextCtrl" name="ID_TEXT_CTRL">
          <style>wxTE_MULTILINE</style>
        </object>
        <option>1</option>
        <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND</flag>
        <border>4</border>
      </object>
      <object class="sizeritem">
        <object class="wxStaticLine"/>
        <flag>wxLEFT|wxRIGHT|wxGROW</flag>
        <border>4</border>
      </object>
      <object class="sizeritem">
        <object class="wxBoxSizer">
          <orient>wxHORIZONTAL</orient>
          <object class="spacer">
            <option>1</option>
          </object>
          <object class="sizeritem">
            <object class="wxBitmapButton" name="wxID_OK">
              <bitmap stock_id="wxART_TICK_MARK"></bitmap>
            </object>
          </object>
          <object class="sizeritem">
            <object class="wxBitmapButton" name="wxID_CANCEL">
              <bitmap stock_id="wxART_CROSS_MARK"></bitmap>
            </object>
          </object>
        </object>
        <flag>wxALL|wxGROW</flag>
        <border>4</border>
      </object>
    </object>
    <bg>#FFFFFF</bg>
  </object>
  <object class="wxMenu" name="PopupMenu">
    <object class="wxMenuItem" name="ID_TOGGLE_MAIN_FRAME">
      <label>メインフレーム</label>
      <bitmap stock_id="wxART_FOLDER_OPEN"></bitmap>
    </object>
    <object class="separator"/>
    <object class="wxMenuItem" name="ID_EXIT_APP">
      <label>アプリケーションの終了</label>
      <bitmap stock_id="wxART_QUIT"></bitmap>
    </object>
  </object>
  <object class="wxMenuBar" name="MainMenubar">
    <object class="wxMenu">
      <label>ファイル</label>
      <object class="wxMenuItem" name="wxID_EXIT">
        <label>アプリケーションの終了</label>
      </object>
    </object>
  </object>
</resource>

主フレーム「MainFrame」と主フレーム用のメニューバー「MainMenubar」、 およびタスクバーコンテキストメニュー「PopupMenu」を定義しています。

メインコード

sample.py

#!/usr/bin/local/python
# -*- coding: utf-8 -*-

import sys
import os
import wx
import wx_utils
from wx_utils import XRC, XRCID, XRCCTRL

import main_icon

class TaskBarIcon(wx.TaskBarIcon):

  RESOURCE_ID = 'TASKBERICON1'
  binder = wx_utils.bind_manager(RESOURCE_ID)

  def __init__(self, main_frame):
    wx.TaskBarIcon.__init__(self)
    self.main_frame = main_frame
    self.SetIcon(main_icon.getIcon(), u'タスクバーアイコンのヒント')
    self.binder.bindall(self, self.RESOURCE_ID)

  def CreatePopupMenu(self):
    return XRC().LoadMenu('PopupMenu')

  @binder(wx.EVT_TASKBAR_LEFT_DCLICK)
  def OnDblClicked(self, event):
    tc = XRCCTRL(self.main_frame, 'ID_TEXT_CTRL')
    tc.write(u'ダブルクリック!!')

  @binder(wx.EVT_MENU, id=XRCID('ID_TOGGLE_MAIN_FRAME'))
  def OnToggleMainFrame(self, event):
    if self.main_frame.IsShown():
      self.main_frame.Hide()
    else:
      self.main_frame.Show()
      self.main_frame.Iconize(False)

  @binder(wx.EVT_MENU, id=XRCID('ID_EXIT_APP'))
  def OnExitApp(self, event):
    self.main_frame.OnCloseApp(None)

class MainFrame(wx.Frame):
  u"""MainFrame class deffinition.
  """
  RESOURCE_ID = 'MainFrame'
  MENUBAR_ID = 'MainMenubar'
  binder = wx_utils.bind_manager(RESOURCE_ID)

  def __init__(self, parent=None):
    pre = wx.PreFrame()
    XRC().LoadOnFrame(pre, parent, self.RESOURCE_ID)
    self.PostCreate(pre)
    self.SetMenuBar(XRC().LoadMenuBar(self.MENUBAR_ID))
    self.tbicon = TaskBarIcon(self)
    self.binder.bindall(self, self.RESOURCE_ID)
    self.SetIcon(main_icon.getIcon())
    self.SetSize((480,400))

  @binder(wx.EVT_CLOSE)
  def OnCloseApp(self, event):
    self.tbicon.Destroy()
    self.Destroy()

  @binder(wx.EVT_MENU, id=XRCID('wxID_EXIT'))
  def OnExitApp(self, event):
    self.OnCloseApp(None)

# startup application.
if __name__=='__main__':
  app = wx.App(False)
  wx_utils.XrcInit()
  frame = MainFrame()
  app.SetTopWindow(frame)
  #frame.Show()
  app.MainLoop()

解説

概要

タスクバークラスと主フレームクラスをそれぞれ別々にイベントマッピングを行いました。

イベントを処理するインスタンスがひとつでも残っているとapp.MainLoop()は終了しないので、 それぞれの終了処理は、タスクバークラス、主フレームクラス共に破棄するようにしました。

親子関係が定義づけされる場合は、親が破棄されるとき子のすべてを破棄するので今回のように意識する必要はありません。

注釈

TaskbarIconを親にしてMainFrameを子にしようとしたらエラーでした。TaskbarIconは親になる機能を持たないようです。

フレーム中の子コントロールへのアクセス

この例では、子コントロールの「ID_TEXT_CTRL」というXRCIDをもつwx.TextCtrlにアクセスしています。

tc = XRCCTRL(self, 'ID_TEXT_CTRL')

このような記述でwx.TextCtrlインスタンスを取得できます。 XRCCTRLファンクションの第一引数は親フレームまたはダイアログのインスタンスを指定します。 第二引数には、XRCedで編集時に名づけたIDを指定します。