在不是焦点时存储 TextInput 的选择(Kivy)

Storing selection of TextInput when not is focus (Kivy)

我有一个 TextInput 和一个按钮,我的目标是能够 select 来自 TextInput 的一些文本,然后按下一个调用打印函数的按钮:selection_text、selection_to 和 selection_from。

但是,因为在按下按钮时 TextInput 不在焦点上,所以 selection 丢失并且函数 returns 没有 AND/OR 不正确的值。

我在类似的问题中看到过这行代码,但我无法通过弄乱代码或查看 TextInput 文档来弄清楚它的意思,因为我只看到它叫做来自 'on_focus' 函数

Clock.schedule_once(lambda dt: new_post_input.selection_text)

我还不能在示例程序中重现该问题,因为当我将小部件放入它们自己的程序时它起作用了

main.py

from kivy.app import App
from kivy.properties import BooleanProperty, StringProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.modules import inspector
from kivy.core.window import Window


class NewPost(FloatLayout):
    buttons_disabled = BooleanProperty(False)
    cancle_button_disabled = BooleanProperty(True)
    preview_text = StringProperty()
    def make_bold(self, new_post_input, selected):
        print('Selected = ' + selected)
        print('Button has been pushed')

    def preview_post(self, Button, cancleButton, TextInput, Label):
        #self.preview_text = ('Hello\n' + TextInput.text)
        self.buttons_disabled = True
        self.cancle_button_disabled = False
        Label.opacity = 1
        Label.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
        TextInput.opacity = 0
        cancleButton.opacity = 1
        cancleButton.pos_hint = {'center_x': 0.5, 'center_y': 0.5}
        Button.opacity = 0
        Button.pos_hint = {'center_x': 0.5, 'center_y': -1}
        #print(TextInput.text)

    def back_from_preview(self, Button, previewButton, TextInput, Label):
        self.buttons_disable = False
        self.cancle_button_disabled = True
        Label.opacity = 0
        Label.pos_hint = {'center_x': 0.5, 'center_y': -1}
        TextInput.opacity = 1
        Button.opacity = 0
        Button.pos_hint = {'center_x': 0.5, 'center_y': -1}
        previewButton.opacity = 1
        previewButton.pos_hint = {'center_x': 0.5, 'center_y': 0.5}

class SelectionApp(App):
    def build(self):
        inspector.create_inspector(Window, SelectionApp)


SelectionApp().run()

selection.kv

