为什么位置属性(pos 和 pos_hint)不影响我的 Kivy 应用程序中的小部件放置?

问题描述 投票:0回答:1

我正在开发一个 Kivy 应用程序,我需要动态调整某些小部件的位置和高度。但是,无论我尝试什么, pos 和 pos_hint 属性似乎都不会影响布局中小部件的放置。具体来说,我使用 BoxLayout 垂直组织小部件,但更改布局和各个小部件的 pos 或 pos_hint 对它们的定位没有明显影响。

这是我尝试过的:

在 TextInput 和 Button 小部件上使用 pos_hint 来更改它们的垂直位置。 调整 BoxLayout 上的 pos 属性来移动整个布局。 设置小部件的高度并使用 size_hint_y 控制小部件的大小。 尝试向上移动布局以在屏幕底部创建空间。 这些方法似乎都没有任何效果。布局保持在其原始位置,并且小部件未按预期放置或调整大小。

我的代码:

from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.clock import Clock
import random

class LongStringApp(App):
    def build(self):
        # Set the window size (optional)
        Window.size = (800, 600)

        # Create a long string of text
        long_string = ("""Therefore, I urge you, brothers and sisters, in view of God’s mercy, to offer your bodies as a living sacrifice, holy and pleasing to God—this is your true and proper worship.""")
        self.original_text = long_string

        # Split the text into words
        words = long_string.split()

        
        num_blanks = len(words) // 6

        # Randomly select which words to replace with blanks
        indices_to_blank = random.sample(range(len(words)), num_blanks)

        # Replace the selected words with underscores of the same length
        for i in indices_to_blank:
            word_length = len(words[i])
            words[i] = "_" * word_length  # Replace with underscores

        # Reconstruct the string with blanks
        modified_string = " ".join(words)

        # Variables for easy adjustment
        self.HEIGHT_PERCENTAGE_TEXT = 0.8  # 80% of the screen height for the TextInput
        self.HEIGHT_PERCENTAGE_BUTTON = 0.1  # 10% of the screen height for the Button
        self.POS_PERCENTAGE_LAYOUT = 0.6  # Position of the entire layout, starting from the top

        # Create a BoxLayout to hold the TextInput and Submit Button
        self.layout = BoxLayout(orientation='vertical', padding=10, spacing=10)

        # Create a TextInput widget to allow the user to edit the string
        self.text_input = TextInput(text=modified_string, font_size=20, multiline=True, size_hint_y=None,
                                    background_color=(0, 0, 0, 1), foreground_color=(1, 1, 1, 1))  # Black background, white text
        self.text_input.height = Window.height * self.HEIGHT_PERCENTAGE_TEXT  # Set the height of the TextInput
        self.text_input.text_size = (Window.width - 20, None)  # Set the text size for wrapping
        self.text_input.bind(width=self.update_text_size)  # Bind width to text_size for wrapping

        # Add the TextInput to the layout
        self.layout.add_widget(self.text_input)

        # Create a submit button to check if the filled-in text matches the original
        submit_button = Button(text="Submit", size_hint_y=None, height=50, background_color=(0.2, 0.6, 0.2, 1))

        # Set height for the Button manually
        submit_button.height = Window.height * self.HEIGHT_PERCENTAGE_BUTTON  # Set the height of the Button

        submit_button.bind(on_press=self.check_answers)

        # Add the button to the layout
        self.layout.add_widget(submit_button)

        # Create a ScrollView and add the layout to it
        scroll_view = ScrollView()
        scroll_view.add_widget(self.layout)

        # Schedule the scroll to the top after the window has been fully created
        Clock.schedule_once(self.scroll_to_top, 0.1)

        # Move the entire layout up by 20% of the screen height (adjusting the top margin)
        self.layout.pos_hint = {'top': self.POS_PERCENTAGE_LAYOUT}  # Set the top position to be 80% from the top

        
        return scroll_view

    def update_text_size(self, *args):
        # Update the text_size with the current width of the TextInput minus padding
        self.text_input.text_size = (self.layout.width - 20, None)

    def scroll_to_top(self, dt):
        # This function will set the ScrollView to the top
        self.root.scroll_y = 1
        
        # Set focus to the TextInput and move the cursor to the start
        self.text_input.focus = True
        self.text_input.cursor = (0, 0)  # Moves the cursor to the start


    def check_answers(self, instance):
        # Get the filled-in text from the TextInput
        filled_text = self.text_input.text.strip()

        # Remove any extra spaces for comparison
        original_text = self.original_text
        original_text_clean = ' '.join(original_text.split())
        filled_text_clean = ' '.join(filled_text.split())

        # Check if the filled text matches the original text
        if filled_text_clean == original_text_clean:
            result_text = "Correct! You filled in all the blanks correctly."
        else:
            result_text = "There are some mistakes. Please try again."

        # Create a result label to show feedback
        result_label = Label(text=result_text, size_hint=(1, None), height=50, font_size=18, color=(1, 1, 1, 1))

        # Add the result label to the layout (within BoxLayout)
        self.layout.add_widget(result_label)

        # Optionally remove the result label after a few seconds
        Clock.schedule_once(lambda dt: self.remove_result_label(result_label), 2)

    def remove_result_label(self, label):
        self.layout.remove_widget(label)

if __name__ == '__main__':
    LongStringApp().run()

我的期望: pos_hint 和 pos 属性应该调整 TextInput 和 Button 小部件以及整个布局的位置。 我想通过将布局和小部件向上移动 20%,在屏幕底部(窗口的 20% 应该是空的,底部 20%)创建空间。 怎么了: 小部件保持在其初始位置,调整 pos 或 pos_hint 不会影响布局。 附加信息: 我还尝试使用 size_hint_y 来调整高度,但这只会调整小部件的大小,而不是它们的位置。 有人可以帮助我理解为什么 pos 和 pos_hint 属性不适用于我的 Kivy 应用程序中的小部件放置吗?

python android kivy
1个回答
0
投票

第一个问题是您希望屏幕底部 20% 为空,但您的

TextInput
Button
的大小占据了屏幕的 90%。首先,尝试改变:

self.HEIGHT_PERCENTAGE_TEXT = 0.8

至:

self.HEIGHT_PERCENTAGE_TEXT = 0.7

此外,为了让

ScrollView
正常工作,其子布局必须将
size_hint_y
设置为
None
。请参阅文档。所以尝试改变:

self.layout = BoxLayout(orientation='vertical', padding=10, spacing=10)

至:

self.layout = BoxLayout(orientation='vertical', padding=10, spacing=10, size_hint_y=None)

现在您需要实际设置

BoxLayout
的高度,这可以通过将
minimum_height
绑定为:

来完成
self.layout.bind(minimum_height=self.layout.setter('height'))

我认为上述更改将为您提供您所描述的内容。

至于在

pos_hint
中使用
BoxLayout
,请参阅 文档,其中提到:

位置提示部分起作用,具体取决于方向:

If the orientation is vertical: x, right and center_x will be used.

If the orientation is horizontal: y, top and center_y will be used.
© www.soinside.com 2019 - 2024. All rights reserved.