Updating Progress Bar displayed in Popup in Kivy

时间:2018-09-18 19:47:40

标签: python kivy

How do you update a progress bar that is displayed in Kivy. In the following example I get AttributeError: 'super' object has no attribute '__getattr__'. The issue is in the following line

self.ids.progress.value = value

I can see why since the progressBar widget is in <LoadingPopup> and not <MainScreen> but after trying several different things I can't reference the progressBar widget in <LoadingPopup> from the do_update method.

Thanks in advance

import threading
from functools import partial

from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty
from kivy.uix.spinner import Spinner
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.popup import Popup



Builder.load_string('''

<LoadingPopup>:
    title: "Popup"
    size_hint: None, None
    size: 400, 400
    auto_dismiss: False

    BoxLayout:
        orientation: "vertical"
        ProgressBar:
            id: progress
            size_hint: (1.0, 0.06)

<MainScreen>:
    BoxLayout:
        orientation: 'vertical'

        Spinner:
            id: first
            text: ' First Number'
            values: ['1','2','3','4','5','6','7','8','9']

        Spinner:
            id: second
            text: ' Second Number'
            values: ['1','2','3','4','5','6','7','8','9']

        Label:
            id: result
            text: ' Result'
            color: 0,0,0,1
        Button:
            id: res
            on_press: root.doit_in_thread(first.text,second.text)
            text: 'Multiply'


''')

class LoadingPopup(Popup):

    def __init__(self, obj, **kwargs):
        super(LoadingPopup, self).__init__(**kwargs)


class MainScreen(FloatLayout):
    changet = StringProperty()
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)

    def doit_in_thread(self, fir, sec):
        popup = LoadingPopup(self)
        popup.open()
        threading.Thread(target=partial(self.onMul, fir, sec, popup)).start()

    def do_update(self, value, text, *args):
        self.ids.progress.value = value
        self.ids.result.text = text

    def onMul(self,fir,sec, popup):
        a = (int(fir)*int(sec))
        print(a)
        b = 0
        old_value = 0
        endRange = 1000000
        for i in range(endRange):
            progress = int(((i+1)*100)/endRange)
            if progress != old_value and progress % 5 == 0:
                text = str(b*(int(fir)*int(sec)))
                Clock.schedule_once(partial(self.do_update, progress, text))
                old_value = progress
            b+=1

        popup.dismiss()

class TestApp(App):
    def build(self):
        return MainScreen()

if __name__ == "__main__":
    TestApp().run()

2 个答案:

答案 0 :(得分:0)

One way to do it, is to keep a reference of the popup so you can address it later:

def __init__(self, **kwargs):
    super(MainScreen, self).__init__(**kwargs)
    self.popup = LoadingPopup(self)

def doit_in_thread(self, fir, sec):
    self.popup.open()
    threading.Thread(target=partial(self.onMul, fir, sec, self.popup)).start()

def do_update(self, value, text, *args):
    self.popup.ids.progress.value = value
    self.ids.result.text = text

答案 1 :(得分:0)

Python代码

  1. popup的所有引用替换为self.popup,以便您可以在MainScreen类中的方法中访问它。
  2. self.ids.progress.value替换为self.popup.ids.progress.value
  3. a = (int(fir)*int(sec)起,将str(b*(int(fir)*int(sec)))替换为str(b * a)
  4. 不需要将popup传递给onMul方法,而使用self.popup来访问它

摘要

class MainScreen(FloatLayout):
    changet = StringProperty()

    def doit_in_thread(self, fir, sec):
        self.popup = LoadingPopup(self)
        self.popup.open()
        threading.Thread(target=partial(self.onMul, fir, sec)).start()

    def do_update(self, value, text, *args):
        self.popup.ids.progress.value = value
        self.ids.result.text = text

    def onMul(self, fir, sec):
        a = (int(fir)*int(sec))
        print(a)
        b = 0
        old_value = 0
        endRange = 1000000
        for i in range(endRange):
            progress = int(((i+1)*100)/endRange)
            if progress != old_value and progress % 5 == 0:
                text = str(b*(int(fir)*int(sec)))
                # text = str(b * a)
                print("\ttext=", text)
                Clock.schedule_once(partial(self.do_update, progress, text))
                old_value = progress
            b+=1
    self.popup.dismiss()

kv文件

result不可见,因为“标签”小部件的默认背景颜色为黑色,并且result的文本颜色也设置为黑色,color: 0,0,0,1。因此,请删除color: 0,0,0,1

摘要

    Label:
        id: result
        text: ' Result'

输出

Img01