python 3.x kivy:动态添加小部件到scrollview

时间:2017-12-07 11:19:37

标签: python kivy

我是kivy的新手并试图创建一个滚动视图,其中充满了几个小部件。那种作品.. 但是订单项本身经常会丢失自己的小部件,我经常会收到此错误:

[CRITICAL] [时钟]警告,在下一帧之前完成了太多的迭代。检查您的代码,或增加Clock.max_iteration属性

我读了很多“时钟”,阻止了mainthread等。我试图通过使用不同的线程解决它..但仍然缺少小部件。

附上代码和图片。非常感谢帮助!! THX!

widgets missing..

my controller.kv

#:kivy 1.0

<Controller>:

    size_hint: 1., 1.
    pos_hint: {'center_x': .5, 'center_y': .5}
    do_default_tab: False


    tab1_pgbar: tab1_pgbar
    layout_content: layout_content
    tab1_refresh_btn: tab1_refresh_btn

    TabbedPanelItem:
        id: tab1
        text: 'Browse'

        BoxLayout:
            id: bl
            orientation: 'vertical'

            ScrollView:
                size_hint: 1.0,0.7              

                GridLayout:
                    id: layout_content
                    size_hint_y: None
                    height: self.minimum_height                
                    cols: 1
                    row_default_height: '100dp'
                    row_force_default: True
                    spacing: 0, 5            

            BoxLayout:
                size_hint: 1.0,None
                height: 25              

                ProgressBar:
                    size_hint: 1.0,1.0  
                    id: tab1_pgbar 
                    max: 1000

                Button:
                    id: tab1_refresh_btn    
                    text: 'Refresh'             
                    size: 100,25
                    on_release: root.refresh()   

我的kivyMain.py

import kivy
kivy.require('1.10.0')

from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.clock import mainthread

import time
import threading


class myJobEntry(BoxLayout):
    def __init__(self):
        super(myJobEntry, self).__init__()       


    def addStuff(self,runindex,program):   
        b1 = Button(text=runindex,size_hint=(None,1.0),width=100)
        b2 = TextInput(text=program,height=80)

        hbox1 = BoxLayout(orientation='horizontal')      
        for i in range(10):
            hbox1.add_widget(Button(text='{}'.format(i)))


        vbox1 = BoxLayout(orientation='vertical')
        vbox1.add_widget(hbox1)
        vbox1.add_widget(b2)

        self.add_widget(b1)
        self.add_widget(vbox1)


class Controller(TabbedPanel):
    '''Create a controller that receives a custom widget from the kv lang file.
    Add an action to be called from the kv lang file.
    '''    
    layout_content = ObjectProperty()
    tab1_refresh_btn = ObjectProperty()
    tab1_pgbar = ObjectProperty() 
    text_input = ObjectProperty() 

    def addSeveralObjects(self):
        self.tab1_pgbar.value = 0
        self.layout_content.enabled=False

        for i in range(100):              
            myObj = myJobEntry()
            myObj.addStuff('{}'.format(i),'i')            
            self.layout_content.add_widget(myObj)                            
            self.updateBar()


    def refresh(self):        
        self.tab1_refresh_btn.enabled = False
        self.tab1_pgbar.value = 1        

        mythread = threading.Thread(target=self.addSeveralObjects)
        mythread.start()        

        self.resetRefreshButton()


    def resetRefreshButton(self):
        self.tab1_refresh_btn.text = 'Last Refresh: {}'.format(time.ctime())
        self.tab1_refresh_btn.enabled = True


    def updateBar(self):
        self.tab1_pgbar.value += 1

class ControllerApp(App):

    def build(self):       
        return Controller()

if __name__ == '__main__':
    ControllerApp().run()

1 个答案:

答案 0 :(得分:1)

我猜问题是你的线程,更好的选择是使用kivy Clock对象:

...
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.metrics import dp
...

class Controller(TabbedPanel):
    '''Create a controller that receives a custom widget from the kv lang file.
    Add an action to be called from the kv lang file.
    '''
    layout_content = ObjectProperty()
    tab1_refresh_btn = ObjectProperty()
    tab1_pgbar = ObjectProperty()
    text_input = ObjectProperty()
    i = 0
    h = NumericProperty(0)

    def addSeveralObjects(self, *args):
        self.layout_content.enabled = False
        myObj = myJobEntry()
        myObj.addStuff('{}'.format(self.i), '{}'.format(self.i))
        self.layout_content.add_widget(myObj)
        if self.i % 4 == 0:
            self.h += dp(420)
        self.updateBar()
        self.i += 1
        if self.i >= 100:
            self.clock.cancel()

    def refresh(self):
        self.tab1_refresh_btn.enabled = False
        self.clock =Clock.schedule_interval(self.addSeveralObjects, .05)
        self.resetRefreshButton()

    def resetRefreshButton(self):
        self.tab1_refresh_btn.text = 'Last Refresh: {}'.format(time.ctime())
        self.tab1_refresh_btn.enabled = True

    def updateBar(self):
        self.tab1_pgbar.value += 1
...

在你的kv:

<Controller>:
    ...
    TabbedPanelItem:
        ...
        BoxLayout:
            ...
            ScrollView:
                size_hint: 1.0,0.7
                GridLayout:
                    id: layout_content
                    height: root.h
                    size_hint_y: None
                    cols: 1
                    row_default_height: '100dp'
                    row_force_default: True
                    spacing: 0, 5
            ...
        ...
     ...
 ...