滚动视图问题-将行添加到滚动视图后,scroll_y不更新

时间:2019-09-02 14:34:49

标签: python kivy

我注意到当将新行添加到现有的滚动视图时,scroll_y值将重置为0.0。这是一个问题,因为在将行添加到现有的滚动视图时,我需要知道新的scroll_y值。

在将新行添加到scrollview之后,我可以手动向下滚动鼠标滚轮(通过滚动停止)来获取新的scroll_y值。但是,我需要在代码向视图中添加新行并将滚动条向上移动之后立即知道新的scroll_y值,如下例所示。

在将新行添加到滚动视图并且使用代码移动了条形之后,如何获取新的scroll_y值?

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.graphics import Line, InstructionGroup, Canvas, CanvasBase, Color, Rectangle

Builder.load_string("""
<ButtonsApp>:
    ScrollView:
        id: sv
        size_hint: None, None
        pos: 205, 200
        size: 200, 600 
        on_scroll_stop: app.scroll_on_stop()
        scroll_type: ['bars']
        scroll_wheel_distance: 20
        bar_width: 8
        bar_inactive_color: .55, .55, .55, 1 
        bar_color: .663, .663, .663, 1 
        canvas.before:
            Color:
                rgba: 0, .5, 1, 1
                group: 'b'
            Rectangle:
                size: 0, 0
                group: 'b'
        GridLayout:
            id: container
            cols: 1
            height: self.minimum_height
            size_hint: None, None
            do_scroll_x: False


""")

class ButtonsApp(App, FloatLayout):

    def build(self):
        global rolling_row_cnt
        global my_number_list
        global start_row 
        global end_row
        rolling_row_cnt = 0 #we will use this variable to keep track of the total number of rows in the scrollview as we add rows to it..
        my_number_list = []
        #create a list of numbers from 1 to 600 - this represents the max number of rows that can be displayed
        for i in range(0, 600):
            my_number_list.append(i)
        #we will start the scrollview only showing 100 rows to start.. 
        #as the user scrolls down the view we will add more rows (100 at a time) and adjust the scrollview upwards      
        start_row = 0
        end_row = 100
        self.modify_scrollview()
        return self

    def modify_scrollview(self):
        global rolling_row_cnt
        global my_number_list
        global start_row 
        global end_row
        for i in my_number_list[start_row:end_row]: #add 100 rows to the scrollview...
            L1 = Button(text="row = " + str(rolling_row_cnt), font_size=12, halign='left', valign='middle', size_hint=[None, None], height=37, width=60, background_color=[0, 0, 0, 1], color=[.92, .92, .92, 1])
            L1.bind(size=L1.setter('text_size'))  
            self.ids.container.add_widget(L1)
            rolling_row_cnt = rolling_row_cnt + 1
        if rolling_row_cnt > 99:
            print ("WRONG SCROLL_Y = " + str(self.ids.sv.scroll_y)) #THIS IS WHERE THE PROBLEM OCCURS - after you add rows to the existing scrollview through scroll_on_stop below,
        #the scroll_y value that gets calculated here is 0.0 which is WRONG. How do I get this value to update properly when new rows are added to the scrollview? If I add new rows and move the bar up using code,
        #it should give me the scroll_y at the current bar's position, not 0.0.. 

    def scroll_on_stop(self):
        global start_row 
        global end_row
        if self.ids.sv.scroll_y < .05: #if the user scrolls the view close to the bottom, we will add another 100 rows to the existing scrollview 
            start_row = start_row + 100
            end_row = end_row + 100
            self.modify_scrollview() #trigger the addition of 100 more rows to the existing scrollview
            self.root.ids.sv.scroll_to(self.root.ids.container.children[100]) #adjust the scrollview UPWARD to keep the last most row from last time in view for the user..
        print ("SCROLL_Y = " + str(self.ids.sv.scroll_y)) #this scroll_y is correct when you manually move the mouse wheel 

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

1 个答案:

答案 0 :(得分:0)

我认为这个问题有两个方面。 首先-我怀疑on_scroll_stop事件的行为不符合您的期望(这不是我所期望的)。每次鼠标滚轮滚动都会导致多个on_scroll_stop事件,而不仅仅是滚动结束时的一个事件。这会使您的scroll_on_stop()方法在每次鼠标滚轮滚动时都会被调用多次。

第二个-scroll_to()方法将延迟自身(使用Clock.schedule.once()),如果还有其他未决操作(例如将行添加到其子级时)。

因此,当scroll_on_stop()被多次调用时,scroll_to()被延迟(scroll_y未更新),导致报告了旧值scroll_y。 / p>

我认为您可以通过不使用scroll_to()来解决此问题,而只需设置scroll_y。我建议替换您的行:

self.root.ids.sv.scroll_to(self.root.ids.container.children[100])

类似:

self.root.ids.sv.scroll_y = 100.0/end_row

这可以防止scroll_on_stop()一次滚动多次添加行,并且应滚动到所需的行。