简体   繁体   English

如何打开tkinter中的SVG个文件?

[英]How to open SVG files in tkinter?

I want to be able to open SVG files in tkinter. The answer I'm using right now converts the SVG into a PNG before showing it in tkinter, but since I want to be to resize it without losing quality, I need a better answer.我希望能够在 tkinter 中打开 SVG 个文件。我现在使用的答案是将 SVG 转换为 PNG,然后在 tkinter 中显示它,但由于我想在不损失质量的情况下调整它的大小,我需要一个更好的答案.

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

But to add svg support to tk 8.6, it is necessary to install an extra package like tksvg .但是要为 tk 8.6 添加 svg 支持,需要安装额外的 package ,如tksvg So, first install tksvg, following the instructions from here .因此,首先按照此处的说明安装 tksvg。 Then you can create a PhotoImage from a svg file but you need to load tksvg in the tcl interpreter.然后您可以从 svg 文件创建一个PhotoImage ,但您需要在 tcl 解释器中加载 tksvg。 I wrote a quick python wrapper for 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)))

So SvgImage is like a PhotoImage but it has the additional options (only one of them can be specified since they are three different way of specifying the image size):所以SvgImage就像PhotoImage但它有额外的选项(只能指定其中一个,因为它们是指定图像大小的三种不同方式):

  • scale
  • scaletowidth : width in pixel scaletowidth :以像素为单位的宽度
  • scaletoheight : height in pixel scaletoheight : 以像素为单位的高度

Here is an example:这是一个例子:

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()

I think that there is no way of doing this without losing quality resolutions, but if svglib was not good enough maybe cairo can do it better.我认为没有办法在不损失质量分辨率的情况下做到这一点,但如果 svglib 不够好,也许 cairo 可以做得更好。 Try the code bellow.试试下面的代码。 It has the advantage that you don't really need the image as a png file, but since PIL does not handle svg you have to convert it anyway:它的优点是您实际上并不需要将图像作为 png 文件,但由于 PIL 不处理 svg 无论如何您都必须转换它:

from io import BytesIO
import cairosvg
from PIL import Image

out = BytesIO()
cairosvg.svg2png(url='path/to/svg', write_to=out)
image = Image.open(out)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM