首页 > 解决方案 > 如何在 tkinter 中打开 SVG 文件?

问题描述

我希望能够在 tkinter 中打开 SVG 文件。我现在使用的答案是在 tkinter 中显示之前将 SVG 转换为 PNG,但是由于我想在不损失质量的情况下调整它的大小,所以我需要一个更好的答案。

标签: pythonsvgtkinter

解决方案


一些基本的 svg 支持将成为 tk 8.7 ( https://core.tcl-lang.org/tips/doc/trunk/tip/507.md ) 的一部分。

但是要为 tk 8.6 添加 svg 支持,需要安装一个额外的包,例如tksvg。因此,首先按照此处的说明安装 tksvg 。然后您可以从 svg 文件创建一个PhotoImage,但您需要在 tcl 解释器中加载 tksvg。我为 tksvg 写了一个快速的 python 包装器:

import tkinter as tk

class SvgImage(tk.PhotoImage):
    """Widget which can display images in PGM, PPM, GIF, PNG format."""
    _tksvg_loaded = False
    _svg_options = ['scale', 'scaletowidth', 'scaletoheight']

    def __init__(self, name=None, cnf={}, master=None, **kw):
        # load tksvg
        if not SvgImage._tksvg_loaded:
            if master is None:
                master = tk._default_root
                if not master:
                    raise RuntimeError('Too early to create image')
            master.tk.eval('package require tksvg')
            SvgImage._tksvg_loaded = True
        # remove specific svg options from keywords
        svgkw = {opt: kw.pop(opt, None) for opt in self._svg_options}
        tk.PhotoImage.__init__(self, name, cnf, master, **kw)
        # pass svg options
        self.configure(**svgkw)

    def configure(self, **kw):
        svgkw = {opt: kw.pop(opt) for opt in self._svg_options if opt in kw}
        # non svg options
        if kw:
            tk.PhotoImage.configure(self, **kw)
        # svg options
        options = ()
        for k, v in svgkw.items():
            if v is not None:
                options = options + ('-'+k, str(v))
        self.tk.eval('%s configure -format {svg %s}' % (self.name, ' '.join(options)))

所以SvgImage就像 aPhotoImage但它有额外的选项(只能指定其中一个,因为它们是指定图像大小的三种不同方式):

  • scale
  • scaletowidth: 像素宽度
  • scaletoheight: 像素高度

这是一个例子:

root = tk.Tk()

def rescale():
    global scale
    scale += 0.5
    img.configure(scale=scale)

scale = 0.5
img = SvgImage(master=root, file='/path/to/file.svg', scale=scale)
tk.Button(root, image=img, command=rescale).pack()
root.mainloop()

推荐阅读