PageLayout:
    Label:
        text: 'Swipe to the next page'
        font_size: dp(50)
    Label:
        text: 'And again'
        canvas.before:
            Color:
                rgba: (0,.8,.8,1)
            RoundedRectangle:
                size: self.size
                radius: [dp(6),]
                pos: self.x, self.y    
    NewPost:
        id: new_post
        canvas.after:
            Color:
                rgba: 0,1,0,1
            Line:
                width: dp(1.6)
                rounded_rectangle:(self.x, self.y, self.width, self.height, dp(5))
        BoxLayout:
            id: main_new_post
            orientation: 'vertical'
            padding: '10dp', '16dp'
            pos_hint: {'center_x': 0.5, 'center_y': 0.5}
            canvas.before:
                Color:
                    rgba: 0, 0, 0, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
            AnchorLayout:
                size_hint: 1, .05
                anchor_x: 'right'
                anchor_y: 'center'
                Label:
                    text: 'New Post'
                    size_hint: None, None
                    size: '100dp', '30dp'
                    color: .8, 0, 0, 1
                    font_size: '16dp'
                    #pos_hint: {'center_x': 0.8, 'center_y': 0.5}
            Label:
                size_hint: 1, .035
                text: ''
                font_size: '1dp'
            BoxLayout:
                orientation: 'vertical'
                padding: '10dp', 0
                size_hint: 1, .38
                FloatLayout:
                    TextInput:
                        id: new_post_input
                        #disabled: new_post.buttons_disabled
                        opacity: 1
                        background_color: 0, 0, 0, 1
                        foreground_color: 1, 1, 1, 1
                        background_disable_normal: True
                        multiline: True
                        font_size: '15dp'
                        padding: '10dp', '10dp'
                        selection_color: (.8, 0, 0, .5)
                        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
                        allow_copy: True
                        #on_focus: new_post.on_focus(self)
                        canvas.after:
                            Color:
                                rgba: 1,1,1,1
                            Line:
                                width: dp(1.6)
                                rounded_rectangle:(self.x, self.y, self.width, self.height, dp(5))
                    BoxLayout:
                        orientation: 'vertical'
                        id: preview_new_post_label
                        opacity: 0
                        pos_hint: {'center_x': 0.5, 'center_y': -1}
                        canvas.before:
                            Color:
                                rgba: (.8,.8,.8,1)
                            RoundedRectangle:
                                size: self.size
                                radius: [dp(6),]
                                pos: self.x, self.y
                        canvas:
                            Color:
                                rgba:0.8,0,0,1
                            Line:
                                width: dp(1.6)
                                rounded_rectangle:(self.x,self.y,self.width,self.height, dp(5))
                        ScrollView:
                            always_overscroll: False
                            bar_color: (0,0,0,0)
                            Label:
                                text: ('Someone:\n' + new_post_input.text)
                                padding: "10dp", "12dp"
                                size_hint: None, None
                                height: self.texture_size[1]
                                width: self.parent.width
                                font_size: "12dp"
                                text_size: self.width, None
                                color: 0,0,0,1
                                multiline: True
                                markup: True
            BoxLayout:
                orientation: 'horizontal'
                size_hint: 1, .08
                padding: '10dp', 0
                AnchorLayout:
                    anchor_x: 'left'
                    anchor_y: 'center'
                    Label:
                        text: 'Text Modification'
                        font_size: '12dp'
                        size_hint: None, None
            BoxLayout:
                orientation: 'vertical'
                padding: '10dp', 0
                size_hint: 1, .12
                BoxLayout:
                    orientation: 'horizontal'
                    #padding: '10dp', 0
                    canvas.after:
                        Color:
                            rgba: 1, 1, 1, 1
                        Line:
                            width: 1.6
                            rounded_rectangle:(self.x, self.y, self.width, self.height, 5)
                    ScrollView:
                        GridLayout:
                            id: container_x
                            size_hint_x: None
                            rows: 1
                            col_default_width: dp(95)
                            width: self.minimum_width
                            spacing: dp(7)
                            Button:
                                text: "Bold"
                                font_size: '14dp'
                                color: 1, 1, 1, 1
                                background_color: .2, .2, .2, 0
                                on_press: new_post.make_bold(new_post_input, new_post_input.selection_text)
                                canvas.before:
                                    Color:
                                        rgba: (.2,.2,.2,0) if self.state=='normal' else (.3,.3,.3,1)
                                    RoundedRectangle:
                                        pos: self.pos
                                        size: self.size
                                        radius: [dp(6),]
                                canvas:
                                    Color:
                                        rgba: (1,1,1,1) if self.state=='normal' else (1,1,1,1)
                                    Line:
                                        width: dp(1.2)
                                        rounded_rectangle:(self.x,self.y,self.width,self.height, dp(6))
            BoxLayout:
                orientation: 'horizontal'
                size_hint: 1, .08
                #padding: '10dp', 0
                AnchorLayout:
                    anchor_x: 'left'
                    anchor_y: 'center'
                    Label:
                        text: 'Post Category'
                        font_size: '12dp'
                        size_hint: None, None
            BoxLayout:
                orientation: 'vertical'
                padding: '10dp', 0
                size_hint: 1, .12
                BoxLayout:
                    orientation: 'horizontal'
                    #padding: '10dp', 0
                    canvas.after:
                        Color:
                            rgba: 1, 1, 1, 1
                        Line:
                            width: 1.6
                            rounded_rectangle:(self.x, self.y, self.width, self.height, 5)
                    ScrollView:
                        GridLayout:
                            id: container_x
                            size_hint_x: None
                            rows: 1
                            col_default_width: dp(95)
                            width: self.minimum_width
                            spacing: dp(7)
                            ToggleButton:
                                text: "Opinion"
                                font_size: '14dp'
                                color: 1, 1, 1, 1
                                background_color: .2, .2, .2, 0
                                on_press: new_post.update_catagory(self, 'opinions')
                                canvas.before:
                                    Color:
                                        rgba: (.2,.2,.2,0) if self.state=='normal' else (.3,.3,.3,1)
                                    RoundedRectangle:
                                        pos: self.pos
                                        size: self.size
                                        radius: [dp(6),]
                                canvas:
                                    Color:
                                        rgba: (1,1,1,1) if self.state=='normal' else (1,1,1,1)
                                    Line:
                                        width: dp(1.2)
                                        rounded_rectangle:(self.x,self.y,self.width,self.height, dp(6))

演示程序运行:YouTube link

感谢任何 suggestions/solutions :)

更新

事实证明,当 TextInput 位于超过 2 页的 PageLayout 中时,selection 似乎停止工作(在我的程序中)。

我创建了一个粗略的演示程序来展示问题并将其放入 .py 和 .kv

您可以通过创建自定义 TextInput 实例并覆盖其方法之一来实现。

class MyTextInput(TextInput):
    selected_text = StringProperty("")
    # Use this prop. instead of 'selection_text'.

    def cancel_selection(self):
        self.selected_text = self.selection_text
        super().cancel_selection()

现在在任何需要的地方使用这个实例和新的 属性。

.kv,

                FloatLayout:
                    MyTextInput:
                        id: new_post_input
                        .
                        .
                        .
                            Button:
                                text: "Bold"
                                font_size: '14dp'
                                color: 1, 1, 1, 1
                                background_color: .2, .2, .2, 0
                                on_press: new_post.make_bold(new_post_input, new_post_input.selected_text)