Ipywidgetsで「ポップアップウインドウもどき」を作ってみる
簡単なPythonのプログラムを試すのに、Jupyter notebookを使っているのですが、ちょっとしたGUIが欲しくなったので、ipywidgetsと言うライブラリを試しています。ちなみに使っている環境は以下の通りです。
OS : macOS-13.5.2
Python : ver. 3.11.4
Jupyter Notebook : ver. 6.5.4
ipywidgets : ver. 8.0.6
pywidgetsは、お手軽に使えるウイジェットセットで、見たところ一通りのものは揃っていますが、あまり細かい凝ったことはできなさそうな感じです。 Ipywidgetsができないことの中に、メッセージやメニューなどの「ポップアップができない」というのががあります。ポップアップはできませんが、メッセージやメニューなどの表示・非表示を切り替えてそれっぽく見せることはできそうです。
IpywidgetsにはOutputと言うウィジェットが用意されています。これは、表示出力先となるエリアとなるウィジェットで標準出力、標準エラー出力、動画などの出力先として使えますし、各種ウィジェットの表示先としても使えます。Outputに何かを出力する時には、Outputをコンテキストマネージャとして使い、with文の中でdisplay()やprint()などを呼び出します。
import ipywidgets as widgets
out = widgets.Output()
display(out)
with out :
display(widgets.Button(description ="SAMPLE"))
Output上の表示を消去する場合は、Outputウィジェットのメソッドclear_output()を呼び出します。
out.clear_output()
この仕組みを使って、表示されているラベルの文字列と背景色を設定するメニューを「ポップアップっぽく」表示するプログラムを作ってみます。
import ipywidgets as widgets
class PropertyEditor:
# カテゴリーの属性を定義するエディター
# 動的に表示・非表示が可能
def __init__(self):
self.caller = None
self.name = "Blank"
self.color = "white"
self._initialize_widget()
def _initialize_widget(self):
self.name_text = widgets.Text(
value = self.name,
description='Label Strings:')
self.color_picker = widgets.ColorPicker(
concise=False,
description='Color:',
value=self.color)
save_button = widgets.Button(
description ='Save',
layout = widgets.Layout(width = '45pt') )
save_button.on_click(self._closeEditPanel)
save_button_panel = widgets.HBox(
[save_button],
layout=widgets.Layout(display='flex', flex_flow='row',
justify_content='center'))
self.widget = widgets.VBox([self.name_text, self.color_picker,save_button_panel],
layout=widgets.Layout(border='1px solid black',
display='flex', flex_flow='colomun',
justify_content='center'))
# 動的に表示・非表示を切り替えるためにOutputウィジェットを作る
self.out = widgets.Output()
def showEditPanel(self, caller):
self.caller = caller
self.name_text.value = caller.name
self.color_picker.value = caller.color
# Outputウイジェットをクリア
self.out.clear_output()
# Outputウイジェットの上にエディタを表示
with self.out:
display(self.widget)
def _closeEditPanel(self, x):
self.caller.setProperties(self.name_text.value, self.color_picker.value)
#Outputウイジェットをクリアし、エディタを消去
self.out.clear_output()
class SamplePanel:
# 最初から表示される、ラベルとボタンを含むパネル
def __init__(self):
self.name ="Default String"
self.color = "lightgray"
self.editor = None
self._label = widgets.Label(
value=self.name,
layout = widgets.Layout(width = '180pt',height ='22pt'),
style={"background": self.color}
)
self._edit_button = widgets.Button(description ='Edit',
disabled = False,
layout = widgets.Layout(width = '36pt'),
)
self._edit_button.on_click(self._showPropertyEditor)
self.widget = widgets.HBox([self._label, self._edit_button])
def setProperties(self, name, color):
self.name = name
self.color = color
self._label.value = name
self._label.style.background = color
def _showPropertyEditor(self, x):
self.editor.showEditPanel(self)
# ここからメインプログラム
editor = PropertyEditor()
sample_panel = SamplePanel()
sample_panel.editor = editor
sample_box = widgets.HBox([sample_panel.widget, editor.out])
display(sample_box)
こんな感じで設定パネルが表示されたり消えたりします。
仕組みを絵で書くとこんな感じです。参考まで。