Kivy-如何在 TextInput 中允许水平和垂直滚动?
Kivy-how to allow Horizontal and Vertical scrolling in TextInput?
我对 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 的文档感到困惑,哈哈)
您需要根据其中文本行的长度调整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()
这是一个经过简化且略有改进的工作解决方案。主要区别是
- 填充一行可滚动输出字段的一行输入输入字段
- 滚动仅限于水平方向
- 防止过度滚动
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()
结果
我对 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 的文档感到困惑,哈哈)
您需要根据其中文本行的长度调整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()
这是一个经过简化且略有改进的工作解决方案。主要区别是
- 填充一行可滚动输出字段的一行输入输入字段
- 滚动仅限于水平方向
- 防止过度滚动
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()