我在虚拟机中运行 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/