FloatPanel does not initiate a status change when clicking the close icon. I think it is due to JsPanel not sending a status change for close. The following code extends FloatPanel to add onbeforeclose
, to end the dtale session.
Thanks to @matthiasautrata.
import gc
import dtale
import pandas as pd
import panel as pn
from werkzeug.serving import BaseWSGIServer
pn.extension('floatpanel')
# Be careful using this if you have other Dtale Sessions open
def proper_dtale_shutdown():
for obj in gc.get_objects():
try:
if isinstance(obj, BaseWSGIServer):
obj.shutdown()
break
except Exception as e:
print(e)
dtale.global_state.cleanup()
class CustomFloatPanel(pn.layout.FloatPanel):
def __init__(self, *objects, name='', **params):
super().__init__(*objects, name=name, **params)
self._scripts[
'render'
] = """
if (state.panel) {
view.run_script('close')
}
var config = {
headerTitle: data.name,
content: float,
theme: data.theme,
id: 'jsPanel'+data.id,
position: view.run_script('get_position'),
contentSize: `${model.width} ${model.height}`,
onstatuschange: function() {
data.status = this.status
},
onbeforeclose: function(panel, status, closedByUser) {
data.status = 'closed'
}
}
if (data.contained) {
config.container = view.container
}
config = {...config, ...data.config}
state.panel = jsPanel.create(config);
"""
self.param.watch(self.close_dtale_session, 'status')
def close_dtale_session(self, event):
if self.status == 'closed' and self.dt and dtale.get_instance(self.dt._data_id):
# .kill() does not currently work on dtale version 3.3.0
# utilizing their workaround
proper_dtale_shutdown()
self.objects = []
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
dt = dtale.show(df, host='localhost')
html = f""" <iframe src="{dt._main_url}" width="1000" height="1000"></iframe> """
float_panel = CustomFloatPanel(html, name='Browse Database', margin=20)
float_panel.dt = dt
pn.serve(float_panel)