在不使用 kv 文件的情况下在 Kivy 中滚动视图

Scrollview in Kivy without using kv file

我需要在我的 Kivy 应用程序中创建滚动视图功能,但不使用 kv 文件。

下面我的代码不起作用。我想我走错了路。请帮我。我需要在 window 中间创建框架,并且只有 2 个按钮应该可见,并且用户只能循环向下滚动按钮列表。

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.scrollview import ScrollView
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')


class MyApp(App):
    def build(self):
        self.create_scrollview()
        Window.size = (900, 600)
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.2, 0.6)
        self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}

        self.some_words = Label(font_size='16', text='Win or Lose', color='white', halign='center')
        self.window.add_widget(self.some_words)

        self.button_1 = Button(text='1st button', background_color='#04D0F9')
        self.button_1.size_hint = (0.2, 0.2)
        self.button_1.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_1.bind(on_press=self.ask1)
        self.window.add_widget(self.button_1)

        self.button_2 = Button(text='2nd button', background_color='#04D0F9')
        self.button_2.size_hint = (0.2, 0.2)
        self.button_2.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_2.bind(on_press=self.ask2)
        self.window.add_widget(self.button_2)

        self.button_3 = Button(text='3rd button', background_color='#04D0F9')
        self.button_3.size_hint = (0.2, 0.2)
        self.button_3.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_3.bind(on_press=self.ask3)
        self.window.add_widget(self.button_3)

        self.button_4 = Button(text='4th button', background_color='#04D0F9')
        self.button_4.size_hint = (0.2, 0.2)
        self.button_4.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_4.bind(on_press=self.ask4)
        self.window.add_widget(self.button_4)

        self.button_5 = Button(text='5th button', background_color='#04D0F9')
        self.button_5.size_hint = (0.2, 0.2)
        self.button_5.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_5.bind(on_press=self.ask5)
        self.window.add_widget(self.button_5)

        self.button_6 = Button(text='6th button', background_color='#04D0F9')
        self.button_6.size_hint = (0.2, 0.2)
        self.button_6.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_6.bind(on_press=self.ask6)
        self.window.add_widget(self.button_6)

        return self.window

    def ask1(self, instance):
        self.some_words.text = 'Test 1'

    def ask2(self, instance):
        self.some_words.text = 'Test 2'

    def ask3(self, instance):
        self.some_words.text = 'Test 3'

    def ask4(self, instance):
        self.some_words.text = 'Test 4'

    def ask5(self, instance):
        self.some_words.text = 'Test 5'

    def ask6(self, instance):
        self.some_words.text = 'Test 6'

    def create_scrollview(self):
        base = (self.button_1, self.button_2, self.button_3, self.button_4, self.button_5, self.button_6)
        layout = GridLayout(cols=1)
        layout.bind(minimum_height=layout.setter("height"))

        for element in base:
            button = Button(text=str(element), size_hint=(1, 0.1))
            layout.add_widget(button)
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.window.add_widget(scrollview)

if __name__ == "__main__":
    MyApp().run()

我更新后的代码如下。此代码也无法正常工作。没有按钮可见,只有文本在黑色背景上可见。请帮忙。也许我做错了什么。应用程序已打开,没有错误,但预期结果是按钮滚动功能不起作用。

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.scrollview import ScrollView
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')


