一連のテキスト コントロールを含むカスタム ダイアログを作成しました。すべてのテキスト コントロールには、特定の値をより便利に追加するためのいくつかのボタンが横にあります。ほとんどの場合、ユーザーはボタンを使用する必要がないため、ユーザーがダイアログをタブで移動するときに、これらのボタンにフォーカスを与えたくありません。
特定のコントローラーを標準のタブ トラバーサルから除外する便利な方法はありますか?
ボタンがキーボードでフォーカスされないようにする簡単な方法は、以下のオーバーライドをサポートするものから派生するwx.lib.buttons.GenButton
か、wx.lib.buttons.ThemedGenButton
それに基づいています。wx.PyControl
AcceptsFocusFromKeyboard()
class NoFocusButton(wx.lib.buttons.ThemedGenButton):
def __init__(self, parent, id=wx.ID_ANY, label=wx.EmptyString, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.ButtonNameStr):
wx.lib.buttons.ThemedGenButton.__init__(self,parent,id,label,pos,size,style,validator,name)
def AcceptsFocusFromKeyboard(self):
return False # does not accept focus
より複雑なナビゲーションルールまたはコントロールの場合はwx.EVT_NAVIGATION_KEY
、ナビゲーションを自分で処理および管理できます。ナビゲートするウィンドウのリストを取得するには、を使用できますself.GetChildren()
。で現在フォーカスされているウィンドウのインデックスは、wx.WindowList
を介して取得できます.index(mywindow)
。その情報を使用して、ユーザーが「ナビゲーションキー」を押すたびにリストをナビゲートし、フォーカスしたくないコントロールをスキップして、フォーカスを次の該当するコントロールに設定できます。
リスト内を簡単に移動できるように、ジェネレーターを作成できます。
def CycleList(thelist,index,forward):
for unused in range(len(thelist)): # cycle through the list ONCE
if forward:
index = index+1 if index+1 < len(thelist) else 0
else:
index = index-1 if index-1 >= 0 else len(thelist)-1
yield thelist[index]
ダイアログで、次を処理しwx.EVT_NAVIGATION_KEY
ます。
self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
def OnNavigationKey(self,event):
children = self.GetChildren() # list of child windows
focused = self.FindFocus() # current focus
# avoid accessing elements that do not exist
if not focused or focused not in children:
event.Skip() # use default behavior
return
index = children.index(focused)
for child in CycleList(children,index,event.GetDirection()):
# default behavior:
if child.AcceptsFocusFromKeyboard():
child.SetFocus()
return
上記の例は、デフォルトの動作をエミュレートします。フォーカス可能なコントロールを循環します(静的テキストなどのフォーカスできないコントロールをスキップします)。AcceptsFocusFromKeyboard
チェックを拡張して特定のコントロールを除外したり、 Falseを返すことを実装するカスタムボタンクラスを作成したりできます。
注:wx.PyWindow
、、wx.PyPanel
およびwx.PyControl
のオーバーライドを許可するメカニズムを実装している間、AcceptsFocusFromKeyboard
標準のwxPythonコントロールはそうではありません。ただし、Python側での処理wx.EVT_NAVIGATION_KEY
とチェックは、オーバーライドされたメソッドを呼び出す実際のPythonオブジェクトにアクセスします。AcceptsFocusFromKeyboard
C ++を使用している場合、この回答の残りの部分で説明されているように、この問題には簡単な解決策があります。wxPythonでは、wxWidgetsクラスを特殊化できないようです。これは私には致命的な問題のようです。
AcceptsFocusFromKeyboard()をオーバーライドしてFALSEを返すことにより、タブトラバーサルから除外されるボタンコントロールの特殊化を作成できます。
http://docs.wxwidgets.org/trunk/classwx_window.html#a2370bdd3ab08e7ef3c7555c6aa8301b8
次のC++コードは正常に機能します。タブを押すと、フォーカスが最初のボタンから3番目のボタンにジャンプします。
class cNoTabButton : public wxButton
{
public:
cNoTabButton(wxWindow *parent,
wxWindowID id,
const wxString& label = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0 )
: wxButton(parent,id,label,pos,size,style)
{}
bool AcceptsFocusFromKeyboard() const {
return false;
}
};
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title)
{
// set the frame icon
SetIcon(wxICON(sample));
wxPanel * panel = new wxPanel(this,-1,wxPoint(0,0),wxSize(500,500));
new wxButton(panel,-1,"TabPlease",wxPoint(20,20));
new cNoTabButton(panel,-1,"NoTabThanks",wxPoint(100,20));
new wxButton(panel,-1,"OKWithMe",wxPoint(200,20));
}