【问题标题】:Clearing the Kivy canvas with a keyboard key press使用键盘按键清除 Kivy 画布
【发布时间】:2018-08-28 22:47:06
【问题描述】:

我正在使用 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 时,我可以单击Draw 按钮,然后使用鼠标在画布上绘图。然后我可以通过单击 Clear 按钮来清除画布。但是按 c 键(在DrawScreen 类的_on_keyboard_down 函数中分配),画布不会被清除。然而,按下 c 键仍会将 kivy_variables.touch_data 变量分配给一个空列表 = [],并打印 cleared data 消息。

为什么self.ids.painter.canvas.clear() 函数在我使用按键时没有被正确调用,但在我使用 Kivy 按钮时却正常运行?我发现即使我将 self.ids.painter.canvas.clear() 函数调用移至 _on_keyboard_down 函数以便它直接调用而不是通过 on_release_clear 调用,我也会得到相同的行为。

这与我的初始化过程或我如何处理键盘事件有关吗?

【问题讨论】:

    标签: python button canvas keyboard kivy


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,成功了!对于任何将来引用此线程的用户,可以找到引用此 App 行为的文档here,其中提供了以下示例和说明:class ShowcaseApp(App): pass 此方法将在目录中搜索名为 showcase.kv 的文件包含 main.py。 kv 文件的名称必须是类的小写名称,如果存在,则末尾没有“App”后缀。
    猜你喜欢
    • 2010-12-03
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 2014-05-28
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    相关资源
    最近更新 更多