Kivy RecycleView,RecycleGridLayout,可滚动标签问题

时间:2017-06-09 17:36:41

标签: python kivy

正如标题所示,我试图制作一个固定标题和单元格大小为w400 x h60的数据表。如果标签内的文本超过400的宽度,则标签应水平滚动。下面发布的代码是我最接近的代码。

检查树时,ScrollCell(BoxLayout)的尺寸为100x100,并且不会满足给定尺寸或填充RecycleGridLayout的deafult col /行宽度/高度。

以下是它的外观:

Screen Shot

感谢您解决此问题的任何帮助。

rtable.py:

from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.recycleview import RecycleView
from kivy.properties import BooleanProperty
from kivy.properties import ObjectProperty
from kivy.properties import NumericProperty, StringProperty
import kivy
kivy.require('1.10.0')


class HeaderCell(Label):
    pass


class TableHeader(ScrollView):
    """Fixed table header that scrolls x with the data table"""
    header = ObjectProperty(None)

    def __init__(self, list_dicts=None, *args, **kwargs):
        super(TableHeader, self).__init__(*args, **kwargs)

        titles = list_dicts[0].keys()

        for title in titles:
            self.header.add_widget(HeaderCell(text=title))


class ScrollCell(BoxLayout):
    text = StringProperty(None)
    is_even = BooleanProperty(None)


class TableData(RecycleView):
    nrows = NumericProperty(None)
    ncols = NumericProperty(None)
    rgrid = ObjectProperty(None)

    def __init__(self, list_dicts=[], *args, **kwargs):
        self.nrows = len(list_dicts)
        self.ncols = len(list_dicts[0])

        super(TableData, self).__init__(*args, **kwargs)

        self.data = []
        for i, ord_dict in enumerate(list_dicts):
            is_even = i % 2 == 0
            row_vals = ord_dict.values()
            for text in row_vals:
                self.data.append({'text': text, 'is_even': is_even})


class Table(BoxLayout):

    def __init__(self, list_dicts=[], *args, **kwargs):

        super(Table, self).__init__(*args, **kwargs)
        self.orientation = "vertical"

        self.header = TableHeader(list_dicts=list_dicts)
        self.table_data = TableData(list_dicts=list_dicts)

        self.table_data.fbind('scroll_x', self.scroll_with_header)

        self.add_widget(self.header)
        self.add_widget(self.table_data)

    def scroll_with_header(self, obj, value):
        self.header.scroll_x = value


if __name__ == '__main__':
    from kivy.app import App
    from collections import OrderedDict

    class RtableApp(App):
        def build(self):
            data = []

            keys = ["Title Col: {}".format(i + 1) for i in range(15)]

            for nrow in range(30):
                row = OrderedDict.fromkeys(keys)
                for i, key in enumerate(keys):
                    row[key] = "Data col: {}, row: {}".format(i + 1, nrow + 1)
                    if i % 3 == 0:
                        row[key] = row[key] + ". Extra long label. " * 3
                data.append(row)

            return Table(list_dicts=data)

    RtableApp().run()

rtable.kv:

<HeaderCell>
    size_hint: (None, None)
    height: 60
    width: 400
    text_size: self.size
    halign: "left"
    valign: "middle"
    background_disabled_normal: '' 
    disabled_color: (1, 1, 1, 1)
    canvas.before:
        Color:
            rgba: 0.165, 0.165, 0.165, 1
        Rectangle:
            pos: self.pos
            size: self.size

<TableHeader>:
    header: header
    bar_width: 0
    do_scroll: False
    size_hint: (1, None)
    effect_cls: "ScrollEffect"
    height: 60
    GridLayout:
        id: header
        rows: 1
        size_hint: (None, None)
        width: self.minimum_width
        height: self.minimum_height

<ScrollCell>:
    orientation: 'horizontal'
    label: label
    size_hint: (None, None)
    size: (400, 60)  
    text: ''
    canvas.before:
        Color:
            rgba: [0.23, 0.23, 0.23, 1] if self.is_even else [0.2, 0.2, 0.2, 1]
        Rectangle:
            pos: self.pos
            size: self.size     
    ScrollView:
        scroll_type: ['bars', 'content']
        do_scroll_x: True
        do_scroll_y: False
        effect_cls: "ScrollEffect"
        Label:
            id: label
            text_size: None, self.height
            size_hint: (None, 1)
            width: self.texture_size[0]
            text: root.text
            padding_x: 10



<TableData>:
    rgrid: rgrid
    bar_width: 25
    scroll_type: ['bars']
    bar_color: [0.2, 0.7, 0.9, 1]
    bar_inactive_color: [0.2, 0.7, 0.9, .5]
    do_scroll_x: True
    do_scroll_y: True
    effect_cls: "ScrollEffect"
    viewclass: "ScrollCell"
    RecycleGridLayout:
        id: rgrid
        rows: root.nrows
        cols: root.ncols
        size_hint: (None, None)
        width: self.minimum_width
        height: self.minimum_height
        col_default_width: 400
        row_default_height: 60

1 个答案:

答案 0 :(得分:1)

当我发现我的设计中存在缺陷时,我能够完成这项工作。如果标签是可滚动的并占据RecycleGridLayout中单元格的整个区域(400x60),那么这将通过不允许表格滚动y和x来打破RecycleView的滚动行为。这可能是由嵌套的ScrollViews引起的。

Nested Scroll-able Labels

在文档中提到了能够嵌套ScrollViews,但我无法弄明白。我还在#kivy irc日志中看到不推荐嵌套ScrollViews。我决定采用一种不同的途径,使用工具提示&#39;键入小部件,以便在标签宽于单元格时显示标签。