python - Virtualbox Ubuntu pygame.display.set_mode 在交互式 python 中的行为与解释文件时的行为不同

标签 python ubuntu tkinter pygame virtualbox

我在虚拟机中运行 Ubuntu(主机操作系统是 Windows 7)。我正在使用Python 2.7。以下代码在各种情况下都会表现得很奇怪:

def set_screen():
    global screen
    screen = pygame.display.set_mode((600,600))

def set_tk():
    global root
    global embed
    global tkwin
    root = tk.Tk()
    root.wm_title("OpenBox")
    embed = tk.Frame(root, width = 600, height = 600)
    embed.pack(side=LEFT)
    windowid = embed.winfo_id()
    tkwin = tk.Frame(root, width = 200, height = 600)
    tkwin.pack(side=RIGHT)
    os.environ['SDL_WINDOWID'] = str(windowid)
    if sys.platform == "win32":
        os.environ['SDL_VIDEODRIVER'] = 'windib'
    if len(sys.argv) > 1:
        if sys.argv[1] == "-f":
            root.attributes("-fullscreen", True)

set_tk()
pygame.init()
pygame.display.init()
set_screen()

这意味着创建一个 tkinter 窗口,其中嵌入了 pygame 显示。这是我遇到的一些不同行为:

窗口

在 Windows 上,代码运行良好。正如预期的那样,使用嵌入式 pygame 显示打开 tkinter 框架。

VirtualBox Ubuntu 解释文件

在 Ubuntu 上,当我运行程序文件(输入“python”)时,程序无法运行,在调用 pygame.display.set_mode 时会触发此错误(如果我不设置操作系统,则不会引发该错误)将 pygame 窗口嵌入到 tkinter 的环境):

X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  3 (X_GetWindowAttributes)
  Resource id in failed request:  0x1600004
  Serial number of failed request:  53
  Current serial number in output stream:  54

VirtualBox Ubuntu 交互式 python

我可以输入与键入“python script.py”时不起作用的完全相同的代码,然后将其输入到交互式 python 中,该代码将起作用。交互式 python 和在文件上运行 python 之间的第一个主要区别是时间,所以我首先尝试在调用 display.set_mode 之前添加 time.sleep() ,但这没有什么区别。另一个主要区别是它在不停止程序的情况下处理异常,所以我也尝试了 try 和 except 来测试这一点,但它没有解决问题。我也不能只在交互式 python 中运行整个程序(也许通过 stdin 和 stdout 上的 pexpect 或子进程句柄提供它),因为还有 tkinter 线程为我的 pygame 显示维护 gui 侧边栏,并且它们在交互式中不起作用 python 。

VirtualBox Ubuntu 执行

我也尝试过使用exec调用display.set_mode,希望这个执行环境可能有所不同。但是,调用 exec set_mode 会产生与仅调用 set_mode 相同的结果,这意味着它在交互式 Python 中有效,但在读取文件时则无效。

VirtualBox Ubuntu 交互式 python 函数

代码在函数内的行为也不同。在交互式Python中,在一个函数中运行所有这些代码将使其无法工作。当我试验哪些代码在函数内部有效和无效时,我发现必须在函数外部输入的代码是 pygame.display.set_mode。奇怪的是,当我将 display.set_mode 单独放在一个函数中而没有其他代码时,它起作用了。当 python 从文件中读取代码时,上述所有情况都会引发错误。


我还尝试以交互方式定义所有显示信息,然后对其进行腌制以供我的主程序加载和访问。然而,由于 pygame.surface 对象无法被 pickle,所以这不起作用。


为什么这段代码在某些环境中可以工作,但在其他环境中却不能?有没有办法让这段代码在 Virtualbox Ubuntu 中成功?

最佳答案

Tkinter 需要 mainloop() 才能工作。
如果没有 mainloop(),Tkinter 会立即结束工作。

Windows 和 Interactive Python 可能不会打扰这个,或者它们使用自己的主循环来保持 Tkinter 运行。

还有另一个问题:mainloop() 使 Tkinter 保持工作状态,但它不允许在 mainloop() 下面运行任何行(在 mainloop() 之前) (和 Tkinter)结束工作)。因此,我使用 after() 100 毫秒后运行 set_screen() - 当 mainloop() 开始工作时。

使用 Python 2.7.5 在(非虚拟)Linux Mint 16(基于 Ubuntu)上进行测试

from Tkinter import *
import Tkinter as tk
import pygame
from pygame.locals import *
import os

def set_screen():
    global screen

    pygame.init()
    pygame.display.init()
    screen = pygame.display.set_mode((600,600))
    screen_rect = screen.get_rect()
    pygame.draw.circle(screen, (255,0,0), screen_rect.center, 50 )
    pygame.display.flip()


def set_tk():
    global root
    global embed
    global tkwin
    root = tk.Tk()
    root.wm_title("OpenBox")
    embed = tk.Frame(root, width = 600, height = 600)
    embed.pack(side=LEFT)
    windowid = embed.winfo_id()
    tkwin = tk.Frame(root, width = 200, height = 600)
    tkwin.pack(side=RIGHT)
    os.environ['SDL_WINDOWID'] = str(windowid)
    #~ if sys.platform == "win32":
        #~ os.environ['SDL_VIDEODRIVER'] = 'windib'
    #~ if len(sys.argv) > 1:
        #~ if sys.argv[1] == "-f":
            #~ root.attributes("-fullscreen", True)         
    root.after(100,set_screen)
    root.mainloop()

set_tk()

关于python - Virtualbox Ubuntu pygame.display.set_mode 在交互式 python 中的行为与解释文件时的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24047852/

相关文章:

linux - 根据文件夹的日期和文件的日期将文件移动到linux中各自的文件夹

php - 在 PHP 7.2 Ubuntu 上运行 composer install 时出错

python - 为什么我的按钮的命令在我创建按钮时立即执行,而不是在我单击它时执行?

python - vim:.vimrc 无法正确加载 python 文件

python - 使用 django 和 django rest 框架时的异常处理

python - 将字符串传递给数据框 iloc

python - 在 ubuntu 12.04 中编译 statsmodels 示例

python - 每次按下 `tkinter` 中的按钮时,如何为标签获取不同的值?

python - tksnack-尝试创建波形

python - 将路径、文件名、ext 字符串分成三个单独的变量的最稳定和Pythonic 跨平台方法是什么?