Корневые переменные kv недоступны в python - PullRequest
0 голосов
/ 01 июня 2018

Это мой файл kv, в котором я создал собственный виджет и две корневых переменной: имя и дату в самом kv.

<Entry@Widget>:
    name: ''
    date: ''
    size_hint: (None, None)
    canvas.before:
        Color:
            rgba: 1, 1, 1, .4
        Rectangle:
            pos: self.pos
            size: self.size
        Color:
            rgba: 0, 0, 0, 1
    Label:
        text: root.name[0:1]
        color: 41/255, 128/255, 185/255, 1
        pos: root.pos
        font_size: sp(50)
    Label:
        text: root.name[1:]
        color: 41/255, 128/255, 185/255, 1
        pos: root.x+sp(80), root.y+sp(8)
        font_size: sp(30)
    Label:
        text: root.date
        color: 17/255, 80/255, 122/255, 1
        pos: root.x+sp(50), root.y-sp(10)
        font_size: 10

И еще одна вещь.Я ovveride on_touch_down событие виджета Entry, как показано ниже в коде Python:

class Entry(RelativeLayout):

    def on_touch_down(self, touch):
        super(Entry, self).on_touch_down(touch)
        popup = Mypopup()
        popup.open()
        return True

Теперь на моем главном экране я динамически добавляю виджеты, поэтому я набрал код в Python, который выглядит примерно так: -

class MainScreen(FloatLayout):

    def __init__(self, **kargs):
        super(MainScreen, self).__init__(**kargs)
        layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
        layout.bind(minimum_height=layout.setter('height'))
        for i in range(100):
            entry = Entry(name='Facebook', date='30/21/2', size=(Window.width, sp(100)))
            layout.add_widget(entry)    
        scroll = ScrollView(size_hint=(1, None), height=Window.height)
        scroll.add_widget(layout)
        self.add_widget(scroll)

но это дает мне ошибку, говорящую: -

File "C:\Users\Himanshu Pharawal\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\app.py", line 802, in run
     root = self.build()    File "main.py", line 47, in build
     return MainScreen()    File "main.py", line 38, in __init__
     entry = Entry(name='Facebook', date='30/21/2', size=(Window.width, sp(100)))    File "main.py", line 21, in __init__
     super(Entry, self).__init__(*args, **kargs)    File "C:\Users\Himanshu Pharawal\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\relativelayout.py", line 265, in __init__
     super(RelativeLayout, self).__init__(**kw)    File "C:\Users\Himanshu Pharawal\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\floatlayout.py", line 65, in __init__
     super(FloatLayout, self).__init__(**kwargs)    File "C:\Users\Himanshu Pharawal\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)    File "C:\Users\Himanshu Pharawal\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\uix\widget.py", line 337, in __init__
     super(Widget, self).__init__(**kwargs)    File "kivy\_event.pyx", line 254, in kivy._event.EventDispatcher.__init__ (kivy\_event.c:5332) TypeError: object.__init__() takes no parameters

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Решение ошибки

Решение этой ошибки состоит в определении двух StringProperty переменных, name и date в классе Запись в main.py.

Переопределение метода on_touch_down

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

Snippets

class Entry(RelativeLayout):
    name = StringProperty()
    date = StringProperty()

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            popup = Mypopup()
            popup.open()
            return True
        return super(Entry, self).on_touch_down(touch)

Если касание попадает внутрь нашего виджета, мы создаем и открываем Mypopup и возвращаем True, указывая, что мы сработали касание и не хотим егодля дальнейшего распространения.

Наконец, если касание выходит за пределы нашего виджета, мы вызываем исходное событие, используя super(…), и возвращаем результат.Это позволяет продолжить распространение события касания, как обычно.

Руководство по программированию »Управление вводом» Основные сведения о событиях касания

По умолчанию события касанияотправляются всем отображаемым в данный момент виджетам.Это означает, что виджеты получают событие касания, независимо от того, происходит оно в своей физической области или нет....
Чтобы обеспечить максимальную гибкость, Kivy отправляет события всем виджетам и позволяет им решать, как на них реагировать.Если вы хотите отвечать только на сенсорные события внутри виджета, вы просто проверяете:

def on_touch_down(self, touch):
    if self.collide_point(*touch.pos):
        # The touch has occurred inside the widgets area. Do stuff!
        pass