class MyApp(App):

    def create_scrollview(self):
        base = (self.button_1, self.button_2, self.button_3, 
        self.button_4, self.button_5, self.button_6)
        layout = GridLayout(cols=1, size_hint_y=None)
        layout.bind(minimum_height=layout.setter("height"))

        for element in base:
            button = Button(text=str(element), size_hint=(1, None))
            layout.add_widget(button)
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.window.add_widget(scrollview)

    def build(self):
        Window.size = (900, 600)
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.2, 0.6)
        self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}

        self.some_words = Label(font_size='16', text='Win or Lose', 
 color='white', halign='center')
        self.window.add_widget(self.some_words)

        self.button_1 = Button(text='1st button', 
background_color='#04D0F9')
        self.button_1.size_hint = (0.2, 0.2)
        self.button_1.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_1.bind(on_press=self.ask1)

        self.button_2 = Button(text='2nd button', 
background_color='#04D0F9')
        self.button_2.size_hint = (0.2, None)
        self.button_2.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_2.bind(on_press=self.ask2)

        self.button_3 = Button(text='3rd button', 
background_color='#04D0F9')
        self.button_3.size_hint = (0.2, None)
        self.button_3.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_3.bind(on_press=self.ask3)

        self.button_4 = Button(text='4th button', 
background_color='#04D0F9')
        self.button_4.size_hint = (0.2, None)
        self.button_4.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_4.bind(on_press=self.ask4)

        self.button_5 = Button(text='5th button', 
background_color='#04D0F9')
        self.button_5.size_hint = (0.2, None)
        self.button_5.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_5.bind(on_press=self.ask5)

        self.button_6 = Button(text='6th button', 
background_color='#04D0F9')
        self.button_6.size_hint = (0.2, None)
        self.button_6.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.button_6.bind(on_press=self.ask6)

        return self.window

    def ask1(self, instance):
        self.some_words.text = 'Test 1'

    def ask2(self, instance):
        self.some_words.text = 'Test 2'

    def ask3(self, instance):
        self.some_words.text = 'Test 3'

    def ask4(self, instance):
        self.some_words.text = 'Test 4'

    def ask5(self, instance):
        self.some_words.text = 'Test 5'

    def ask6(self, instance):
        self.some_words.text = 'Test 6'

if __name__ == "__main__":
    MyApp().run()

更新: 我已经更改了代码,但仍然存在不正确的反映。正如您从我的代码中看到的那样,我希望使用“第一个按钮”、“第二个按钮”等按钮。但是反射不正确。我不明白我需要如何修复它。此外,按钮功能不起作用。例如,我需要在单击“第一个按钮”时看到“测试 1”,但是当我单击任何按钮时没有任何反应。

image

您只是遗漏了一些小东西:

  1. 您将创建的每个按钮添加到 self.window,然后将相同的按钮添加到 SrollView,因此您得到了重复的小部件。为每个按钮删除此行:self.window.add_widget(self.button_6)

  2. 当你 运行 你的 kivy 应用程序时,首先它加载 .kv 文件(在这种情况下没有这个),然后 运行是 App.build() 方法。与 python 中的任何其他函数一样,build() 是一个同步函数,因此您要做的第一件事就是调用 self.create_scrollview() 方法,该方法需要所有按钮才能工作...问题是此时尚未创建按钮,因此您会收到错误消息。解决办法是把self.create_scrollview()移到函数build().

    的return之前
  3. 为了能够滚动,您必须停用 child 的至少一个 size_hint 指令(x 或 y)以启用滚动。所以你所有的按钮和包含按钮的网格布局必须有 size_hint=(1,None)size_hint_y=None。所以:

def create_scrollview(self):
        base = (self.button_1, self.button_2, self.button_3, self.button_4, self.button_5, self.button_6)
        layout = GridLayout(cols=1, size_hint_y=None)
        layout.bind(minimum_height=layout.setter("height"))

        for element in base:
            button = Button(text=str(element), size_hint=(1, None))
            layout.add_widget(button)
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.window.add_widget(scrollview)

如您所见,我只是修改了一些小东西,但这会修复您的代码

编辑 2:

为您的按钮创建一个自定义 class,这样您的每个按钮都有您想要的回调:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.scrollview import ScrollView
from kivy.properties import NumericProperty
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')


class MyButton(Button):
    num = NumericProperty(0)
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.size_hint = (0.2, None)
        self.pos_hint = {"center_x": 0.5, "center_y": 0.5}
        self.background_color = '#04D0F9'

    def on_press(self):
       App.get_running_app().some_words.text = f'Test {self.num}'
        

class MyApp(App):
    def build(self):
        Window.size = (900, 600)
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.2, 0.6)
        self.window.pos_hint = {"center_x": 0.5, "center_y": 0.6}

        self.some_words = Label(font_size='16', text='Win or Lose', color='white', halign='center')
        self.window.add_widget(self.some_words)

        self.create_scrollview()
        
        return self.window

    def create_scrollview(self):
        listNames = ['1st Button', '2nd button', '3rd button', '4th button', '5th button', '6th button']
        layout = GridLayout(cols=1, size_hint_y=None)
        layout.bind(minimum_height=layout.setter("height"))
        for i in range(6):
            button = MyButton(text=listNames[i], num=i+1)
            layout.add_widget(button)
            layout.ids[str(i+1)]=button
        scrollview = ScrollView(size=(Window.width, Window.height))
        scrollview.add_widget(layout)
        self.window.add_widget(scrollview)

if __name__ == "__main__":
    MyApp().run()