Python Kivy如何允许文本输入中的水平和垂直滚动?

Python Kivy如何允许文本输入中的水平和垂直滚动?,python,kivy,kivy-language,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

我对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的文档弄糊涂了。lol

您需要根据文本行的长度调整文本输入的宽度。不幸的是,没有简单的方法可以动态调整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()

这里有一个简化的、稍加改进的工作解决方案。关键区别在于

单行输入输入字段,填充单行可滚动输出字段 滚动仅限于水平滚动 防止过卷 textinputscrolling.kv 后果
非常感谢你!!很长一段时间以来,我一直在想如何做到这一点,文档中很少有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()
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()