![](/img/trans.png)
[英]How to embed a third party application (using SDL2) into a QWidget?
[英]How can I embed an SDL2 window in my Tkinter GUI application?
我正在尝试通过 pySDL2 将 SDL2 窗口嵌入到我的 Tkinter 应用程序中。 如何设置我的 pySDL2 窗口、渲染器,以便我的渲染或绘图显示在嵌入的框架内?
其他示例已显示为 pygame,但我发现我的 pygame 版本目前无法正常使用 SDL2。 我知道还有其他 pygame 实现试图实现 SDL2,但与 SDL2 的兼容性对我来说是最重要的。
这种正常工作的一个例子是 Tkinter 窗口中的一个框架,它有一个屏幕,当点击一个按钮时,通过 pySDL2 API 在框架上绘制一些东西。 在尝试使用在别处找到的 pygame 解决方案时,我收到了一些不同的错误,包括 BadWindow、BadDrawable(与 X 服务器功能相关。)
这方面的例子很难找到,所以希望这个答案能帮助其他人。 在使用 pySDL2 包装器 API 时,您需要了解不同操作的 ctypes。 在某些情况下,API 已被扩展以避免这些看似神秘的操作中的一些。 提供了一个示例代码,然后在下面解释。
from sdl2 import *
import tkinter as tk
from tkinter import *
import random, ctypes
def draw():
global renderer
x1 = ctypes.c_int(random.randrange(0, 600))
y1 = ctypes.c_int(random.randrange(0, 500))
x2 = ctypes.c_int(random.randrange(0, 600))
y2 = ctypes.c_int(random.randrange(0, 500))
r = ctypes.c_ubyte(random.randrange(0, 255))
g = ctypes.c_ubyte(random.randrange(0, 255))
b = ctypes.c_ubyte(random.randrange(0, 255))
SDL_SetRenderDrawColor(renderer, r, g, b, ctypes.c_ubyte(255))
SDL_RenderDrawLine(renderer, x1, y1, x2, y2)
def sdl_update():
global window, event, renderer
SDL_RenderPresent(renderer);
if SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == SDL_QUIT:
SDL_DestroyRenderer(renderer)
SDL_DestroyWindow(window)
SDL_Quit()
# tkinter stuff #
root = tk.Tk()
embed = tk.Frame(root, width = 500, height = 500) #creates embed frame for pygame window
embed.grid(columnspan = (600), rowspan = 500) # Adds grid
embed.pack(side = LEFT) #packs window to the left
buttonwin = tk.Frame(root, width = 75, height = 500)
buttonwin.pack(side = LEFT)
button1 = Button(buttonwin,text = 'Draw', command=draw)
button1.pack(side=LEFT)
root.update()
#################################
# SDL window stuff #
SDL_Init(SDL_INIT_VIDEO)
window = SDL_CreateWindowFrom(embed.winfo_id())
renderer = SDL_CreateRenderer(window, -1, 0)
SDL_SetRenderDrawColor(renderer, ctypes.c_ubyte(255), ctypes.c_ubyte(255),
ctypes.c_ubyte(255), ctypes.c_ubyte(255))
SDL_RenderClear(renderer)
event = SDL_Event()
draw()
while True:
sdl_update()
root.update()
上面的示例显示您可以创建您的 tkinter GUI,然后初始化您的 pySDL2 代码,从您想要的任何框架或窗口创建一个窗口,在这种情况下,我选择使用我创建的框架,称为embed
。 使用可用的winfo_id()
函数(参见winfo_id()
文档),我们可以获得窗口的句柄。 draw()
函数只是使用渲染模块进行绘图。 请注意,对于需要某些类型的 SDL2 函数, ctypes
用于以 SDL2 预期的方式格式化这些参数。 在主 while 循环中,调用sdl_update()
函数检查 SDL 事件。 接着是根窗口 (tkinter) 更新调用。 我们创建的Button
将其命令链接到draw()
,当您单击此按钮时,SDL2 窗口链接到的框架中会出现一条随机着色的线。 这段代码改编自PythonNut 关于 pygame 和 tkinter 的这个 SO 答案。 该代码最初是由用户Alex Sallons 编写的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.