3

我在 Jupyter Python 环境中使用 ipyvuetify 为我的最终用户创建交互式仪表板。

我想创建一个交互式工具 btn切换vuitify.theme.darkTrueFalse

当我使用以下代码测试此行为时:

import ipyvuetify as v

v.theme.dark = True

#validate the selected data 
v.Container(children=[
    v.Btn(color='primary', children=[
        v.Icon(left=True, children=[
            'mdi-square'
        ]),
        'Click me'
    ])
])

只有组件的周围Btn有深色背景,页面的其余部分保持浅色背景。

一个技巧可能是?voila-theme=dark在我的网址末尾添加,但它不再是动态的。

有没有办法同时改变 thevoilaipyvuetifytheme ?还是强制ipyvuetify背景占据整个屏幕?

4

2 回答 2

1

更改body背景颜色

使用 Voilà(默认)实验室模板,ipyvuetify 应用程序周围的背景似乎是 HTMLbody背景,因此解决方法是将 ipyvuetify 主题的背景颜色应用于body背景。ipyvuetify-v.1.6.2 背景颜色#fff在浅色主题和#121212深色主题中(来自 vuetify.min.css-v2.2.26)。

<style>可以通过在 HTML元素中添加内部 CSS 来修改背景颜色:

dark_bg = '.jp-Notebook {background-color: #121212}'
light_bg = '.jp-Notebook {background-color: #fff}'

def bg_switch(widget, event, data):
    v.theme.dark = not v.theme.dark
    css.children = [dark_bg] if v.theme.dark==True else [light_bg]

btn = v.Btn(children=[v.Icon(children=['mdi-theme-light-dark'])])
btn.on_event('click',bg_switch)

css = v.Html(tag='style', children=[dark_bg] if v.theme.dark==True else [light_bg])

v.Container(children=[css,btn])

另一种解决方案是通过设置 JS HTML DOM Style 的 backgroundColor 属性来添加内联 CSS body

class BtnTheme(v.VuetifyTemplate):
    dark = traitlets.Bool(v.theme.dark).tag(sync=True)
    template = traitlets.Unicode('''
    <v-btn icon @click="switchTheme">
      <v-icon>mdi-theme-light-dark</v-icon>
    </v-btn>
    <script> {created() {this.updateBackground()},
      methods: {
        switchTheme() {
          this.dark = !this.dark;
          this.updateBackground()
          },
        updateBackground() {
          document.body.style.backgroundColor = this.dark ? '#121212' : '#fff'
        }
      }}
    </script>''').tag(sync=True)
    
btn = BtnTheme()
ipywidgets.jslink((btn, 'dark'), (v.theme, 'dark'))

v.Container(children=[btn])

在上述解决方案中,主题按钮使用其值初始化,v.theme.dark除非FalseTrue应用程序代码中设置为较早。此外,主题按钮可以初始化为 Voilà(实验室模板)主题:

  1. 通过检查查询参数:
v.theme.dark = (os.environ.get('QUERY_STRING', '').find('dark') != -1)
  1. created()或者通过在函数的开头检查类theme-dark中的存在body
if (document.body.classList.contains('theme-dark')) {this.dark = true}

在未知背景颜色的情况下,可以通过两个虚拟元素检测这两种颜色,每个元素都使用两个主题之一进行样式设置:

class BtnTheme(v.VuetifyTemplate):
    dark = traitlets.Bool(v.theme.dark).tag(sync=True)
    v_dark_bg = traitlets.Unicode('').tag(sync=True)
    v_light_bg = traitlets.Unicode('').tag(sync=True)
    template = traitlets.Unicode('''
    <v-btn icon @click="switchTheme">
      <v-icon>mdi-theme-light-dark</v-icon>
      <div class="v-application theme--dark" id="v-dark-style"></div>
      <div class="v-application theme--light" id="v-light-style"></div>
    </v-btn>
    <script> {
      mounted() {
        this.v_dark_bg = getComputedStyle(document.getElementById("v-dark-style")).backgroundColor
        this.v_light_bg = getComputedStyle(document.getElementById("v-light-style")).backgroundColor
        if (document.body.classList.contains('theme-dark')) {this.dark = true}
        this.updateBackground()
        },
      methods: {
        switchTheme() {
          this.dark = !this.dark
          this.updateBackground()
          },
        updateBackground() {
          document.body.style.backgroundColor = this.dark ? this.v_dark_bg : this.v_light_bg
        }
      }
    }
    </script>''').tag(sync=True)
于 2021-03-18T23:09:24.860 回答
1

一个技巧是添加一个不透明的Overlay组件作为背景 ( z-index=-1) 并在切换 ipyvuetify 主题时更改其颜色:

import ipyvuetify as v

dark_bg = '#121212'
light_bg = '#fff'

bg = v.Overlay(
    color=dark_bg if v.theme.dark==True else light_bg, 
    opacity=1, 
    style_='transition:unset', 
    z_index=-1
)

def bg_switch(widget, event, data):
    v.theme.dark = not v.theme.dark
    bg.color = dark_bg if v.theme.dark==True else light_bg

btn = v.Btn(children=[v.Icon(children=['mdi-theme-light-dark'])])
btn.on_event('click', bg_switch)

v.Container(children=[bg, btn])

无需 JS 代码。颜色定义来自vuetify.min.css(ipyvuetify 1.6.2 使用的v2.2.26):#fff浅色主题和#121212深色主题。

于 2021-03-26T00:35:40.213 回答