【问题标题】:Bokeh Custom Save Tool散景自定义保存工具
【发布时间】:2017-09-07 13:53:06
【问题描述】:

我正在尝试在散景中创建自定义保存工具,这就是我所拥有的:

class NewSaveTool(Tool):
    JS_CODE = """
        import * as p from "core/properties"
        import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
        export class NewSaveToolView extends ActionToolView
            do: () -> 
                save_name = @model.source
                @plot_view.save(save_name)

        export class NewSaveTool extends ActionTool
            default_view: NewSaveToolView
            type: "SaveTool"
            tool_name: "Save"
            icon: "bk-tool-icon-save"
            @define {
                source: [ p.String ]
            }
    """
    source = String
    __implementation__ = JS_CODE

该工具加载并在工具栏中,但是当我单击按钮时,我得到了

Uncaught TypeError: this.plot_view.save is not a function

这就是源码中保存工具使用的确切功能,那么有谁知道为什么它在这种情况下不起作用?

【问题讨论】:

    标签: javascript python coffeescript bokeh


    【解决方案1】:

    回答这个问题太晚了,因为我花了太多时间才使它起作用。
    这里的主要变化是“do”到“doit”,虽然老实说我不确定指定的错误来自哪里,这是我从未遇到过的少数错误之一。

    一个有效的实现(至少在 bokeh 12.13 上)是:

    JS_CODE_SAVE = """
    import * as p from "core/properties"
    import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
    
    export class NewSaveView extends ActionToolView
    
      # this is executed when the button is clicked
      doit: () ->
        @plot_view.save(@model.save_name)
    
    export class NewSave extends ActionTool
      default_view: NewSaveView
      type: "NewSave"
    
      tool_name: "Save"
      icon: "bk-tool-icon-save"
    
      @define { save_name: [ p.String ] }
    """
    
    class NewSave(Tool):
        """
        Save a plot with a custom name.
        Usage: NewSaveTool(save_name=name)
        """
        __implementation__ = JS_CODE_SAVE
        save_name = String()
    

    实现为:tools = [CustomSaveTool(savename='custom name')]

    要真正动态更改保存名称,您必须更改 savename 属性,例如在小部件回调函数中:plot.tools[0].save_name = 'new save name'

    【讨论】:

    • 不是答案,只是澄清——我认为“do”是 JS 中的保留字,是 do...while 循环结构的一部分。
    【解决方案2】:

    太棒了!有用! 关于上面的使用示例,只需注释一下,应该是:

    tools = [NewSave(savename='custom name')]
    

    这是一个完整的工作示例(使用 CustomSaveTool 作为类名):

    from bokeh.models import Tool, String
    from bokeh.plotting import figure
    from bokeh.io import show
    
    JS_CODE_SAVE = """
    import * as p from "core/properties"
    import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
    
    export class NewSaveView extends ActionToolView
    
      # this is executed when the button is clicked
      doit: () ->
        @plot_view.save(@model.save_name)
    
    export class CustomSaveTool extends ActionTool
      default_view: NewSaveView
      type: "CustomSaveTool"
    
      tool_name: "Save"
      icon: "bk-tool-icon-save"
    
      @define { save_name: [ p.String ] } """
    
    class CustomSaveTool(Tool):
        """
        Save a plot with a custom name.
        Usage: CustomSaveTool(save_name = name)
        """
        __implementation__ = JS_CODE_SAVE
        save_name = String()
    
    tools = [CustomSaveTool(save_name = 'custom name 1')]
    plot = figure(x_range = (0, 10), y_range = (0, 10), tools = tools)
    plot.line(x = [1, 2, 3], y = [4, 5, 6])
    plot.tools[0].save_name = 'custom name 2'
    show(plot)
    

    【讨论】:

      【解决方案3】:

      初始响应中给出的实现不适用于更新版本的散景。

      这是基于原始 SaveTool 代码的更新版本。它公开了一个可以在 Python 中设置的 save_name 属性:

      from bokeh.models import ActionTool
      from bokeh.util.compiler import TypeScript
      from bokeh.core.properties import String
      
      CUSTOM_SAVE_TS = """
      import {ActionTool, ActionToolView} from "models/tools/actions/action_tool"
      import * as p from "core/properties"
      import {tool_icon_save} from "styles/icons.css"
      
      export class CustomSaveToolView extends ActionToolView {
        model: CustomSaveTool
      
        async save(name: string): Promise<void> {
          const blob = await this.plot_view.to_blob()
          const link = document.createElement("a")
          link.href = URL.createObjectURL(blob)
          link.download = name // + ".png" | "svg" (inferred from MIME type)
          link.target = "_blank"
          link.dispatchEvent(new MouseEvent("click"))
        }
      
        doit(): void {
          this.save(this.model.save_name)
        }
      }
      
      export namespace CustomSaveTool {
        export type Attrs = p.AttrsOf<Props>
      
        export type Props = ActionTool.Props & {
          save_name: p.Property<string>
        } 
      }
      
      export interface CustomSaveTool extends CustomSaveTool.Attrs {}
      
      export class CustomSaveTool extends ActionTool {
        properties: CustomSaveTool.Props 
        __view_type__: CustomSaveToolView
      
        constructor(attrs?: Partial<CustomSaveTool.Attrs>) {
          super(attrs)
        }
      
        static init_CustomSaveTool(): void {
          this.prototype.default_view = CustomSaveToolView
      
          this.register_alias("save", () => new CustomSaveTool())
      
          this.define<CustomSaveTool.Props>(({String}) => ({
            save_name: [ String ],
          }))
        }
      
        tool_name = "Custom Save"
        icon = tool_icon_save
      
      }
      """
      
      class CustomSaveTool(ActionTool):
          """Modified save tool allowing custom file names"""
          __implementation__ = TypeScript(CUSTOM_SAVE_TS)
          save_name = String()
      
      save_tool = CustomSaveTool(save_name='custom_filename')
      

      请注意,与原始 SaveTool 代码相比,我不得不废弃与“复制”功能相关的部分,我认为无论如何都不会真正使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-26
        • 1970-01-01
        • 2019-10-22
        • 1970-01-01
        相关资源
        最近更新 更多