python系GUIアプリケーションでのキーバインド(Tkinter編、wxPython編)

python GUI Tkinter wxPython

pythonでGUIプログラミングをするときのウィジットツールキットが何種類かあります。私は大抵、TkinterかwxPythonでGUIを組み立てていってます。

で、それぞれコピーペーストでよくバインドされるControl-C、Control-Vとか終了させるControl-Qを使いたい場面が多々あります。なので今回それぞれのキーバインド方法をまとめておおくことにしました。今回の例では、<Control>-Qでアプリケーションを終了させるキーバインドを設定してみます。

確認環境は、Linux Mint 18.3上でpythonのバージョンは以下になります。

hoge $ python3 --version
Python 3.5.2

Tkinter編

TkinterはPython標準のツールキットで特にライブラリを追加することもなく使うことが可能です。なのでpythonがクロスプラットフォームで使用可能な状態であればTkinterも新たにライブラリを入れること無くクロスプラットフォーム環境で使用が可能です。

キーバインドに関しても結構簡単に設定することができます。

まず、frameだけ組み立てたソースは以下になります。

#!/usr/bin/env python3                                                                                                                                                                            
# -*- coding: utf-8 -*-                                                                                                                                                                           
#                                                                                                                                                                                                 
# tkkeybind.py                                                                                                                                                                                    
#                                                                                                                                                                                                 

from tkinter import *
from tkinter import ttk

class AppUI(Frame):
    def createWidgets(self):
        main_frame = Frame (root, width=400, height=300)
        main_frame.pack(padx=4, pady=4)                                                                                                                                                           

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.createWidgets()

root = Tk()
app = AppUI(root)

app.master.title("tkkeybind")
app.pack()


root.mainloop()
#### EOF #### 

実行するとこんな感じになります。

hoge $ ./tkbind.py
keybind frame

このままでは、当然ですが<Control>-Qを押してもアプリケーションは終了しません。次にキーバインドしてみます。

#!/usr/bin/env python3                                                                                                                                                                            
# -*- coding: utf-8 -*-                                                                                                                                                                           
#                                                                                                                                                                                                 
# tkkeybind.py                                                                                                                                                                                    
#                                                                                                                                                                                                 

from tkinter import *
from tkinter import ttk

class AppUI(Frame):
    def createWidgets(self):
        main_frame = Frame (root, width=400, height=300)
        main_frame.pack(padx=4, pady=4)

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.createWidgets()

root = Tk()
app = AppUI(root)

app.master.title("tkkeybind")
app.pack()
                                                                                                                                                                                                  
root.bind("<Control-q>", sys.exit)
root.bind("<Control-Q>", sys.exit)
root.mainloop()
#### EOF #### 

root.bind(“<Control-q>”, sys.exit)root.bind(“<Control-Q>”, sys.exit)でキーバインドをしています。これで実行すると<Control>-Qを押すとアプリケーションが終了するのが確認できると思います。

wxPython編

wxPythonもクロスプラットフォームなウィジットツールキットですが各OSにpythonを入れた後にwxPythonもライブラリをpipする必要があります。個人的にですがwxPyhtonのいいところは、各OS NativeなGUIになってくれるところでMac上ではメインメニューが特に指定しないかぎりデスクトップ上部のメニューバーに構成してくれます。

今回、確認時のwxPythonは以下になります。またwxPythonでのキーバインドの方法はいろいろあるようですのでこの記事は一例として参考にしてください。

hoge $ pip show wxpython
Name: wxPython
Version: 4.1.0
Summary: Cross platform GUI toolkit for Python, "Phoenix" version
Home-page: http://wxPython.org/
Author: Robin Dunn
. . . . . 

まず、tkinterのときと同様にframeの雛形を作ります。今回、雛形はwxGladeで作りました。ソースは以下になります。

余談ですがwxGladeで雛形を作ると2行目は、-*- coding: UTF-8 -*-となりますがemacsで編集するとき文句を言われるのでUTF-8の文字を小文字でutf-8に編集しなおしています。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# generated by wxGlade 0.9.4 on Mon Aug 10 13:39:28 2020
#

import wx

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("wxkeybind")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

# end of class MyFrame

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

# end of class MyApp

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()
#### EOF ####

実行すると以下のようになります。

hoge $ wxkeybind.py
keybind frame

キーバインド設計を追記しいたソースは以下になります。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# generated by wxGlade 0.9.4 on Mon Aug 10 13:39:28 2020
#

import wx
import sys

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
        ####
        new_id = wx.NewId()
        accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('Q'), new_id )])
        self.SetAcceleratorTable(accel_tbl)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=new_id)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

        
    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("wxkeybind")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

    def OnQuit(self, event):
        self.Close()
        
        
# end of class MyFrame

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

# end of class MyApp

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()
#### EOF ####

追加したところを抜粋すると def init(self, *args, **kwds):のところに

        new_id = wx.NewId()
        accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL,  ord('Q'), new_id )])
        self.SetAcceleratorTable(accel_tbl)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=new_id)

とdef文追加で

    def OnQuit(self, event):
        self.Close()

になります。これで実行すると<Contorl>-Qでアプリケーションが終了するはずですので確認してみてください。

参考にさせていただいたサイトは以下になります。

wxPython: Keyboard Shortcuts (Accelerators)

中川電子技研

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL