使用键盘键清除Kivy画布按

时间:2018-03-20 07:47:44

标签: python button canvas keyboard kivy

我正在使用Python库Kivy来构建一个简单的绘图应用程序。

我希望用户能够在画布上绘图,然后清除画布以开始新绘图。我已经能够实现一个清晰的画布功能,按下时由Kivy按钮调用,但是当按下键盘键并且调用相同的功能时,我没有得到相同的行为。

我的程序包含三个文件:

  • clear_debugging.py(主程序)
  • main.kv(用于创建屏幕和UI元素的Kivy文件)
  • kivy_variables.py(用于根据x,y坐标存储绘图数据)

clear_debugging.py的代码是:

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.config import Config
from kivy.graphics import Line

import kivy_variables

Config.set('input', 'mouse', 'mouse,multitouch_on_demand')

class Painter(Widget):

    def on_touch_down(self, touch):
        print("INFO: Touch begun!", touch.spos)
        kivy_variables.touch_data.append(touch.spos)
        with self.canvas:
            touch.ud["line"] = Line(points=(touch.x, touch.y), group='touch_lines')

    def on_touch_move(self, touch):
        print(touch.spos)
        kivy_variables.touch_data.append(touch.spos)
        touch.ud["line"].points += (touch.x, touch.y)

    def on_touch_up(self, touch):
        print("INFO: Touch released!")

class MainScreen(Screen):

    def exit_app(self):
        print("INFO: Exiting program.")
        Builder.unload_file("main.kv")
        App.get_running_app().stop()
        Window.close()

class DrawScreen(Screen):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print('INFO: The key', keycode, 'has been pressed')
        if keycode[1] == 'c':
            self.on_release_clear()
        return True # return True to accept the key

    def on_release_clear(self):
        kivy_variables.touch_data = []
        self.ids.painter.canvas.clear()
        print("INFO: Data cleared.")

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("main.kv")

class MainApp(App):

    def build(self):
        return presentation

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

main.kv的代码是:

#: import FadeTransition kivy.uix.screenmanager.FadeTransition

ScreenManagement:
    transition: FadeTransition()
    MainScreen:
    DrawScreen:

<MainScreen>:
    name: "main"
    GridLayout:
        rows: 2
        cols: 1
        Button:
            on_release: app.root.current = "draw"
            text: "Draw"
            font_size: 50
            size_hint: 0.15,0.1
        Button:
            on_release: root.exit_app()
            text: "Exit"
            font_size: 50
            size_hint: 0.15,0.1

<DrawScreen>:
    name: "draw"
    BoxLayout:
        Painter
            id: painter
        BoxLayout:
            Button:
                color: 0,1,0,1
                background_color: 0.5,0.5,0.5,0.5
                font_size: 20
                on_press: app.root.current = "main"
                text: "Back"
                size_hint: 0.2,0.1
                pos_hint: {"right":1, "top":1}
            Button:
                color: 0,1,0,1
                background_color: 0.5,0.5,0.5,0.5
                font_size: 20
                on_press: root.on_release_clear()
                text: "Clear"
                size_hint: 0.2,0.1
                pos_hint: {"right":1, "top":1}

kivy_variables.py的代码是:

touch_data = []

当我运行clear_debugging.py时,我可以单击绘制按钮,然后使用鼠标在画布上绘图。然后我可以通过单击清除按钮清除画布。但是按 c 键(在_on_keyboard_down类的DrawScreen函数中指定),画布不会被清除。但是,按 c 键仍会将kivy_variables.touch_data变量分配给空列表= [],并打印清除数据消息。

为什么在我使用按键时没有正确调用self.ids.painter.canvas.clear()函数,但在使用Kivy按钮时表现得如预期?即使我将self.ids.painter.canvas.clear()函数调用移到_on_keyboard_down函数中,我也会发现相同的行为,因此它直接调用而不是通过on_release_clear调用。

是否与我的初始化程序或我如何处理键盘事件有关?

1 个答案:

答案 0 :(得分:2)

您的代码正在实例化两个不同的DrawScreens,一个在运行presentation = Builder.load_file("main.kv")时另一个,而另一个在App类自动加载kv文件时。第一个是您实际在应用程序中显示的那个,但是当第二个实例化时,其键盘未绑定。当您按某个键时,您会看到消息就像正确接收一样,但这些消息实际上来自未在任何地方绘制的第二个DrawScreen。

您可以通过删除构建方法中的presentation = Builder.load_file("main.kv")return presentation来解决此问题;如果您不从构建方法返回任何内容,则kv文件中的根小部件将自动用作应用程序的根小部件。或者,您可以重命名kv文件。