سؤال

في pyGame التطبيق، أرغب في عرض عناصر واجهة المستخدم الرسومية (GUI) بدون دقة وضوح والموضحة في SVG.

ما الأداة و/أو المكتبة التي يمكنني استخدامها للوصول إلى هذا الهدف؟

(انا احب ال واجهة المستخدم الرسومية OCEMP مجموعة أدوات ولكن يبدو أنها تعتمد على الصورة النقطية لعرضها)

هل كانت مفيدة؟

المحلول

هذا مثال كامل يجمع تلميحات من أشخاص آخرين هنا.يجب أن يعرض ملفًا يسمى test.svg من الدليل الحالي.تم اختباره على Ubuntu 10.10، python-cairo 1.8.8، python-pygame 1.9.1، python-rsvg 2.30.0.

#!/usr/bin/python

import array
import math

import cairo
import pygame
import rsvg

WIDTH = 512
HEIGHT = 512

data = array.array('c', chr(0) * WIDTH * HEIGHT * 4)
surface = cairo.ImageSurface.create_for_data(
    data, cairo.FORMAT_ARGB32, WIDTH, HEIGHT, WIDTH * 4)

pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
svg = rsvg.Handle(file="test.svg")
ctx = cairo.Context(surface)
svg.render_cairo(ctx)

screen = pygame.display.get_surface()
image = pygame.image.frombuffer(data.tostring(), (WIDTH, HEIGHT),"ARGB")
screen.blit(image, (0, 0)) 
pygame.display.flip() 

clock = pygame.time.Clock()
while True:
    clock.tick(15)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            raise SystemExit

نصائح أخرى

السؤال قديم جدًا ولكن مرت 10 سنوات وهناك إمكانية جديدة تعمل ولا تتطلب ذلك librsvg أي أكثر من ذلك.هنالك غلاف Cython فوق مكتبة nanosvg ويعمل:

from svg import Parser, Rasterizer


def load_svg(filename, surface, position, size=None):
    if size is None:
        w = surface.get_width()
        h = surface.get_height()
    else:
        w, h = size
    svg = Parser.parse_file(filename)
    rast = Rasterizer()
    buff = rast.rasterize(svg, w, h)
    image = pygame.image.frombuffer(buff, (w, h), 'ARGB')
    surface.blit(image, position)

لقد وجدت أن حل القاهرة/rsvg معقد جدًا بحيث لا يمكن تشغيله نظرًا لأن التبعيات غامضة تمامًا بحيث لا يمكن تثبيتها.

يمكنك استخدام القاهرة (مع PyCairo)، الذي يدعم عرض صور SVG.تحتوي صفحة الويب PyGame على ملف كيف للتحويل إلى مخزن مؤقت باستخدام القاهرة، واستخدام هذا المخزن المؤقت مباشرة مع PyGame.

أدرك أن هذا لا يجيب بالضبط على سؤالك، ولكن هناك مكتبة تسمى سكويرتل من شأنها أن تعرض ملفات SVG باستخدام Pyglet أو PyOpenGL.

pygamesvg يبدو أنه يفعل ما تريد (على الرغم من أنني لم أجربه).

لا تستطيع القاهرة عرض SVG خارج الصندوق.يبدو أنه يتعين علينا استخدام librsvg.

وجدت للتو هاتين الصفحتين:

من المحتمل أن يعمل شيء مثل هذا (render test.svg ل اختبار.png):

import cairo
import rsvg

WIDTH, HEIGHT  = 256, 256
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)

ctx = cairo.Context (surface)

svg = rsvg.Handle(file="test.svg")
svg.render_cairo(ctx)

surface.write_to_png("test.png")

لقد تعطل التعليق الأخير عندما قمت بتشغيله لأن svg.render_cairo() يتوقع سياقًا للقاهرة وليس سطحًا للقاهرة.لقد قمت بإنشاء واختبار الوظيفة التالية ويبدو أنها تعمل بشكل جيد على نظامي.

import array,cairo, pygame,rsvg

def loadsvg(filename,surface,position):
    WIDTH = surface.get_width()
    HEIGHT = surface.get_height()
    data = array.array('c', chr(0) * WIDTH * HEIGHT * 4)
    cairosurface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32, WIDTH, HEIGHT, WIDTH * 4)
    svg = rsvg.Handle(filename)
    svg.render_cairo(cairo.Context(cairosurface))
    image = pygame.image.frombuffer(data.tostring(), (WIDTH, HEIGHT),"ARGB")
    surface.blit(image, position) 

WIDTH = 800
HEIGHT = 600
pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
screen = pygame.display.get_surface()

loadsvg("test.svg",screen,(0,0))

pygame.display.flip() 

clock = pygame.time.Clock()
while True:
    clock.tick(15)
    event = pygame.event.get()
    for e in event:
        if e.type == 12:
            raise SystemExit

استنادًا إلى الإجابات الأخرى، إليك وظيفة لقراءة ملف SVG وتحويله إلى صورة pygame - بما في ذلك تصحيح ترتيب قنوات الألوان وقياسها:

def pygame_svg( svg_file, scale=1 ):
    svg = rsvg.Handle(file=svg_file)
    width, height= map(svg.get_property, ("width", "height"))
    width*=scale; height*=scale
    data = array.array('c', chr(0) * width * height * 4)
    surface = cairo.ImageSurface.create_for_data( data, cairo.FORMAT_ARGB32, width, height, width*4)
    ctx = cairo.Context(surface)
    ctx.scale(scale, scale)
    svg.render_cairo(ctx)

    #seemingly, cairo and pygame expect channels in a different order...
    #if colors/alpha are funny, mess with the next lines
    import numpy
    data= numpy.fromstring(data, dtype='uint8')
    data.shape= (height, width, 4)
    c= data.copy()
    data[::,::,0]=c[::,::,1]
    data[::,::,1]=c[::,::,0]
    data[::,::,2]=c[::,::,3]
    data[::,::,3]=c[::,::,2]

    image = pygame.image.frombuffer(data.tostring(), (width, height),"ARGB")
    return image
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top