Eelで新規ウィンドウを開く際に、単純にhtmlやjavascriptから開くとアプリケーションモードが解除されて、タブやらメニューバーやら表示されてしまう。
別に問題があるわけじゃないんだけど、何となく格好が悪い。
ということで、Pythonから新規ウィンドウを開けないか試してみた。
単純にeel.start()をもう一度呼べばいいのではないかと試してみる。
フォルダ構成main.py
web
└─ main.html
main.pyimport eel
def main():
eel.init("web")
eel.start("main.html")
"""新しいウィンドウを開く"""
@eel.expose
def open_window():
eel.start("main.html")
if __name__ == '__main__':
main()
main.html<html>
<head>
<meta charset="UTF-8">
<title>eel_exsample</title>
<script type="text/javascript" src="/eel.js"></script>
<script type="text/javascript">
// 新しいWindowを開くPythonスクリプトを実行する
function openWindow() {
eel.open_window();
}
</script>
</head>
<body>
<a href="#" onclick="openWindow()">openWindow</a>
</body>
</html>
openWindowのリンクを押下すると新しいウィンドウが開いた。
問題なく動作しているようだが、コンソールに以下のエラーが出ている。
OSError: [WinError 10048] 通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、またはポートのどれか 1 つのみを使用できます。: ('localhost', 8000)
2018-10-04T01:58:57Z failed with OSError
同じポートでもう一つWebサーバーを立てようとして怒られてるようだ。
1回目のeel.start()ですでにサーバーは立ってるから問題ないんだけどちょっと気持ちが悪い。
以下のように立てるwebサーバーのポートに0を指定してやって、空いている任意のポートを取得するようにしてやればエラーは発生しなくなる。
main.pyimport eel
def main():
eel.init("web")
eel.start("main.html", options={"port" : 0,})
"""新しいウィンドウを開く"""
@eel.expose
def open_window():
eel.start("main.html", options={"port" : 0,})
if __name__ == '__main__':
main()
ただ、新しいウィンドウを開くたびにサーバーが立つのでこれは無いかな。
Eelのソースを読んだところ、eel.browsers.open()にてよしなにchromiumのウィンドウを開いてくれているようだ。。。たぶん。
なので、以下のように直接eel.browsers.open()を呼び出してやれば、エラーメッセージも出てこず、サーバプロセスは一つのみで動作させることができる。
注意点として、1回目にeel.start()に渡したオプションを使いまわすようにすること (eel.start()にて必要なオプションを詰めてくれるので、それを使いまわす)。
main.pyimport eel
web_app_options = {
'port': 0,
}
def main():
eel.init("web")
# eel.start()では、引数に渡したオプションに未指定のものがあった場合、デフォルトの値を詰めてくれる。
eel.start("main.html", options=web_app_options)
"""新しいウィンドウを開く"""
@eel.expose
def open_window():
# 第一引数は開きたいURLのリスト、第二引数はeel.start()に渡したオプション
eel.browsers.open(["main.html",], web_app_options)
if __name__ == '__main__':
main()
ちょっと無理やり感があるかな。
その他の注意点として、開いたばかりのウィンドウのjavascriptの関数をPythonから呼び出せないことに注意する。
eel.sleep()などで開き終わるまで待ってやれば、新規ウィンドウのjavascriptの関数を呼び出せるようになる。
また、同じhtmlを複数ウィンドウ開いている場合、そのhtmlに含まれるjavascriptの関数をPythonから呼び出したら、すべてのウィンドウでその関数が実行される。
一つのウィンドウのみ対象にしたい場合は、javascriptに変数として任意のIDを持たせるなどの工夫が必要になりそう。
と色々はまりどころがあること考えると、Eelで複数ウィンドウ開くのは悪手くさいな。
少なくとも複数ウィンドウに同じ名称のjavascriptの関数が含まれる状況は避けた方がいい(Pythonから呼ばれないなら問題ない)。
複数ウィンドウが必要な場合は、javascriptのモーダルダイアログ扱うようなライブラリ使って、あんまりポカスカ新規ウィンドウが作られないようにした方がいいかな。
大体の機能はモーダルダイアログで済みそうだし、それならアプリケーションモードの見た目との相性も悪くないはず。