我正在制作一个小程序,它从一个网络商店获得最新的收入,如果它比以前的数量多,我使用Pyglet,但是我会出错,因为它不是从主线程调用的。我想知道如何在主线程上调用一个方法。请参阅下面的错误:
“导入pyglet.app的线程”RuntimeError:必须从导入pyglet.app的线程调用EventLoop.run()
def work ():
threading.Timer(5, work).start()
file_Name = "save.txt"
lastRevenue = 0
data = json.load(urllib2.urlopen(''))
newRevenue = data["revenue"]
if (os.path.getsize(file_Name) <= 0):
with open(file_Name, "wb") as f:
f.write('%d' % newRevenue)
f.flush()
with open(file_Name, "rb") as f:
lastRevenue = float(f.readline().strip())
print lastRevenue
print newRevenue
f.close()
if newRevenue > lastRevenue:
with open(file_Name, "wb") as f:
f.write('%f' % newRevenue)
f.flush()
playsound()
def playsound():
music = pyglet.resource.media('cash.wav')
music.play()
pyglet.app.run()
work()发布于 2016-10-12 12:55:33
这并不特别奇怪。work作为一个单独的线程执行,与导入pyglet的线程不同。
导入pyglet.app时,设置了很多上下文变量,什么都没有。我没有说什么,因为我实际上并没有费心去更深入地检查它的实际设置。
而且OpenGL不能在它自己的上下文(它所在的主线程)之外执行。在那里,您不允许从相邻的线程中窥探OpenGL。如果这有意义的话。
但是,如果创建自己的.run()函数并使用基于类的激活Pyglet的方法,则可以从线程启动GUI。
这是一个如何设置它的工作示例:
import pyglet
from pyglet.gl import *
from threading import *
# REQUIRES: AVBin
pyglet.options['audio'] = ('alsa', 'openal', 'silent')
class main(pyglet.window.Window):
def __init__ (self):
super(main, self).__init__(300, 300, fullscreen = False)
self.x, self.y = 0, 0
self.bg = pyglet.sprite.Sprite(pyglet.image.load('background.jpg'))
self.music = pyglet.resource.media('cash.wav')
self.music.play()
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def render(self):
self.clear()
self.bg.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
if not self.music.playing:
self.alive = 0
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
class ThreadExample(Thread):
def __init__(self):
Thread.__init__(self)
self.start()
def run(self):
x = main()
x.run()
Test_One = ThreadExample()请注意,您仍然必须从线程中启动实际的GUI代码。
我强烈建议你这样做
由于混合线程和GUI调用是一种滑坡,我建议您走一条更谨慎的道路。
from threading import *
from time import sleep
def is_main_alive():
for t in enumerate():
if t.name == 'MainThread':
return t.isAlive()
class worker(Thread):
def __init__(self, shared_dictionary):
Thread.__init__(self)
self.shared_dictionary
self.start()
def run(self):
while is_main_alive():
file_Name = "save.txt"
lastRevenue = 0
data = json.load(urllib2.urlopen(''))
newRevenue = data["revenue"]
if (os.path.getsize(file_Name) <= 0):
with open(file_Name, "wb") as f:
f.write('%d' % newRevenue)
f.flush()
with open(file_Name, "rb") as f:
lastRevenue = float(f.readline().strip())
print lastRevenue
print newRevenue
f.close()
if newRevenue > lastRevenue:
with open(file_Name, "wb") as f:
f.write('%f' % newRevenue)
f.flush()
#playsound()
# Instead of calling playsound() here,
# set a flag in the shared dictionary.
self.shared_dictionary['Play_Sound'] = True
sleep(5)
def playsound():
music = pyglet.resource.media('cash.wav')
music.play()
pyglet.app.run()
shared_dictionary = {'Play_Sound' : False}
work_handle = worker(shared_dictionary)
while 1:
if shared_dictionary['Play_Sound']:
playsound()
shared_dictionary['Play_Sound'] = False
sleep(0.025)这是你要找的东西的草稿。
基本上是某种事件/标志驱动的后端,线程和GUI可以用来相互通信。
本质上,您有一个工作线程(就像以前一样),它每5秒检查一次您想要的任何文件,如果它检测到newRevenue > lastRevenue,它将将一个特定的标志设置为True。您的主循环将检测到此更改,播放声音并将标志恢复为False。
我不是故意在这里包括任何错误处理,我们是来帮助而不是创建完整的解决方案的。我希望这能帮助你朝着正确的方向前进。
https://stackoverflow.com/questions/39995447
复制相似问题