顯示具有 wxPython 標籤的文章。 顯示所有文章
顯示具有 wxPython 標籤的文章。 顯示所有文章

2011年2月12日 星期六

Cake: a python shell with a simple plugin system

Cake是一個python的shell操作介面,並實作了一個簡單的插件系統。

從這裡下載。

開啟

雙擊"CakeBoot.bat"即可開啟Cake。

操作說明

1. Shell
中間的Shell是主要的命令輸入介面。Shell的使用方式幾乎與python自帶的IDLE介面相同。
可使用的命令放置於cmdb模組的名稱空間中,因此在Shell中輸入
>>> dir(cmdb)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'callback_to_menubar', 'choice_one_dlg', 'error_dlg', 'file_open_dlg', 'file_save_dlg', 'hello_world', 'modlues_load', 'object_load', 'object_save', 'run_cmd']

即可獲得目前可使用的命令名稱,如欲查看命令的說明訊息,例如cmdb.error_dlg這個命令的說明,輸入
>>> help(cmdb.error_dlg)
Help on function error_dlg in module share.ui.SimpleDlg:

error_dlg(msg)
Popup an error message.

>>> error_dlg("ERROR!")

執行cmdb.error_dlg,輸入
>>> cmdb.error_dlg("NO")
即可看到一個彈出的錯誤訊息視窗。


2. Plugin

Cake在啟動時會匯入放置於路徑"cake\plugin"下的所有附檔名為py檔案。因此可從此處將自訂的命令匯入cake中。直接以一個plugin為例:
cake\plugin\hello_plugin.py
from cmdb import callback_to_menubar

def hello_world():
    print "Hello World"
    
callback_to_menubar(hello_world, "Plugin,Hello,World0")

callback_to_menubar函數提供自訂menubar的menu item的功能。
兩個參數,前一個為此menu item的call back函數,即是按下此menu item後要執行的函數。這裡將在按下menu item後執行hello_world()。
後一個參數則是此menu item在menubar上的放置路徑,這裡的"Plugin,Hello,World0"表示此menu item位於"Plugin"->"Hello"->"World0"
點擊"World0"即可執行hello_world()。於Shell介面會出現
>>> cmdb.hello_world()
Hello World
>>>
callback_to_menubar 函數除了在menubar上放置menu item,並且將回呼函數放入cmdb的名稱空間中。點擊menu item後的動作,只是在Shell介面執行回呼函數。因此也可以直接於Shell介面輸入相同的命令。換句話說,"點擊menu item"僅是取代在Shell介面鍵入函數名稱的動作。

2011年1月19日 星期三

在wxPython中使用自定event

參考網頁。一個簡單的測試程式如下:
import wx
import wx.lib.newevent

# regist a custom event
SomeNewEvent, EVT_SOME_NEW_EVENT = wx.lib.newevent.NewEvent()

