Updating the layout using bokeh tabs - python

I am creating a dashboard for my bokeh app using a template similar to the one demonstrated here:
https://towardsdatascience.com/data-visualization-with-bokeh-in-python-part-iii-a-complete-dashboard-dc6a86aa6e23
Basically I am separating the different functions of my app into different scripts which have a function returning a Panel object containing the layout to be imported in the Tabs object defined on my main.py.
For example, this is my what my read.py script returns:
# First layout / plot
read_layout = bla.layout([firstColRaw,
secondColRaw,
bmo.Spacer(width=50),
thirdColRaw])
def read_tab():
tab = bmo.Panel(child=read_layout, title='Read in data')
return tab
This is what I have on my main.py:
from scripts.read import read_tab
# Tabs to select the app function
tab1 = read_tab()
nav_tabs = [tab1]
tabs = bmo.Tabs(tabs=nav_tabs, width=1500)
# Create the main layout
layout_main = bla.column(buttons,
tabs,
height=300,
width=1500)
# Put the tabs in the current document for display
doc.add_root(layout_main)
I am running into a problem when I try to update the layout of one of the tabs. In this specific example, I would like to dynamically show the user how many raw data files are being loaded in the environment.
In this specific case I modify the contents of the thirdColRaw variable which then add a div to the layout object.
If I am running the app as displayed above, I cannot update the content of the Tabs. If, on the other hand, I don't use Tabs, but instead just load the read_layout from the main.py and add it to the current doc, the layout update works just fine.
Does this mean that I cannot modify/add/remove Panel layout components dynamically? Or am I doing something wrong?
Thanks!

As of Bokeh 0.13 this is known layout bug. There is currently a large PR in progress to address many layout issues at once, including this one, but it will not be ready until Bokeh 1.1 is released. In the mean time, I can only suggest:
avoiding the combination of tabs and responsive sizing modes
using components to template plots into non-Bokeh layouts.

Related

Jupyter Lab - Use input() while interacting with a ipywidget and for it to execute observe method and thus update the widget

In jupyterlab, I'm using a ipywidget consisting of nested Tab widgets with a HTML widget for each leaf Tab children. I was wondering is it possible to interact with this ipywidget while waiting for input using input() . I'm loading strings into the HTML widget when Tab.selected_index changes using observe() because jupyterlab complains about too many operations or something like that but because of input blocking nothing is happening.
So in pseudocode
I create the widget Tab_5 a Tab Widget which for each Tab has another Tab Widget associated with it. Eg Queries have associated tabs 1-10, 11-20 are top level tabs and Tabs 1,2,3,4,5,6,7,8,9,10 are nested under Tab 1 - 10 etc
create def on_value_change(change)
if len(Tab_5.children[Tab_5.selected_index].children[Tab_5.children[Tab_5.selected_index].selected_index].value) == 0:
index = 10 * Tab_5.selected_index + Tab_5.children[Tab_5.selected_index].selected_index
Tab_5.children[Tab_5.selected_index].children[Tab_5.children[Tab_5.selected_index].selected_index].value = "<div style ='line-height: normal;'>"+ descList[index] + "<br><br>"+ str(queryStrings[index]) + "<br><br>" + str(responses[index]) + "</div>"
assign it to the children widgets using Tab_5.children[i].observe(on_value_change, names='selected_index'), Tab_5.observe(on_value_change, names='selected_index')
So I looked at https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html and didn't really understand it and tried doing stuff with the last example.
Basically I'm running some queries using an API and I want to see my past queries in the tabbed interface before choosing to continuing on with future queries with the same parameters apart from one which is incremented. But at the moment, the tabbed widget is not updating while waiting for input.
So previously I generated some Markdown as output but it become really slow. I also at one stage used
from IPython.core.getipython import get_ipython
shell = get_ipython()
payload = dict(
source='set_next_input',
text=contents,
replace=False,
)
shell.payload_manager.write_payload(payload, single = False)
create_new_cell("".join(output))
which created a new code cell which needed to be manually turned into a Markdown cell. (You can programmatically create a cell in Jupyter Notebook but not Jupyter Lab)
So do I need to do something with threads or asyncio? Is this possible or can I accomplish this in a better way by having a widget for the input?
Any suggestions?

Is there a way to hide a displayed object using IPython?

I am using the IPython module in a Jupyter Notebook.
I am using the display module to display buttons.
from ipywidgets import widgets
import IPython.display as dsply
def click_reset(b):
print("reset domains button")
restoreDomains()
resetButton = widgets.Button(description="Reset Domains")
resetButton.on_click(click_reset)
dsply.display(resetButton)
This works fine, but I am trying to find a way to programatically hide certain buttons. Based off the execution of my other code, I want certain buttons to be removed from the UI. Is there anything like hide(resetButton) that I can use?
You can hide a widget using
resetButton.layout.visibility = 'hidden'
to let the widget still consume space, or
resetButton.layout.display = 'none'
to let the widget not consume space anymore.
The top-level attribute resetButton.visible = False is not longer supported.
When I use #SergeyGornostaev's answer, I still have a residual cross showing up on the left side of the cell output. I found the following command removes the widget all together:
resetButton.close()
You can hide every widget by setting it's property visible to False
resetButton.visible = False

PyQt4: Auto completion in Qscintilla and horizontal scrolling