Пример

main.py

from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.popup import Popup
from kivy.core.window import Window
from kivy.metrics import sp
from kivy.properties import StringProperty


class Mypopup(Popup):
    pass


class Entry(RelativeLayout):
    name = StringProperty()
    date = StringProperty()

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            popup = Mypopup()
            popup.open()
            return True
        return super(Entry, self).on_touch_down(touch)


class MainScreen(FloatLayout):

    def __init__(self, **kargs):
        super(MainScreen, self).__init__(**kargs)
        layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
        layout.bind(minimum_height=layout.setter('height'))
        for i in range(100):
            entry = Entry(name='Facebook', date='30/21/2', size=(Window.width, sp(100)))
            layout.add_widget(entry)
        scroll = ScrollView(size_hint=(1, None), height=Window.height)
        scroll.add_widget(layout)
        self.add_widget(scroll)


class TestApp(App):

    def build(self):
        return MainScreen()


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

test.кв

#:kivy 1.10.0

<Mypopup>:
    title: 'Test popup'
    size_hint: (None, None)
    size: (400, 400)
    BoxLayout:
        Label:
            text: 'Hello world'

<Entry@Widget>:
    name: ''
    date: ''
    size_hint: (None, None)
    canvas.before:
        Color:
            rgba: 1, 1, 1, .4
        Rectangle:
            pos: self.pos
            size: self.size
        Color:
            rgba: 0, 0, 0, 1
    Label:
        text: root.name[0:1]
        color: 41/255, 128/255, 185/255, 1
        pos: root.pos
        font_size: sp(50)
    Label:
        text: root.name[1:]
        color: 41/255, 128/255, 185/255, 1
        pos: root.x+sp(80), root.y+sp(8)
        font_size: sp(30)
    Label:
        text: root.date
        color: 17/255, 80/255, 122/255, 1
        pos: root.x+sp(50), root.y-sp(10)
        font_size: 10

Выход

Img01 - App Startup Img02 - Mypopup open

0 голосов
/ 02 июня 2018

Нельзя указать, что у вас есть класс с именем Entry, который наследуется от FloatLayout в .py, и другой Entry, который наследует от Widget в .kv, во-первых, он не будетОткажитесь от Entry, созданного в .kv, то, что вы должны сделать, это только указать, что вы собираетесь продолжать реализацию класса через <Entry> без чего-либо еще в .kv.

С другой стороны,Свойства имени и даты не идентифицируются автоматически, вы должны разделить их, как показано ниже:

main.py

from kivy.app import App

from kivy.core.window import Window

from kivy.metrics import sp

from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.popup import Popup

class Mypopup(Popup):
    pass

class Entry(FloatLayout):
    def __init__(self, name="", date="", **kwargs):
        super(Entry, self).__init__(**kwargs)
        self.name = name
        self.date = date

    def on_touch_down(self, touch):
        super(Entry, self).on_touch_down(touch)
        popup = Mypopup()
        popup.open()
        return True

class MainScreen(FloatLayout):
    def __init__(self, **kargs):
        super(MainScreen, self).__init__(**kargs)
        layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
        layout.bind(minimum_height=layout.setter('height'))
        for i in range(100):
            entry = Entry(name='Facebook', date='30/21/2', size=(Window.width, sp(100)))
            layout.add_widget(entry)    
        scroll = ScrollView(size_hint=(1, None), height=Window.height)
        scroll.add_widget(layout)
        self.add_widget(scroll)

class TestApp(App):
    def build(self):
        return MainScreen()

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

test.kv:

<Entry>:
    name: ''
    date: ''
    size_hint: (None, None)
    canvas.before:
        Color:
            rgba: 1, 1, 1, .4
        Rectangle:
            pos: self.pos
            size: self.size
        Color:
            rgba: 0, 0, 0, 1
    Label:
        text: root.name[0:1]
        color: 41/255, 128/255, 185/255, 1
        pos: root.pos
        font_size: sp(50)
    Label:
        text: root.name[1:]
        color: 41/255, 128/255, 185/255, 1
        pos: root.x+sp(80), root.y+sp(8)
        font_size: sp(30)
    Label:
        text: root.date
        color: 17/255, 80/255, 122/255, 1
        pos: root.x+sp(50), root.y-sp(10)
        font_size: 10
...