首页 > 编程问答 >添加新选项卡时如何保留输入和输出值?

添加新选项卡时如何保留输入和输出值?

时间:2024-08-03 04:56:54浏览次数:8  
标签:python py-shiny

我在开发 Python 闪亮应用程序时遇到了一个特殊问题。我的应用程序当前具有通过按下名为“+”的导航集选项卡动态生成新选项卡的功能。但是,按“+”后,之前选项卡的状态(包括输入和输出值)将重置回空。有没有办法保留任何以前存在的选项卡的状态?

我的代码概述如下:

from shiny import App, Inputs, Outputs, Session, module, reactive, render, ui

# Create a Module UI
@module.ui
def textbox_ui(panelNum):
    return ui.nav_panel(
        f"Tab {panelNum}",
        ui.input_text_area(id=f"test_text",
                           label = "Enter some text"),
        ui.output_ui(f"display_text_{panelNum}"),
        value = f"Tab_{panelNum}"
    )

# Set up module server
@module.server
def textbox_server(input, output, session, panelNum):

    @output(id=f"display_text_{panelNum}")
    @render.text
    def return_text():
       return input[f"test_text"]()


# Set up app UI
app_ui = ui.page_fluid(
    ui.tags.head(
       ui.tags.style(
           """
           body {
               height: 100vh;
               overflow-y: auto !important;
           }
           """
       )
    ),
    ui.h2('Test App', align='center', fillable=True),
    ui.output_ui("tab_UI"),
    title = "Test App"
)

# Set up server
def server(input, output, session):
   
   # Set up reactive values
   navs = reactive.value(0)
   
   # Add tabs if the user presses "+"
   @reactive.effect
   @reactive.event(input.shiny_tabs)
   def add_tabs():
      if input.shiny_tabs() == "+":
          navs.set(navs.get() + 1)
   
   @output
   @render.ui
   def tab_UI():
      [textbox_server(str(x), panelNum=x+1) for x in range(navs.get())]
      ui.update_navs("shiny_tabs", selected = f"Tab_{navs.get()}")

      return ui.navset_tab(
         ui.nav_panel("Home",
                      ui.card(
                         ui.card_header("Overview"),
                         ui.p("An example of the outputs clearing")
                         ),
                      value = "panel0"
                      ),
        *[textbox_ui(str(x), panelNum=x+1) for x in range(navs.get())],
        ui.nav_panel("+"),
        id = "shiny_tabs"
     )

app = App(app_ui, server)

问题在于,每次添加新选项卡时,都会重新创建所有选项卡及其相应的状态。为了保留状态,需要在选项卡外部存储每个选项卡的输入值。这可以使用 reactiveValues reactiveVal 在 Shiny 会话中完成。

以下是使用 reactiveValues 修改后的代码:

from shiny import App, Inputs, Outputs, Session, module, reactive, render, ui

# Create a Module UI
@module.ui
def textbox_ui(panelNum):
    return ui.nav_panel(
        f"Tab {panelNum}",
        ui.input_text_area(id=f"test_text_{panelNum}", label="Enter some text"),
        ui.output_ui(f"display_text_{panelNum}"),
        value=f"Tab_{panelNum}"
    )

# Set up module server
@module.server
def textbox_server(input, output, session, panelNum, saved_values):
    @reactive.effect
    @reactive.event(input[f"test_text_{panelNum}"])
    def save_input_value():
        saved_values[panelNum] = input[f"test_text_{panelNum}"]()

    @output(id=f"display_text_{panelNum}")
    @render.text
    def return_text():
        return saved_values.get(panelNum, "")

# Set up app UI
app_ui = ui.page_fluid(
    ui.tags.head(
        ui.tags.style(
            """
            body {
                height: 100vh;
                overflow-y: auto !important;
            }
            """
        )
    ),
    ui.h2("Test App", align="center", fillable=True),
    ui.output_ui("tab_UI"),
    title="Test App"
)

# Set up server
def server(input, output, session):
    # Set up reactive values
    navs = reactive.value(0)
    saved_values = reactive.Value({})

    # Add tabs if the user presses "+"
    @reactive.effect
    @reactive.event(input.shiny_tabs)
    def add_tabs():
        if input.shiny_tabs() == "+":
            navs.set(navs.get() + 1)

    @output
    @render.ui
    def tab_UI():
        ui.update_navs("shiny_tabs", selected=f"Tab_{navs.get()}")

        return ui.navset_tab(
            ui.nav_panel("Home",
                         ui.card(
                             ui.card_header("Overview"),
                             ui.p("An example of the outputs NOT clearing")
                         ),
                         value="panel0"
                         ),
            *[textbox_ui(panelNum=x + 1) for x in range(navs.get())],
            ui.nav_panel("+"),
            id="shiny_tabs"
        )

    for i in range(1, navs.get() + 1):
        textbox_server(panelNum=i, saved_values=saved_values)


