Перекрытие пользовательского виджета в ScrollView GridLayout в Киви - PullRequest
0 голосов
/ 21 марта 2020

это пробный код, который я хочу внедрить в свой финальный проект.

Python Код:

import kivy
kivy.require('1.0.6') 
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder

class Wid(BoxLayout):

    def settxt(self,i):
        lab = self.ids['lab']
        but = self.ids['but']
        lab.text = "Label Number {}".format(i)
        but.text = "Button Number {}".format(i)


class Win1(Screen):
    i=0
    def addw(self):
        box1 = self.ids['box1']
        self.i = self.i +1
        w = Wid()
        w.settxt(self.i)
        box1.add_widget(w)

    def switch(self):
        sm.current="win2"


class Win2(Screen):
    def switch(self):
        sm.current="win1"

class WindowManager(ScreenManager):
    pass

kv = Builder.load_file("test.kv")
sm = WindowManager()

screens = [Win1(name="win1"), Win2(name="win2")]
for screen in screens:
    sm.add_widget(screen)

sm.current = "win1"

class Test(App):

    def build(self):
        return sm

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

Код Kivy:

<Wid>:
    lab:lab
    but:but
    BoxLayout:
        height: self.minimum_height
        size: root.size
        Label:
            id: lab

        Button:
            id: but


<Win1>
    name:"win1"
    box1:box1
    BoxLayout:
        height: self.minimum_height
        orientation: "vertical"
        BoxLayout:
            size_hint: 1,0.2
            Button:
                text:"window 2"
                on_release:
                    root.switch()

            Button:
                text:"add wid"
                on_release:
                    root.addw()

        ScrollView:
            GridLayout:
                id:box1
                orientation: "vertical"
                spacing: 2
                size_hint_y: None
                height: self.minimum_height  
                row_default_height: 60
                cols:1

<Win2>
    name: "win2"

    BoxLayout:
        id: bl

        height: bl.minimum_height
        size_hint_y: None
        Button:
            text:"window 2"
            on_release:
                root.switch()

С нажатием выключателя Я ожидаю, что мой пользовательский виджет попадет в сетку в виде прокрутки, один под другим. Но вместо этого каждый новый виджет появляется в последней ячейке макета и перекрывается с предыдущей, а над ними продолжают образовываться пустые ячейки. Не знаю, где это идет не так.

Ответы [ 3 ]

0 голосов
/ 22 марта 2020

Ряд вопросов здесь, смотрите комментарии. Самая большая проблема, которую я вижу, - это размещение элементов в виджете. Поместите виджеты в макет, а не другие виджеты.

import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

kv = """
<Wid>:               # Put widgets in a layout, not a widget.
    lab:lab
    but:but
    BoxLayout:
        size: root.size
        Label:
            id: lab

        Button:
            id: but


<Win1>
    # name:"win1"
    box1:box1
    BoxLayout:
        orientation: "vertical"
        BoxLayout:
            size_hint: 1,0.2
            Button:
                text:"window 2"
                on_release:
                    root.switch()

            Button:
                text:"add wid"
                on_release:
                    root.addw()

        ScrollView:
            GridLayout:
                id:box1
                orientation: "vertical"
                spacing: 2
                size_hint_y: None
                height: self.minimum_height  
                row_default_height: 60
                cols:1

<Win2>:
    # name: "win2"
    BoxLayout:
        Button:
            text:"window 2"
            on_release:
                root.switch()
ScreenManager:
    id: sm
    Win1:
        name: 'win1'
    Win2:
        name: 'win2'

"""


class Wid(BoxLayout):       # Change to layout
    def settxt(self,i):
        lab = self.ids['lab']
        but = self.ids['but']
        lab.text = "Label Number {}".format(i)
        but.text = "Button Number {}".format(i)


class Win1(Screen):
    i = 0

    def addw(self):
        box1 = self.ids['box1']
        self.i = self.i + 1
        w = Wid()
        w.settxt(self.i)
        box1.add_widget(w)

    @staticmethod
    def switch():
        app = App.get_running_app()
        app.root.current = "win2"


class Win2(Screen):
    @staticmethod
    def switch():
        app = App.get_running_app()
        app.root.current = "win1"

# class WindowManager(ScreenManager):
#     pass

# kv = Builder.load_file("test.kv")
# sm = WindowManager()
#
# screens = [win1(name="win1"), win2(name="win2")]
# for screen in screens:
#     sm.add_widget(screen)
#
# sm.current = "win1"


class WidgetQApp(App):
    def build(self):
        return Builder.load_string(kv)


WidgetQApp().run()
0 голосов
/ 22 марта 2020

Здесь я перенес kv в отдельный файл и динамически создал экраны. Ключевые моменты: я добавляю экраны динамически в on_start, это после завершения сборки. Я создаю ScreenManager в kv и использую id для добавления экранов. В коде kv я поместил ScreenManger в BoxLayout. Это личное предпочтение. Я делаю так, чтобы при доступе к объектам виджет root не являлся диспетчером экрана. Поэтому в методах switch () адресация использует назначенный идентификатор, а не полагается на то, что виджет root является диспетчером экрана.

FWIW: Если код переключателя будет только изменять экраны, я бы переместил эти отдельные строки в КВ.

import kivy

kivy.require('1.0.6')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen


class Wid(BoxLayout):  # Change to layout
    def settxt(self, i):
        lab = self.ids['lab']
        but = self.ids['but']
        lab.text = "Label Number {}".format(i)
        but.text = "Button Number {}".format(i)


class Win1(Screen):
    i = 0

    def addw(self):
        box1 = self.ids['box1']
        self.i = self.i + 1
        w = Wid()
        w.settxt(self.i)
        box1.add_widget(w)

    @staticmethod
    def switch():
        app = App.get_running_app()
        app.root.ids.sm.current = "win2"


class Win2(Screen):
    @staticmethod
    def switch():
        app = App.get_running_app()
        app.root.ids.sm.current = "win1"


class WidgetQ1App(App):
    def build(self):
        return Builder.load_file('widgetq.kv')

    def on_start(self):
        screens = [Win1(name="win1"), Win2(name="win2")]
        sm = self.root.ids.sm
        for screen in screens:
            sm.add_widget(screen)


WidgetQ1App().run()

И код КВ:

<Wid>:               # Put widgets in a layout, not a widget.
    lab:lab
    but:but
    BoxLayout:
        size: root.size
        Label:
            id: lab

        Button:
            id: but


<Win1>
    # name:"win1"
    box1:box1
    BoxLayout:
        orientation: "vertical"
        BoxLayout:
            size_hint: 1,0.2
            Button:
                text:"window 2"
                on_release:
                    root.switch()

            Button:
                text:"add wid"
                on_release:
                    root.addw()

        ScrollView:
            GridLayout:
                id:box1
                orientation: "vertical"
                spacing: 2
                size_hint_y: None
                height: self.minimum_height
                row_default_height: 60
                cols:1

<Win2>:
    # name: "win2"
    BoxLayout:
        Button:
            text:"window 2"
            on_release:
                root.switch()
BoxLayout:
    ScreenManager:
        id: sm
0 голосов
/ 21 марта 2020
<win2>
    name: "win2"
    size_hint_y: None
    height: bl.minimum_height
    BoxLayout:
        id: bl
        Button:
            text:"window 2"
            on_release:
                root.switch()

Ваши пользовательские виджеты не имеют определенной высоты, попробуйте изменить что-то вроде выше.

Кроме того, начинайте имена классов с заглавной буквы, kv требует этого в некоторых случаях. Например, win2 должно быть Win2.

...