我在虚拟机(主机操作系统是Windows 7)中运行Ubuntu。我正在使用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()


这意味着创建一个嵌入了pygame显示的tkinter窗口。这是我遇到的各种行为:

视窗

在Windows上,代码工作正常。如预期的那样,使用嵌入式pygame显示器打开tkinter框架。

VirtualBox Ubuntu解释文件

在Ubuntu上,当我运行程序文件(键入“ python”)时,该程序无法正常工作,并在调用pygame.display.set_mode时触发了此错误(如果我未设置嵌入的os环境,则不会引发该错误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(),但这没有什么区别。另一个主要区别是它在不停止程序的情况下处理异常,因此我也尝试了“除”测试以外的其他方法,它并没有解决问题。我也不能只在交互式python中运行整个程序(也许通过stdin和stdout上的pexpect或子进程句柄来喂它),因为也有tkinter线程为我的pygame显示维护了gui侧边栏,并且它们不能在交互式中工作蟒蛇。

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对象进行腌制,因此无法正常工作。



为什么此代码在某些环境中有效,而在另一些环境中无效?有没有办法使此代码在Virtualbox Ubuntu中成功?

最佳答案

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

Windows和Interactive Python可能不会对此困扰,或者它们使用自己的mainloop来保持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/

10-12 13:03