class TestWin(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        # bind event and event handler
        self.Bind(EVT_SOME_NEW_EVENT, self.handler)
        
        # trigger an event
        #     create an event
        evt = SomeNewEvent(attr1="hello", attr2=654)
        #     post this event
        wx.PostEvent(self, evt)

    # event handler
    def handler(self, evt):
        print evt.attr1, evt.attr2
 
app = wx.PySimpleApp()
app.TopWindow = TestWin()
app.TopWindow.Show()
app.MainLoop() 

2010年10月5日 星期二

在視窗中嵌入shell介面

shell介面可以以文字形式,以直接鍵入函數與參數的方式控制應用程式,甚至執行一段script。

wxPython提供一個shell的應用程式,稱做PyShell,可以在
Python26\Lib\site-packages\wx-2.8-msw-unicode\wx\py目錄下
執行PyShell.py。

目錄下的shell.py中的Shell類別是此shell程式的核心,放到應用程式中即是一個現成的shell介面。此shell介面還支援自動完成與函數提示。


以下是簡單的嵌入範例,將Shell類別置入一個wx.Panel中。
"""
ShellPanel provides a shell interface in a panel.

# put shell in a frame
self.myShellPanel = ShellPanel(objDict = {'win':self}, parent = self)
"""

import wx
import wx.py as  py

class ShellPanel(wx.Panel):
    def __init__(self, objDict, *args, **kwds):
        """\
ShellPanel(objectDict, parent, ...)
    Create a Shell panel and put some object into this shell;
    Assign "myHelpInfo" object for default help text."""
        # format of objdict: { Name:object }

        kwds["style"] = wx.TAB_TRAVERSAL
        wx.Panel.__init__(self, *args, **kwds)

        self.objectDict = objDict
        self.myShell = py.shell.Shell(self, -1, locals = self.objectDict )

        sizer_Shell = wx.BoxSizer(wx.HORIZONTAL)
        sizer_Shell.Add(self.myShell, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_Shell)

self.myShell = py.shell.Shell(self, -1, locals = objDict)
參數locals接收一個{名稱字串:物件}的字典,可將物件以對應的名稱字串在shell介面中操作。如果將應用程式(視窗)本身傳入,即可在shell介面中控制視窗,如上例將視窗物件以"win"命名,並在shell介面下輸入"win.SetTitle('Hello World')",便可改變視窗Title顯示。

此shell介面比起python內建的IDLE仍有些缺點。如下程式碼:
from time import sleep
for i in range(10): sleep(1)
無法如同在IDLE中,以鍵盤方式中斷。
(參考網頁:命令行的 Python shell 保留了處理鍵盤中斷( Ctrl +C)的能力...)

更多的Shell類別建構參數使用,請參考shell.py原始碼。

2009年8月9日 星期日

Some simple dialogs of wxPython

  以下四個是我常用的wxPython對話框(或許之後還會陸續增加),包成函數形式省卻了部分填參數與開啟對話框,消除(Destroy)對話框的動作。


import wx

def SingleChoiceGetDialog(wnd, ItemNameList, dlgTitle = "", hintString = ""):
"""\
SingleChoiceGetDialog(wnd, ItemNameList, dlgTitle = "", hintString = "")
Get selected index in given items.

Parameters:
wnd ( type = parent window )
ItemNameList ( type = list of string )
dlgTitle ( type = string )
hintString ( type = string )
Returns:
selectedIndex( type = int or None )"""
dlg = wx.SingleChoiceDialog(
wnd, hintString, dlgTitle,
ItemNameList,
wx.CHOICEDLG_STYLE
)

if dlg.ShowModal() == wx.ID_OK:
selectedIndex = dlg.GetSelection()
else: selectedIndex = None
dlg.Destroy()
return selectedIndex

def FilePathGet(wnd, op, wildcard, dlgTitle):
wildcard = "|".join(["""%s file (*.%s)|*.%s"""%(fileType, subName, subName)
for (fileType, subName) in wildcard])

style = (wx.SAVE | wx.CHANGE_DIR) if op == "save" else (wx.OPEN | wx.CHANGE_DIR)
FileDlg = wx.FileDialog( wnd, dlgTitle,
defaultDir="",
defaultFile="",
wildcard = wildcard,
style=style
)

if( FileDlg.ShowModal() == wx.ID_OK ):
filePath = FileDlg.GetPath()
else: filePath = None
FileDlg.Destroy()
return filePath

def FileOpenPathGetDialog(wnd, wildcard = [("All","*")], dlgTitle = "File Open"):
"""\
FileOpenPathGetDialog(wnd, wildcard = [("All","*")], dlgTitle = "File Open")
Get selected file path on action of "FileOpen".

Parameters:
wnd ( type = parent window )
wildcard ( type = list of tuple )
dlgTitle ( type = string )
Returns:
filePath ( type = string or None)"""
return FilePathGet(wnd, "open", wildcard, dlgTitle)

def FileSavePathGetDialog(wnd, wildcard = [("All","*")], dlgTitle = "File Save"):
"""\
FileSavePathGetDialog(wnd, wildcard = [("All","*")], dlgTitle = "File Save")
Get selected file path on action of "FileSave".

Parameters:
wnd ( type = parent window )
wildcard ( type = list of tuple )
dlgTitle ( type = string )
Returns:
filePath ( type = string or None )"""
return FilePathGet(wnd, "save", wildcard, dlgTitle)

def ErrorMessageDialog(wnd, msg):
"""\
ErrorMessageDialog(wnd, msg)
Popup an error message.

Parameters:
wnd ( type = parent window )
msg ( type = string )"""
dlg = wx.MessageDialog(wnd, msg, "Error", wx.OK | wx.ICON_ERROR )
dlg.ShowModal()
dlg.Destroy()


  SingleChoiceGetDialog:從ItemNameList中單選。

  FileOpenPathGetDialog, FileSavePathGetDialog:取得"開檔"/"存檔"的檔案路徑。
    想顯示副檔名為"py"的檔案("*.py"),就在加入wildcard中加入tuple ("py","py"),前一個"py"是提示字串,後一個"py"是用來過濾副檔名的字串。

  ErrorMessageDialog:彈出錯誤訊息。

  對於GUI,我傾向花越少時間處理越好;漂亮,獨特的外觀是不太在乎的,只要個普通的window類型的表現,能讓使用者了解的動作提示,例如一看就知道這是要開啟檔案,就足夠了。所以我用了許多預設參數簡化函數呼叫。例如在frame中開啟檔案--

filePath = FileOpenPathGetDialog(self) # "self" is frame object in this case
if filePath: data = open(filePath,"w")