Измените TextInput на отображение только функции для Kivy Python

#python-3.x #kivy #kivy-language

Вопрос:

Я все еще новичок в киви и все еще относительно новичок в Python. У меня есть main. py. Я планирую WindowGUI принять ряд предложений от main.py и отобразите их в своем текстовом поле. Вот что у меня есть:

 from os import curdir
from posixpath import dirname
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout  # one of many layout structures
from kivy.uix.textinput import TextInput  # allow for ...text input.
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.spinner import Spinner
from kivy.uix.dropdown import DropDown
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
kivy.require('2.0.0')

class MainGUI(Screen):
    encoder = ObjectProperty()
    mileage = ObjectProperty()
    voltage = ObjectProperty()
    power = ObjectProperty()
    camera = ObjectProperty()
    engaged = ObjectProperty()
    idle = ObjectProperty()
    log = ObjectProperty()
    clear = ObjectProperty()
    status = ObjectProperty(None)

    def __init__(self, saySomething): 
        super().__init__() #Go up to __init__ of App
        self.saySomething = saySomething
    
    def power_option(self):
        self.power.text = "Power"
    
    def print_status(self):
        self.ids.Status_screen.text = self.saySomething
        return self.ids.Status_screen.text

class CameraGUI(Screen):
    def __init__(self, **kwargs): #kwargs is just a variable. it could be "banana" or "apple"
        super().__init__() #Go up to __init__ of App

class GUIManager(ScreenManager):
    pass

kv = Builder.load_file('newWindow.kv')

class WindowGUI(App):
    def __init__(self):
        super().__init__()
        # self.say = say
        print("TRY ME!!!!")
        
    
    def build(self):
        self.title = 'IamHero'
        return kv
    
if __name__ == '__main__':
   myWindowGUI = WindowGUI()
   myMainGUI = MainGUI('I am hero!')
   myWindowGUI.run()

###########################_newWindow.kv_#############################

GUIManager:
    MainGUI:
    CameraGUI:

<MainGUI>:
    name: "main"

    status: Status_screen
    GridLayout:
        cols: 2
        size: root.width, root.height #covers entire window
        padding: 15
        
        GridLayout:
            cols:1
            spacing: 10
            GridLayout:
                cols:2
                size_hint: .25,.1  
                Label:
                    id: Engaged
                    text: "Engaged"   
                Label:
                    id: Idle
                    text: "Idle"
            TextInput:
                # size_hint: 1
                id: Status_screen
                multiline: True
                readonly: True
                background_color: .6, .7, 0, 1
                text: root.print_status()
                #on_text: root.print_status()
               
            GridLayout:
                cols:2
                size_hint: .25,.1  
                Button:
                    id: Log
                    text: "Log status"
                    # size_hint_x: .5
                Button:
                    id: Clear
                    text: "Clear"
 

Однако я получил следующую ошибку:

  Traceback (most recent call last):
   File "c:/Users/Jojo/#RaspberryPi4/Test/WindowGUI.py", line 57, in <module>
     kv = Builder.load_file('newWindow.kv')
   File "C:UsersJojoAnaconda3libsite-packageskivylangbuilder.py", line 306, in load_file
     return self.load_string(data, **kwargs)
   File "C:UsersJojoAnaconda3libsite-packageskivylangbuilder.py", line 408, in load_string
     self._apply_rule(
   File "C:UsersJojoAnaconda3libsite-packageskivylangbuilder.py", line 659, in _apply_rule
     child = cls(__no_builder=True)
 TypeError: __init__() got an unexpected keyword argument '__no_builder'
 

Есть какие — нибудь идеи о том, что я сделал не так?

Ответ №1:

Вам не может потребоваться позиционный аргумент в __init__() классе, в котором вы собираетесь использовать kv . Ваше __init__() для MainGUI :

 def __init__(self, saySomething):
 

требуется аргумент для saySomething . Самый простой способ обойти это-просто saySomething превратиться в StringProperty из MainGUI . Тогда вам даже не нужно будет реализовывать __init__() :

 class MainGUI(Screen):
    encoder = ObjectProperty()
    mileage = ObjectProperty()
    voltage = ObjectProperty()
    power = ObjectProperty()
    camera = ObjectProperty()
    engaged = ObjectProperty()
    idle = ObjectProperty()
    log = ObjectProperty()
    clear = ObjectProperty()
    status = ObjectProperty(None)
    saySomething = StringProperty('Hi')

    # def __init__(self, saySomething):
    #     super().__init__() #Go up to __init__ of App
    #     self.saySomething = saySomething
 

Затем вы можете установить значение saySomething так же, как и любое другое свойство в kv :

 <MainGUI>:
    name: "main"

    status: Status_screen
    saySomething: 'I am hero!'
 

или в python вы можете сделать:

 MainGUI(saySomething='I am hero!')
 

Кроме того, линия:

 myMainGUI = MainGUI('I am hero!')
 

(который больше не будет работать) создает экземпляр MainGUI , который не используется. Так что эту строку кода можно удалить.

Комментарии:

1. У меня есть моя main.py в который будут передаваться переменные MainGUI . Ваше решение, похоже, не позволяет мне достичь этого…или я что-то упускаю здесь? Мне все еще нужно создать экземпляр класса, если я хочу передать ему что-нибудь, верно?

2. Builder.load_file('newWindow.kv') Создает экземпляр MainGUI того, что вы видите в своем App . Если вы создадите другой экземпляр MainGUI , он не будет иметь никакой связи с экземпляром, который отображается в вашем графическом интерфейсе. Итак, вам нужно получить ссылку на уже существующий экземпляр, что-то вроде: mainGUI = self.root.get_screen('main') (если выполняется в App методе). Тогда ты сможешь это сделать mainGUI.saySomething = 'Abba Dabba Doo' .

3. ОК. Так что я вкладываю MainGUI = self.root.get_screen('main') и MainGUI.saySomething = 'Abba Dabba Doo' def __init__(self): class WindowGUI(App) вкладываю и вкладываю saySomething = StringProperty() MainGUI . Что мне тогда делать def print_status(self): ? У меня есть text: root.print_status() в файле kv

4. Вы можете исключить этот print_status() метод и ввести text: root.saySomething kv . Кроме того, настройка MainGUI = anything -плохая идея, потому MainGUI что это класс. Храните имена классов и имена переменных отдельно.

5. Круто. Я исправил MainGUI mainGUI это в def __init__(self): классе WindowGUI(App) . Теперь я получил эту ошибку: AttributeError: 'NoneType' object has no attribute 'get_screen' ссылаясь на mainGUI = self.root.get_screen('main')