大家好我是在python中编写Gtk + GUI应用程序,它使用onvif Iam在应用程序中使用异步调用SOAP服务来播放视频和移动摄像头。但是当我按下其中一个按钮移动摄像机视频时会挂起一秒钟然后在按下按钮时它没问题但是当它被释放时它会再次挂起。
class ContinuousMove(threading.Thread):
def __init__(self,onvif_service):
threading.Thread.__init__(self)
self.start()
self.onvif_service=onvif_service
self.position=self.onvif_service.get_client().factory.create('ns4:PTZVector')
self.profileToken=self.onvif_service.get_client().factory.create('ns4:ReferenceToken')
self.speed=self.onvif_service.get_client().factory.create('ns4:PTZSpeed')
self.timeout=self.onvif_service.get_client().factory.create('ns4:Timeout')
self.executor=concurrent.futures.ThreadPoolExecutor(max_workers=1)
def move(self,x,y,zoom):
future = self.executor.submit(self.__move__,x,y,zoom)
def __move__(self,x,y,zoom):
self.position.PanTilt._x=x
self.position.PanTilt._y=y
self.position.Zoom._x=zoom
self.profileToken='media_profile1'
self.onvif_service.get_client().service.ContinuousMove(self.profileToken,self.position)
如您所见,我使用了conncurent.future模块及其类ThreadPoolExecutor进行异步调用
接下来,我在播放器类中创建了ContinMove类的实例,该类扩展了Gtk.Window 然后我创建按钮并设置事件回调。
class player(Gtk.Window):
#bunch of functions
def __init__(self):
Gtk.Window.__init__(self):
self.gui_init()
self.camera=ContinuousMove(onvif_service)
self.player=Player(self.previewArea)#class which constructs gstreamer pipeline and renders it on previewArea
def gui_init(self):
self.previewArea=Gtk.RenderArea()
self.buttonDown=Gtk.Button("DOWN")
self.buttonDown.connect("pressed",self.on_down_pressed)
def on_down_pressed(self,btn):
#instance of ContinuousMove
self.Camera.move(0,-0.1,0)
app=player()
app.show_all()
Gtk.main()
如果你能指出我在这里做错了什么以及为什么视频会挂起,我将不胜感激。
没有粘贴整个代码,因为它非常庞大我希望你能从中理解这个问题。
我添加了我的Player对象和RenderArea对象的init,因为我认为它与此问题相关。 我初始化Player对象并将其发送到RenderArea,以便它可以向其呈现视频。 现在问题是可以以某种方式按钮小部件块RenderArea小部件吗?
我将详细说明会发生什么。例如,当我按下DOWN按钮时,它会冻结视频,因为它看起来像是跳了几帧。几乎所有东西都干了,似乎没什么用。问题不是RenderArea也不是Gstreamer问题是移动方法和/或按钮按下事件。
答案 0 :(得分:0)
on_down_pressed()
看起来像一个事件处理程序。如果它阻塞,则GUI“冻结”(不响应)。
with
- 语句在退出时调用executor.shutdown(wait=True)
来阻止该方法。
要避免在Camera.move()
方法中阻止,请将ThreadPoolExecutor()
的创建移至__init__()
,并仅调用不会阻止executor.submit()
的{{1}}。