☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Swapping two figures in a gridbox at runtime in bokeh server

Community Supportserver
vbs
vbs

Hello gentlemen,

is it possible to update the layout of figures arranged in a gridplot at runtime? Basically I want to reorder figures by swapping positions of two figures using a button callback. But whatever I try to do it does not work as expected.

Here is a minimal example of what I do consider one of my best tries:

from bokeh.application.handlers.function import FunctionHandler
from bokeh.application import Application
from bokeh.document import Document
from bokeh.server.server import Server
from bokeh.plotting import figure, output_file, show, gridplot
from bokeh.models import GridBox
from bokeh.layouts import column, grid
from bokeh.models.widgets import Button

model = None


def on_button():
    f1, f2, b = model.children[1].children
    
    # swap items - but no effect
    model.children[1].children = [f2, f1, b]


def make_document(doc: Document):
    global model
    x = [1, 2, 3, 4, 5]
    y = [6, 7, 2, 4, 5]

    p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')
    p.line(x, y, legend="Temp.", line_width=2)

    y2 = [3, 5, 2, 11, 9]
    p2 = figure(title="simple line example", x_axis_label='x', y_axis_label='y')
    p2.line(x, y2, legend="Temp.", line_width=2)

    b = Button(label="Rearrange", button_type="success")
    b.on_click(on_button)

    model = gridplot(children=[[p], [p2], [b]])
    doc.add_root(model)


handler = FunctionHandler(make_document)
app = Application(handler, )

apps = {'/': app}

server = Server(apps, port=80)
server.run_until_shutdown()

But it has no visible effect. I suspect it is quite easy to do probably but I just can’t manage to do the right thing. A bit of help would be very appreciated.

I am using Bokeh 1.4.0 from Miniconda on Windows 10 x64.

Thanks alot!

⌁   Link to post
Bryan
Bryan

FYI for the future: half the core team, and a great many Bokeh users, are women. Please be inclusive and respectful of the entire Bokeh community here.

is it possible to update the layout of figures arranged in a gridplot at runtime?

Yes, but it will be pretty tedious, because the actual stored format for grid children (i.e. what you need to update) is more complicated than what you pass in initially. It looks like this, where the actual position in the grid is determined by the numbers in the tuples (not by the top level order):

[(Figure(id=...), 0, 0), (Figure(id=...), 1, 0), (Button(id=...), 2, 0)]

Could you use a column here instead? That would be much easier to update.

⌁   Link to post
vbs
vbs

Oh I am sorry, I didn’t mean to be disrespectful to anyone. So “Hello” also to all ladies and also to people of all other genders also.

[(Figure(id=...), 0, 0), (Figure(id=...), 1, 0), (Button(id=...), 2, 0)]

Actually I think I already tried that in the past but could not get it to work. I again tried it using your proposal changing that one line to this:

#    model.children[1].children = [f2, f1, b]
    model.children[1].children = [(f2, 0, 0), (f1, 1, 0), (b, 2, 0)]

but then I get:

  File "C:\Users\Robin\Miniconda3\envs\qrawler\lib\site-packages\bokeh\core\property\container.py", line 90, in validate
    raise ValueError(msg)
ValueError: expected an element of List(Either(Tuple(Instance(LayoutDOM), Int, Int), Tuple(Instance(LayoutDOM), Int, Int, Int, Int))), got seq with invalid items [((Figure(id='1048', ...), 1, 0), 0, 0), ((Figure(id='1001', ...), 0, 0), 1, 0), ((Button(id='1095', ...), 2, 0), 2, 0)]

Yes I already tried with column and managed to rearrange it out-of-the-box. The selling point for gridplot for me was the toolbar collecting feature:

gridplot() also collects all tools into a single toolbar, and the currently active tool is the same for all plots in the grid.

I guess this would also be possible to achieve also using a column? I might give it a try, thank you.

⌁   Link to post
p-himik
p-himik

Regarding the ValueError - f1, f2, and b in the on_button function are not instances of LayoutDOM but rather tuples themselves. The first item is an instance of LayoutDOM, the second is the row of the element, the third one is the column.

With that being said, all you need to do is swap the row values. Swapping the whole tuples doesn’t do anything because, well, the tuples also have the row number.

⌁   Link to post
vbs
vbs

Isn’t that what I did with this line already?

model.children[1].children = [(f2, 0, 0), (f1, 1, 0), (b, 2, 0)]

I think f1 had “0,0” before and has now “1,0”.

⌁   Link to post

End of archived discussion · Replies are disabled