我在python 2.7.15中使用kivy 1.11.0。
#-*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from kivy.lang import Builder
Builder.load_string("""
<InitScreen>:
AnchorLayout:
anchor_x:"center"
anchor_y:"center"
Label:
text:"init"
<WaitScreen>:
Image:
id:charactor
pos_hint:{'center_x':.5,'y':0 }
size_hint:1,1
source:'./wait1.png'
""")
class Charactor(Image):
pass
class InitScreen(Screen):
pass
class WaitScreen(Screen):
def __init__(self, **kwargs):
super(WaitScreen, self).__init__(**kwargs)
class View(App):
sm = ScreenManager()
cli = mqtt.Client(protocol=mqtt.MQTTv311)
def __init__(self, **kwargs):
super(View, self).__init__(**kwargs)
def build(self):
self.sm.add_widget(InitScreen(name='init'))
self.sm.current='init'
return self.sm
def on_start(self):
self.cli.on_connect = self.on_connect
self.cli.on_message = self.on_message
self.cli.connect('localhost', port=1883, keepalive=60)
self.cli.loop_start()
def on_connect(self,client, userdata, flags, respons_code):
print('status {0}'.format(respons_code))
client.subscribe('get/test')
def on_message(self,client, userdata, msg):
self.changeScreen()
def changeScreen(self,**kwargs):
self.sm.add_widget(WaitScreen(name='wait'))
self.sm.current='wait'
if __name__ == '__main__':
View().run()
如果收到消息(on_message),请更改屏幕
但出现了错误
Fatal Python error: (pygame parachute) Segmentation Fault
我认为已检测到错误原因 有图像。 当on_message加载图像源时,发生错误 我认为paho.mqtt回调(on_message,on_connect)值得怀疑
因为当self.changeScreen()处于def on_start,def构建状态时,未发生错误
下面的代码是没有发生错误
class View(App):
sm = ScreenManager()
cli = mqtt.Client(protocol=mqtt.MQTTv311)
waitflag = False
def __init__(self, **kwargs):
super(View, self).__init__(**kwargs)
def build(self):
self.sm.add_widget(InitScreen(name='init'))
self.sm.current='init'
return self.sm
def on_start(self):
self.cli.on_connect = self.on_connect
self.cli.on_message = self.on_message
self.cli.connect('localhost', port=1883, keepalive=60)
self.cli.loop_start()
Clock.schedule_interval(self.changeScreen, 1)
def on_connect(self,client, userdata, flags, respons_code):
print('status {0}'.format(respons_code))
client.subscribe('get/test')
def on_message(self,client, userdata, msg):
self.waitflag = True
def changeScreen(self,dt):
if self.waitflag:
self.sm.add_widget(WaitScreen(name='wait'))
self.sm.current='wait'
self.waitflag = False
但是这段代码感觉很糟糕。因为如果WaitScreen不使用Image source,就不会发生错误
请告诉我如何避免错误。 我想使用上层代码
答案 0 :(得分:1)
此问题已解决。
from kivy.clock import mainthread
和
@mainthread
def on_message(self,client, userdata, msg):
仅此而已
答案 1 :(得分:0)
根本原因是加载图像,即您的应用程序正在等待加载图像。
用Image
替换AsyncImage
将防止您的应用程序等待图像加载。但是在加载4到5张图片/ WaitScreen之后,它将以IndexError: list index out of range
崩溃。
number
类型的NumericProperty
,因为屏幕名称在ScreenManager中必须是唯一的。有关详细信息,请参见代码段,示例和输出。在示例中,我们使用在线经纪人,如iot.eclipse.org
上的经纪人。
def on_start(self):
self.number = 0
self.cli = mqtt.Client(protocol=mqtt.MQTTv311)
self.cli.on_connect = self.on_connect
self.cli.on_message = self.on_message
self.cli.connect("iot.eclipse.org", port=1883, keepalive=60)
Clock.schedule_interval(self.loop, 0.5) # call loop every 0.5 seconds
def loop(self, dt):
# manually call the Paho MQTT loop() method
self.cli.loop(0.1) # blocks for 100 ms
name
在ScreenManager中 必须唯一 的屏幕名称。 这是ScreenManager.current的名称。
name是StringProperty,默认为‘>
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.clock import Clock
Builder.load_string("""
<InitScreen>:
AnchorLayout:
anchor_x:"center"
anchor_y:"center"
Label:
text:"init"
<WaitScreen>:
Image:
id: charactor
pos_hint: {'center_x':.5, 'y':0}
size_hint: 1, 1
source: './wait.jpeg'
""")
class Charactor(Image):
pass
class InitScreen(Screen):
pass
class WaitScreen(Screen):
pass
class View(App):
def build(self):
self.number = NumericProperty(0)
self.sm = ScreenManager()
self.sm.add_widget(InitScreen(name='init'))
return self.sm
def on_start(self):
self.number = 0
self.cli = mqtt.Client(protocol=mqtt.MQTTv311)
self.cli.on_connect = self.on_connect
self.cli.on_message = self.on_message
self.cli.connect("iot.eclipse.org", port=1883, keepalive=60)
Clock.schedule_interval(self.loop, 0.5) # call loop every 0.5 seconds
def loop(self, dt):
# manually call the Paho MQTT loop() method
self.cli.loop(0.1) # blocks for 100 ms
def on_connect(self, client, userdata, flags, response_code):
print("\non_connect:")
print("\tclient={0}, userdata={1}, flags={2}, response_code={3}".format(client, userdata, flags, response_code))
client.subscribe("$SYS/#")
def on_message(self, client, userdata, msg):
print("\non_message:")
print("\tclient={0}, userdata={1}, msg={2}".format(client, userdata, msg))
print("\tmsg.topic={0}, msg.payload={1}".format(msg.topic, msg.payload))
self.changeScreen()
self.number += 1
def changeScreen(self):
print("\nchangeScreen:")
print("\tnumber={}".format(self.number))
screen_name = 'wait{}'.format(self.number)
print("\tscreen_name={}".format(screen_name))
self.sm.add_widget(WaitScreen(name=screen_name))
self.sm.current = screen_name
def on_stop(self):
# stop the loop before exit
self.cli.loop_stop()
if __name__ == '__main__':
View().run()