app = App(app_ui, server)

更改如下:

  1. 为每个输入框使用唯一 ID: 我们将输入框的 ID 从 "test_text" 修改为 "test_text_{panelNum}" ,以便每个选项卡都有唯一的 ID。
  2. 使用 reactive.Value 存储输入值: 我们创建了一个 reactive.Value 对象 ( saved_values ),用于存储每个选项卡的输入值。
  3. textbox_server 中保存和加载输入值: 我们在 textbox_server 中添加了逻辑,以便在输入框的值更改时,将其保存在 saved_values 中,并在渲染输出时从 saved_values 中加载值。

现在,即使添加了新选项卡,先前选项卡的输入和输出值也将被保留。

标签:python,py-shiny
From: 78817794

相关文章

  • python数据分析与可视化基础
    一、数据分析介绍:1.数据分析含义:数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,将它们加以汇总和理解并消化,以求最大化地开发数据的功能,发挥数据的作用。数据分析是为了提取有用信息和形成结论而对数据加以详细研究和概括总结的过程。数据分析的数学基础在20世纪早......
  • 为什么要设置 os.environ[“PYTHONHASHSEED“] = “0“,这样做具体会影响哪些随机值?
    ......
  • Python,Geopandas报错,AttributeError: The geopandas.dataset has been deprecated and
    Python版本3.9,Geopandas版本1.0.1问题描述:这是执行的代码,importpandasaspdimportgeopandasimportmatplotlib.pyplotaspltworld=geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))world.plot()plt.show()这是报错信息,Traceback(mo......
  • Python,Maskrcnn训练,cannot import name ‘saving‘ from ‘keras.engine‘ ,等问题集合
    Python版本=3.9,tensorflow=2.11.0,keras==2.11.0问题一、module'keras.engine'hasnoattribute'Layer'Traceback(mostrecentcalllast):File"C:\Users\Administrator\Desktop\20240801\代码\test.py",line16,in<module>......
  • 7-Python数据类型——列表和元组的详解(增删改查、索引、切片、步长、循环)
    一、列表1.1列表list有序且可变的容器,可以存放多个不同类型的元素列表就是专门用来记录多个同种属性的值列表:存储同一个类别的数据,方便操作字符串,不可变:即:创建好之后内部就无法修改【内置功能都是新创建一份数据】name="xiaochaun"data=name.upper()print(nam......
  • python中的 is 和 ==
    一前言环境:win10python3.10二is和isnot1比较对象的identityis和isnot是python的比较运算符,比较运算符除了这两个,还有下图中的这些is和isnot比较的是两个对象的是identityidentity是啥,内置函数id()返回的就是这个东西通过上面id函数的解释,现在知道,identi......
  • Python应用开发——30天学习Streamlit Python包进行APP的构建(23):构建多页面应用程序
    创建动态导航菜单通过st.navigation,可以轻松创建动态导航菜单。您可以在每次重新运行时更改传递给st.navigation的页面集,从而更改与之匹配的导航菜单。这是创建自定义、基于角色的导航菜单的便捷功能。本教程使用st.navigation和st.Page,它们是在Streamlit1.36.0版中......
  • Python数据结构第二天—循环链表、树、二叉搜索树
    双向链表之前学习的单向链表只能从头遍历到尾,过程是单向的,而双向链表既可以从头遍历到尾,也可以从尾遍历到头,它的过程是双向的。既然它是双向的,那么我们要实现一个双向链表,就需要在单向链表的基础上,给每一个结点增加一个向前的引用。双向链表的创建:"""我们要实现的是一......
  • Python学习笔记50:游戏篇之外星人入侵(十一)
    前言本篇文章接着之前的内容,继续对游戏功能进行优化,主要是优化游戏状态以及对应的处理。状态一个游戏包含多种状态,这个状态是一个可以很复杂也可以很简单的内容。条件所限,我们这个游戏的状态就比较简单:未开始游戏中暂停结束我们通过一个字段进行控制,并且将这个字段放置......
  • python——functools
    好的,我们再详细讲解functools模块的常用工具,包括每个API的语法和参数,并特别详细解释lru_cache的工作原理及其缓存机制。functools简介functools模块提供了许多高阶函数和工具,用于操作或返回其他函数,帮助我们更方便地进行函数式编程。1.partial函数partial函数用于固定......