当前位置: 首页 > 知识库问答 >
问题:

如何在我的Tkinter GUI应用程序中嵌入SDL2窗口?

索正豪
2023-03-14

我正试图通过pySDL2将SDL2窗口嵌入到Tkinter应用程序中。如何设置pySDL2窗口、渲染器,使渲染或绘图显示在嵌入的帧中?

其他例子已经显示了pyplay,但是我发现我的pyplay版本目前不能正确地与SDL2一起工作。我知道还有其他pyplay的实现试图实现SDL2,但是与SDL2的兼容性对我来说是最重要的。

一个正确工作的例子是Tkinter窗口中的一个帧,该窗口有一个屏幕,当单击按钮时,该屏幕通过PySDL2API将某些内容绘制到该帧。在尝试使用其他地方找到的pygame解决方案时,我收到了一些不同的错误,包括BadWindow、BadDrawable(与X服务器功能相关)

共有1个答案

董子航
2023-03-14

这方面的例子很难找到,所以希望这个答案能帮助其他人。在使用pySDL2包装器API时,您需要了解不同操作的CType。在某些情况下,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()

上面的例子显示,您可以创建您的tkinterGUI,然后初始化您的pySDL2代码,从您想要的任何框架或窗口创建一个窗口,在这种情况下,我选择使用我创建的框架,称为embed。使用可用的winfo_id()函数(参见tkinter文档),我们可以获得窗口的句柄。函数仅仅使用渲染模块进行绘图。请注意,对于期望某些类型的SDL2函数,使用ctype以SDL2期望的方式格式化这些参数。在主而循环中,调用sdl_update()函数检查SDL事件。之后是根窗口(tkinter)更新调用。我们创建的Button将其命令链接到Drew(),当您单击此按钮时,SDL2窗口链接到的框架中会出现随机颜色的线条。这段代码改编自PythonNut关于pyplay和tkinter的这个SO回答。该代码最初是由用户Alex Sallons编写的。

 类似资料:
  • 问题内容: 我正在寻找一种将Google JavaScript引擎V8嵌入我的Java应用程序中的解决方案。 你有解决办法吗? 问题答案: 您可以使用J2V8 https://github.com/eclipsesource/J2V8。它甚至可以在Maven Central中使用 。 以下是您好,世界!使用J2V8的程序。 您将需要在pom.xml中指定平台。J2V8当前支持win32_x86,m

  • 问题内容: 我想在我的Tkinter主窗口中嵌入一个终端。我想有一个终端(基于Bash的终端)可以运行的子窗口。我还希望能够让我的程序与终端交互,至少我想阅读当前的工作目录和/或设置它。 我不知道这是否真的不可能。过去我可以使用Perl / Tk做到这一点,所以也许可以在这里复制它。 我当时使用的代码是这样的: Tk主窗口在哪里。 当然,我完全同意Bryan的观点:尽管我以前从未使用GUI库进行编

  • 问题内容: 在Elasticsearch 2.x中,我使用以下代码来启动嵌入式Node进行测试: 这不再编译。如何在5.x中启动嵌入式节点? 问题答案: 不再正式支持嵌入elasticsearch,它比2.x中的要复杂一些,但可以。 您需要添加一些依赖项: 然后启动一个这样的节点:

  • 我制作了一个web应用程序,允许任何用户使用套接字进行聊天。现在我想用jitsi打视频电话。 我的应用程序上的所有用户都是经过身份验证的用户。当用户单击聊天窗口中的call按钮时,我想使用REST API调用在新窗口中启动Jitsi Meet Conference。 任何正确方向的指导或指针都将受到高度赞赏。

  • 我有一个很大的swing应用程序,我想把javafx嵌入其中。我多次尝试这样做(通过遵循oracle教程等),但只有在声明一个新的JFrame以使用JFXPanel组件时才成功。但是,我不想使用新的框架,我想将我的Javafx代码合并到swing应用程序的根JFrame中。 我们可以将javaFX组件嵌入到JPanel而不是JFrame中吗?如果答案是肯定的,为什么我没有成功?