#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()
в файле kv4. Вы можете исключить этот
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')