python - Kivy RecycleView、RecycleGridLayout、滚动标签问题

标签 python kivy

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

检查树,ScrollCell (BoxLayout) 的尺寸为 100x100,并且未填充其给定大小或填充 RecycleGridLayout 的默认列/行宽度/高度。

它的外观如下:

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

最佳答案

我能够完成这项工作,但后来我发现了我的预期设计中的一个缺陷。如果标签可滚动并占据 RecycleGridLayout 内单元格的整个区域 (400x60),则这将通过不允许表格滚动 y 和 x 来破坏 RecycleView 的滚动行为。这可能是由嵌套的 ScrollView 引起的。

Nested Scroll-able Labels

文档中提到能够嵌套 ScrollView,但我无法弄清楚。我还在 #kivy irc 日志中看到不建议嵌套 ScrollView。我决定采用不同的路线,使用“工具提示”类型小部件在标签比单元格宽时显示标签。

关于python - Kivy RecycleView、RecycleGridLayout、滚动标签问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44463773/

相关文章:

python - 计算游戏的高分表

python - InstalledAppFlow 自动获取授权码

python - TensorFlow:有没有办法测量模型的 FLOPS?

python - Kivy on_dropfile 没有被调用

python - Appveyor 上的 Kivy PyInstaller

python - subprocess.run 简单场景失败

python - Pandas Groupby 基于 2 个日期列表分组的独特计数

python - Kivy 不工作,MESA-LOADER : failed to open iris and swrast

python - 永远不会调用 Kivy Android plyer.gps on_location 回调

python - 将 Python 与 Kivy 结合使用