TIL

Today I Learned. 知ったこと、学んだことを書いていく

has_focus(value)で渡したUIControl(Window)にフォーカスがあるか確認する - Python

指定したコントロールにフォーカスがあるかどうか

prompt_toolkit.layout.layout.Layout.has_focus()で確認できる

has_focus(value)

Check whether the given control has the focus.
:param value: UIControl or Window instance.

Reference — prompt_toolkit 2.0.6 documentation

WindowUIControlを渡す

使い方としてはキーバインディング

@kb.add('o')
def _(event):
    logger.debug(event.app.layout.has_focus(left_window))

って感じにする

まず、キーが押された時に、現在起動中のApplicationlayoutを取得する

こんなApplicationだったばあい

from prompt_toolkit.application import Application
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.layout.containers import VSplit, Window
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.document import Document
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.keys import Keys

from logging import getLogger, config
config.fileConfig("logger.conf")
logger = getLogger(__name__)


def get_text():
    return '\n'.join([chr(i) for i in range(65, 65+26)] * 3)


left_window = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True)))
right_window = Window(BufferControl(Buffer(document=Document(get_text(), cursor_position=0), read_only=True)))
split_line = Window(width=1, char='|')

body = VSplit([
    left_window,
    split_line,
    right_window
    ])

# キーバインディング
kb = KeyBindings()
kb.add(Keys.Tab)(focus_next)
kb.add(Keys.BackTab)(focus_previous)


@kb.add('q')
def _(event):
    event.app.exit()


@kb.add('o')
def _(event):
    logger.debug(event.app.layout)


app = Application(
        layout=Layout(body),
        key_bindings=kb,
        full_screen=True)

app.run()

出力されるのは、

2018-11-02 07:39:37:DEBUG Layout(<prompt_toolkit.layout.containers.VSplit object 
at 0x1017b5be0>, current_window=Window(content=<BufferControl buffer=<Buffer
(name='', text='A\nB\nC\nD\nE\nF\n...') at 4319711808> at 4319711640>))

event.app.layoutでApplication()のコンストラクタのlayoutに指定した参照が取得できる。

指定のウィンドウにフォーカスがあるか調べる

左側のウィンドウにフォーカスがあるかどうかはLayout.has_focus()left_windowを渡せばいい

@kb.add('o')
def _(event):
    logger.debug(event.app.layout.has_focus(left_window))

左側にフォーカスがある時にoを押すとTrue、右側にあるときはFalse

基本的には、ウィンドウとかはインスタンスを変数に入れておけば良いのかな

このhas_focus()を使えば、特定のウィンドウにフォーカスがあるときのみ、キーバインドを実行するとかできるのかな?
fillterとか使えそう...?


logger.confは以下の通り

;ロガーを使用するときには以下のように記述する
;from logging import getLogger, config
;config.fileConfig("logger.conf")
;_logger = getLogger(__name__)

[loggers]
keys=root

[handlers]
keys=fileHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=fileHandler

[handler_fileHandler]
class=FileHandler
level=DEBUG
; ハンドラで使用するフォーマッタを指定
formatter=simpleFormatter
; FileHandlerのコンストラクタへの引数
args=("log.log", "a+")

[formatter_simpleFormatter]
format=%(asctime)s:%(levelname)s %(message)s
; 時間の表示形式を設定
datefmt=%Y-%m-%d %H:%M:%S

参考文献