我对kivy相对较新,并且在某些图像和按钮图像无法正确加载时出现间歇性问题,即使使用相同图像为同一图像正确加载其他小部件也是如此。我认为线程和kivy绘图不能很好地协同工作是一个问题。对于下面的代码重现问题线程是不必要的,但在完整的应用程序中,加载所有图像块太长时间。谢谢你的帮助。
from kivy.app import App
from kivy.core.window import Window
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivy.effects.opacityscroll import OpacityScrollEffect
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import AsyncImage, Image
from kivy.uix.screenmanager import ScreenManager, Screen
from _functools import partial
from threading import Thread
class resultLine(RelativeLayout):
def __init__(self, title, coverUrl, showid):
super(RelativeLayout, self).__init__(size_hint=(None, None), size=(Window.width * 0.945, 0.12 * Window.height))
self.cover = AsyncImage(source=coverUrl, loading_image='loading.gif', error_image='../../tv.png',
size=(0.2 * self.width, 0.85 * self.height), pos=(0, 0.125 * self.height), size_hint=(None, None),
nocache=True)
self.cover.width = Window.width * 0.2
self.nameButton = Button(text='', size=(self.width, self.height), x=0, size_hint=(None, None), opacity=0.85,
background_normal='../../button.png', background_down='../../button_pressed.png')
fontSize=0.05 * Window.width
self.nameTag = Label(text=' ' + title, font_size=fontSize, width=Window.width * 0.945,
height=self.height, x=0, y=0.05*self.height,
size_hint=(None, None), valign='middle', halign='left', opacity=0.85,
padding_x=Window.width * 0.025)
self.nameTag.text_size = self.nameTag.size
self.nameTag.shorten = True
self.nameTag.shorten_from = 'right'
self.nameTag.split_str = ' ...'
self.nameButton.bind(on_press=self.doNameButtonPress)
self.nameButton.bind(on_release=self.doNameButtonRelease)
self.add_widget(self.nameButton)
self.add_widget(self.nameTag)
self.add_widget(self.cover)
self._trigger_layout()
def doNameButtonPress(self, instance):
self.nameTag.x += 0.01 * self.width
self.nameTag.y -= 0.1 * self.height
# self.cover.pos_hint = {'x':0.01, 'y':0.025}
self.cover.x += 0.01 * self.width
self.cover.y -= 0.1 * self.height
def doNameButtonRelease(self, instance):
self.nameTag.x -= 0.01 * self.width
self.nameTag.y += 0.1 * self.height
# self.cover.pos_hint = {'x':0, 'y':0.1}
self.cover.x -= 0.01 * self.width
self.cover.y += 0.1 * self.height
class ShowSelector(Screen):
bottomLayout = ScrollView(size=(0.95 * Window.width, Window.size[1] * 0.875), pos=(0.025 * Window.width, 0),
size_hint=(None, None), bar_margin=-0.0125 * Window.width, effect_cls=OpacityScrollEffect)
scrollLayout = GridLayout(cols=1, size_hint=(None, None), height=Window.height, spacing=Window.height * .01)
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.add_widget(self.bottomLayout)
self.bottomLayout.add_widget(self.scrollLayout)
self.scrollLayout.bind(minimum_height=self.scrollLayout.setter('height'))
self.scrollLayout.height = (Window.height * 0.12 + self.scrollLayout.spacing[1]) * 100
Thread(target=self.action).start()
def action(self):
for i in xrange(1,100):
self.scrollLayout.add_widget(resultLine(str(i), '1.jpg', 0))
class theApp(App):
smMain =ScreenManager()
selectorScreen = ShowSelector(name='showsel')
def build(self):
self.smMain.add_widget(self.selectorScreen)
return self.smMain
thisApp=theApp()
thisApp.run()
答案 0 :(得分:6)
我明白了。万一其他人遇到这个问题。对GUI的任何更改都必须在主线程中完成。您可以通过将@mainthread放在函数定义上方的行上来强制执行函数。例如:
from kivy.clock import mainthread
@mainthread
def add something(self, w):
self.add_widget(w)
你必须“导入主线程”才能工作。