Kivy-如何在TextInput中允许水平和垂直滚动?

时间:2018-12-14 10:19:50

标签: python kivy kivy-language

我对Python和Kivy还是很陌生,想创建一个简单的代码编辑器。我尝试使用Kivy(.kv)文件制作一个好的原型:

<Label>:
    font_name:'Fura Code Retina Nerd Font Complete.otf'
    font_size:'18sp'
<GridLayout>:
    cols:3
    rows:1
    Label:
        text:"Bars"
        size_hint_x: None
        width: 50
    Label:
        canvas.before:
            Color:
                rgb:0.085,0.095,0.085
            Rectangle:
                pos: self.pos
                size: self.size
        text:"Bars-result"
        size_hint_x: None
        width: 170
    ScrollView:
        TextInput:
            font_size: '18sp'
            cursor_color: [255,255,255,1]
            background_color: (.17, .18, .17, 1)
            foreground_color:[255,255,255,1]
            font_name: 'Fura Code Retina Nerd Font Complete.otf'
            selection_color: (1,1,1,0.125)

您可能已经发现,如果垂直超出框,则可以向后滚动(但是没有实际的滚动条)。但是,在水平方向执行此操作不会发生相同的情况,实际上,我们转到下一行。我想使其在x和y轴上均可滚动,并同时具有滚动条。
感谢您的任何帮助,如果可能的话,文档帮助也会有所帮助(但是,我很快就与Kivy的文档大声混为一谈)

2 个答案:

答案 0 :(得分:0)

您需要根据TextInput中文本行的长度来调整其宽度。不幸的是,没有简单的方法可以动态调整TextInput小部件的宽度。这是我认为可以解决的问题。请注意,这使用了TextInput的内部结构,因此如果TextInput代码在将来的版本中进行更改,则可能会中断:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout

Builder.load_string('''
<Label>:
    font_name:'Fura Code Retina Nerd Font Complete.otf'
    font_size:'18sp'
<GridLayout>:
    cols:3
    rows:1
    Label:
        text:"Bars"
        size_hint_x: None
        width: 50
    Label:
        canvas.before:
            Color:
                rgb:0.085,0.095,0.085
            Rectangle:
                pos: self.pos
                size: self.size
        text:"Bars-result"
        size_hint_x: None
        width: 170
    ScrollView:
        id:scroller
        TextInput:
            id: ti
            size_hint: (None, None)
            width: scroller.width
            height: max(self.minimum_height, scroller.height)
            font_size: '18sp'
            cursor_color: [255,255,255,1]
            background_color: (.17, .18, .17, 1)
            foreground_color:[255,255,255,1]
            font_name: 'Fura Code Retina Nerd Font Complete.otf'
            selection_color: (1,1,1,0.125)
            on_text: app.text_changed()
''')

class ScrollBothApp(App):
    def build(self):
        self.grid = GridLayout()
        return self.grid

    def text_changed(self, *args):
        width_calc = self.grid.ids.scroller.width
        for line_label in self.grid.ids.ti._lines_labels:
            width_calc = max(width_calc, line_label.width + 20)   # add 20 to avoid automatically creating a new line
        self.grid.ids.ti.width = width_calc



ScrollBothApp().run()

答案 1 :(得分:0)

这是一个简化且略有改进的工作解决方案。关键区别是

  • 填充一行可滚动输出字段的一行输入输入字段
  • 滚动仅限于水平
  • 防止过度滚动

textinputscrolling.kv

<TextInputScrolling>:
    textInput: txt_input
    textOutput: txt_output
    scroller: scroll_view

    orientation: 'vertical'
    BoxLayout:
        orientation: 'vertical'
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
        BoxLayout:
            orientation: 'vertical'
            size_hint_y: None
            height: "56dp"
            canvas.before:
                Color:
                    rgb: [0,0,0]
                Rectangle:
                    pos: self.pos
                    size: self.size
            TextInput:
                id: txt_input
                focus: True
                multiline: False
                on_text_validate: root.submitRequest() # ENTER triggers root.submitRequest()

            GridLayout:
                cols: 2
                ScrollView:
                    id: scroll_view
                    do_scroll_y: False # limiting to horizontal scrolling
                    effect_cls: "ScrollEffect" # prevents overscrolling
                    size_hint_x: 3
                    TextInput:
                        id: txt_output
                        size_hint: (None, None) # warning: if not there, scrolling not working !
                        width: scroll_view.width
                        cursor_color: [255,255,255,1]
                        background_color: (.17, .18, .17, 1)
                        foreground_color:[255,255,255,1]
                        selection_color: (1,1,1,0.125)
                        multiline: False
                        read_only: True
                        on_text: root.text_changed()
                Button:
                    id: clear_output_Button
                    text: 'Clear'
                    size_hint_x: 1
                    width: 130
                    on_press: root.clearAll()

textinputscrolling.py

from kivy.app import App
from kivy.config import Config
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout


class TextInputScrolling(BoxLayout):
    textInput = ObjectProperty()
    scroller = ObjectProperty()
    textOutput = ObjectProperty()

    def submitRequest(self):
        self.textOutput.text = self.textInput.text

    def text_changed(self, *args):
        width_calc = self.scroller.width
        for line_label in self.textOutput._lines_labels:
            width_calc = max(width_calc, line_label.width + 20)   # add 20 to avoid automatically creating a new line
        self.textOutput.width = width_calc

    def clearAll(self):
        self.textInput.text = ''
        self.textOutput.text = ''


class TextInputScrollingApp(App):
    def build(self):
        Config.set('graphics', 'width', '200')
        Config.set('graphics', 'height', '60')
        Config.write()

        self.gui = TextInputScrolling()
        return self.gui

TextInputScrollingApp().run()

结果

enter image description here