Вопрос - область предварительного просмотра - RelativeLayout
Кажется, это работает, но не могли бы вы отредактировать или добавить пример, пожалуйста? я делаю
не нужно количество кнопок в области предварительного просмотра увеличено. я просто
хочу каждый раз после нажатия «Предварительный просмотр», в области предварительного просмотра у меня есть
контент, который просто отражает текущий текст self.kv и self.text.
Пример
В следующем примере применяется большинство улучшений, а область Preview
представляет собой RelativeLayout
.
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.properties import NumericProperty, StringProperty
from kivy.factory import Factory
KV = '''
BoxLayout:
BoxLayout:
orientation: 'vertical'
CodeEd
id: code_editor
Button:
text: 'Preview'
on_release: app.preview()
Preview:
id: preview_area
<CodeEd@TextInput>
text: app.text
<Preview@RelativeLayout>
'''
class MyApp(App):
text = StringProperty('')
previous_text = StringProperty('')
def build(self):
self._kv_filename = 'KvEditor_internal.' + str(self.uid)
self.text = '''
class MyButton(Button):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print (333)
return super(Button, self).on_touch_down(touch)
'''
self.previous_text = self.text
self.kv = 'MyButton'
self.root = Builder.load_string(KV)
def preview(self):
preview_area = self.root.ids.preview_area
self.text = self.root.ids.code_editor.text
try:
# Class loading is implemented using exec(, globals())
exec(self.text, globals())
except:
print('some error when exec class ')
Builder.unload_file(self._kv_filename)
try:
# check for code changes
if self.text != self.previous_text:
Factory.unregister(self.kv)
Factory.register(self.kv, cls=globals()[self.kv])
total_children = len(preview_area.children)
preview_area.clear_widgets()
for child in range(total_children):
preview_area.add_widget(Builder.load_string(self.kv, filename=self._kv_filename))
self.previous_text = self.text
preview_area.add_widget(Builder.load_string(self.kv, filename=self._kv_filename))
except Exception as e:
print(e.message if getattr(e, r"message", None) else str(e))
MyApp().run()
выход
Вопрос 1 - Ошибка типа
TypeError: super (type, obj): obj должен быть экземпляром или подтипом
тип
Решение - TypeError
Существует два решения для TypeError
.
Метод 1
Заменить super(MyButton, self).on_touch_down(touch)
на return False
Метод 2
Заменить super(MyButton, self).on_touch_down(touch)
на return super(Button, self).on_touch_down(touch)
Вопрос 2 - Изменения кода поддержки для класса MyButton
Что, если класс MyButton существует, но я хочу внести в него изменения
класс, например, изменить некоторые из его методов, и так далее?
Решение - Поддержка изменений кода для класса MyButton
Для поддержки изменений кода в классе MyButton
необходимы следующие улучшения:
- Добавить оператор импорта для Kivy Properties,
from kivy.properties import NumericProperty, StringProperty
- Добавить оператор импорта для объекта Kivy Factory,
from kivy.factory import Factory
- Добавить новый атрибут класса
previous_text
типа StringProperty
для отслеживания изменений кода.
- Инициализировать
self.previous_text
- Обновление
self.text
при вызове метода preview()
.
- Проверка изменений кода
- Отменить регистрацию предыдущего
class MyButton
с использованием Kivy Factory
- Зарегистрировать новый
class MyButton
используя Kivy Factory
- Сохранить общее количество
MyButton
добавлено
- Удалить ранее добавленные
MyButton
, используя clear_widgets()
. Если ранее добавленные MyButton
не удаляются, функциональность новых функций / изменений кода не будет.
- Используйте цикл
for
для повторного добавления ранее добавленного MyButton
с новыми функциями / возможностями.
- Назначить новые изменения кода,
self.text
на self.previous_text
Отрывки
from kivy.properties import NumericProperty, StringProperty
from kivy.factory import Factory
from kivy.logger import Logger
...
class MyApp(App):
i = NumericProperty(0)
text = StringProperty('')
previous_text = StringProperty('')
def build(self):
...
self.text = '''
...
return True # consumed on_touch_down & don't propagate
# return False
return super(Button, self).on_touch_down(touch)
'''
self.previous_text = self.text
...
def preview(self):
preview_area = self.root.ids.preview_area
self.text = self.root.ids.code_editor.text
...
try:
# check for code changes
if self.text != self.previous_text:
Factory.unregister(self.kv)
Factory.register(self.kv, cls=globals()[self.kv])
total_children = len(preview_area.children)
preview_area.clear_widgets()
for child in range(total_children):
btn = Builder.load_string(self.kv, filename=self._kv_filename)
btn.text = str(child + 1)
preview_area.add_widget(btn)
self.previous_text = self.text
Пример
В следующем примере показан редактор кода, поддерживающий изменения кода для класса MyButton
, и виджеты MyButton
добавляются в GridLayout
.
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty, StringProperty
from kivy.uix.button import Button
from kivy.logger import Logger
from kivy.factory import Factory
KV = '''
BoxLayout:
BoxLayout:
orientation: 'vertical'
CodeEd
id: code_editor
Button:
text: 'Preview'
on_release: app.preview()
Preview:
id: preview_area
<CodeEd@TextInput>:
text: app.text
<Preview@GridLayout>:
cols: 3
'''
class MyApp(App):
i = NumericProperty(0)
text = StringProperty('')
previous_text = StringProperty('')
def build(self):
self._kv_filename = 'KvEditor_internal.' + str(self.uid)
self.text = '''
class MyButton(Button):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print(f"touch.pos={touch.pos}")
print(f"Button.text={self.text}")
return True # consumed on_touch_down & don't propagate
# return False
return super(Button, self).on_touch_down(touch)
'''
self.previous_text = self.text
self.kv = 'MyButton'
self.root = Builder.load_string(KV)
def preview(self):
preview_area = self.root.ids.preview_area
self.text = self.root.ids.code_editor.text
try:
# Class loading is implemented using exec(, globals())
exec(self.text, globals())
except Exception as msg:
print('\nException: some error when exec class ')
Logger.error("KivyApp: Exception: some error when exec class")
print(msg)
quit()
Builder.unload_file(self._kv_filename)
try:
# check for code changes
if self.text != self.previous_text:
Factory.unregister(self.kv)
Factory.register(self.kv, cls=globals()['MyButton'])
total_children = len(preview_area.children)
preview_area.clear_widgets()
for child in range(total_children):
btn = Builder.load_string(self.kv, filename=self._kv_filename)
btn.text = str(child + 1)
preview_area.add_widget(btn)
self.previous_text = self.text
self.i += 1
btn = Builder.load_string(self.kv, filename=self._kv_filename)
btn.text = str(self.i)
preview_area.add_widget(btn)
except Exception as e:
print(e.message if getattr(e, r"message", None) else str(e))
MyApp().run()
выход