I want to show all attributes and tags in auto completion list of a html file if auto completion threshold is set to 1. I have tried this code to use APIs i set this code after the file is loaded in new mdi child(sub window) but it is not working:
lexer=Qsci.QsciLexerHTML()
api = Qsci.QsciAPIs(lexer)
## Add autocompletion strings
api.add("aLongString")
api.add("aLongerString")
api.add("aDifferentString")
api.add("sOmethingElse")
## Compile the api for use in the lexer
api.prepare()
self.activeMdiChild().setAutoCompletionSource(Qsci.QsciScintilla.AcsAPIs)
self.activeMdiChild().setLexer(lexer)
and my horizontal scroll bar is visible all the time i want to set it as scrollbarasneeded. please tell how to do these two tasks.
Other than failing to set the auto-completion threshold, there doesn't seem to be anything wrong with your example code. Here's a minimal working example:
from PyQt4 import QtGui, Qsci
class Window(Qsci.QsciScintilla):
def __init__(self):
Qsci.QsciScintilla.__init__(self)
lexer = Qsci.QsciLexerHTML(self)
api = Qsci.QsciAPIs(lexer)
api.add('aLongString')
api.add('aLongerString')
api.add('aDifferentString')
api.add('sOmethingElse')
api.prepare()
self.setAutoCompletionThreshold(1)
self.setAutoCompletionSource(Qsci.QsciScintilla.AcsAPIs)
self.setLexer(lexer)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
The scrollbar-as-needed feature cannot really be solved, unless you are willing to reimplement everything yourself (which would not be easy). The underlying Scintilla control doesn't directly support automatic horizontal scrollbar hiding, because it involves a potentially very expensive calculation (i.e. determining the longest line). Most people who use Scintilla/Qscintilla just learn to put up with the ever-present horizontal scrollbar.

How to show a png image in Gtk3 with Python?

First of all, it is important to mention that I'm learning Python and Gtk+ 3, so I'm not an advanced programmer in these languages.
I'm trying to make a graphical interface in Gtk3 for a Python script that creates a png image, and I'd like to display it, but the PyGobject documentation is so scarce that I haven't found a way to do that. So far, my interface looks like this:
The buttons and text entries are arranged in a grid, and I'd like to keep empty the big space (represented by the big button) to the right until the script finishes building the image, and then show it in that area. The code is here.
Is there a way to do that using Python in Gtk3?
Thanks in advance,
Germán.
EDIT
Taking a look at the demos pointed out by #gpoo I discovered the Frame widget, and I implemented it in my GUI. This is how it looks like:
Inside the window class, I add the Frame to the grid:
self.frame_rgb = Gtk.Frame(label='RGB image')
self.frame_rgb.set_label_align(0.5, 0.5)
self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
self.grid.attach_next_to(self.frame_rgb, self.label_img_name,
Gtk.PositionType.RIGHT, 3, 8)
I also connect the Run button to a callback function, so that when I click on it, my script creates and then displays the png image:
self.button_run = Gtk.Button(stock=Gtk.STOCK_EXECUTE)
self.button_run.connect('clicked', self.on_button_run_clicked)
self.grid.attach_next_to(self.button_run, self.entry_b_img,
Gtk.PositionType.BOTTOM, 1, 1)
Finally, my callback function is (no calculations yet, only render the image to the Frame for testing purposes):
def on_button_run_clicked(self, widget):
self.img = Gtk.Image.new_from_file('astro-tux.png')
self.frame_rgb.add(self.img)
but I got the following error when I click the Run button:
(makeRGB.py:2613): Gtk-WARNING **: Attempting to add a widget with
type GtkImage to a GtkFrame, but as a GtkBin subclass a GtkFrame can
only contain one widget at a time; it already contains a widget of
type GtkImage
Any help is appreciated!
You can use Gtk.Image. If you generate a file, you could use:
img = Gtk.Image.new_from_file('/path/to/my_file.png')
and add img to the container (GtkGrid in your case). Or, if you already have the Gtk.Image there, you can use:
img.set_from_file('/path/to/my_file.png')
Instead of ...from_file you can use from_pixbuf, and you can create a Gdk.Pixbuf from a stream.
In general, you can use the documentation for C and change the idiom to Python. Also, you can check the demos available in PyGObject, in particular, the demo for handling images.

How to get (childless) “tabs” in a pygtk application

I am facing the problem to need tabs in a pygtk app. Pretty much just like gedit has, but without any per-child widget content.
I’ve come across gtk.Notebook, but that requires me to put a widget for each tab, which I don't want.
The reason is, that I have one widget, but would only like to updates its content based on which tab is selected.
Any hints on how to do that?
My idea so far would be to just add some invisible widget for each tab and then connect to the select-page signal. Which widget could I use as invisible widget, or is there a better/alternative way of achieving my goal?
The invisble widget idea works. But not with gtk.Invisible (this just crashes), but with gtk.HBox() or any other thing that seems empty.
self.notebook.append_page(gtk.HBox(), gtk.Label("title"))
Now if I want to display stuff inside the tab actually, I can use reparent to move the widget to the current tab like this.
class Tab(gtk.HBox):
def __init__(self, child):
self.child = child
self.notebook.append_page(Tab(myWidget), gtk.Label("title"))
def pageSelected(self, notebook, page, pagenum):
box = notebook.get_nth_page(pagenum)
box.child.reparent(box)
You can have global widgets, one per tab as you want, in order to access them easily when the tab is selected.
self.notebook.append_page(self.rightBox, gtk.Label("Orders"))
Then connect to the "switch page" signal
self.notebook.connect("switch-page", self.pageSelected)
and :
def pageSelected(self, notebook, page, pagenum):
name = notebook.get_tab_label(notebook.get_nth_page(pagenum))
Now you have "name" with the label of the currently selected page. Just test it (if name == "Orders" ...) to interact.
Hope this was of some help !

Categories