【问题标题】:How to reference a Kivy Canvas in python如何在 python 中引用 Kivy Canvas
【发布时间】:2019-02-27 01:04:16
【问题描述】:

如果 UI 是在 kv 中构建的,我将如何引用 Kivy Canvas 以从 python 文件中绘图,例如这是我的 .py:

# canvasCallApp.py...

from kivy.app import App

class canvasCallApp(App):
    pass

if __name__ == '__main__':
    canvasCallApp().run()

还有我的 .kv:

# canvasCallApp.kv...

BoxLayout:
    id: left_box
    canvas:
        Color:
            rgb: 0.6, 0.6, 0.6
        Rectangle:
            pos: self.pos
            size: self.size
    Widget:
        size_hint_x: None
        width: left_box.width - right_box.width        
    BoxLayout:
        width: 200
        id: right_box
        Button:
            text: 'I ma a button'

产生:

我如何从 python 到达left_box 中的画布以进行绘图?无法从文档中弄清楚。

【问题讨论】:

    标签: python user-interface kivy kivy-language


    【解决方案1】:

    如果你愿意动态改变画布的颜色或大小,

    我建议使用 Kivy 属性。

    这里是代码。

    from kivy.properties import ListProperty
    from kivy.lang import Builder
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    
    
    class RootLayout(BoxLayout):
        canvas_color = ListProperty([0, 1, 1])
    
    
    class canvasCallApp(App):
        def build(self):
            return kv
    
    
    kv = Builder.load_string('''
    RootLayout:
        id: left_box
        canvas:
            Color:
                rgb: root.canvas_color
            Rectangle:
                pos: self.pos
                size: self.size
        Widget:
            size_hint_x: None
            width: left_box.width - right_box.width        
        BoxLayout:
            width: 200
            id: right_box
            Button:
                text: 'I ma a button'
    ''')
    
    
    if __name__ == '__main__':
        canvasCallApp().run()
    

    我还建议使用RootLayout,这样可以更轻松地通过root.variable_name 从 python 代码中引用变量。

    如果要改变canvas的背景,也可以将kivy代码改为

    canvas:
        Color:
            rgb: root.canvas_color
        Rectangle:
            pos: self.pos
            size: self.size
            source: root.image_path
    

    这样,您可以从kivy.properties 导入StringProperty 并应用相同的东西。随着image_path的值变化,背景会自动变化。

    如果您想直接访问画布以重绘画布,可以使用with canvas

    from kivy.uix.boxlayout import BoxLayout
    from kivy.graphics import Rectangle, Color
    
    class SomeBoxLayout(BoxLayout)
        def __init__(self, **kwargs):
            super(SomeBoxLayout, self).__init__(**kwargs)
    
            with self.canvas:
                Color(1, 0, 0, 1)  # set the color to red
                self.rect = Rectangle(pos=self.center,
                                      size=(self.width/2.,
                                            self.height/2.))
    
        def redraw(self):
            self.canvas.clear()
            with self.canvas:
                Color(0, 0, 1, 1)  # set the color to blue
                self.rect = Rectangle(pos=self.center,
                                      size=(self.width/2.,
                                            self.height/2.))
    

    请注意,您应该在再次绘制之前执行canvas.clear()

    另外,您可以通过这种方式使用with self.canvas.beforewith self.canvas.after

    【讨论】:

    • 谢谢,但我的目标是触发动画,所以不确定属性是否会削减它,正在考虑类似self.widget.canvas.clear() 但到目前为止没有运气。
    • @Keno 我添加了更多代码和一些解释。看看吧!
    【解决方案2】:

    我选择放弃单独的 kivy 语言并在 python 中完成这一切,这需要一些小部件嵌套以实现正确的布局,更重要的是创建、绑定和初始化一个小部件/画布对象,我们稍后可以参考:

    
    # canvasTest.py...
    
    from kivy.app import App
    from kivy.graphics import Rectangle
    from kivy.graphics import Color
    from kivy.uix.widget import Widget
    from kivy.uix.button import Button
    from kivy.uix.boxlayout import BoxLayout
    from random import random as r
    
    
    class rootCanvas(Widget):
        def __init__(self, **kwargs):
            super(rootCanvas, self).__init__(**kwargs)
            with self.canvas:
                Color(r(), 1, 1, mode='hsv')
                self.rect = Rectangle(pos=self.pos, size=self.size)
    
            self.bind(pos=self.update_rect)
            self.bind(size=self.update_rect)
    
        def update_rect(self, *args):
            self.rect.pos = self.pos
            self.rect.size = (self.size[0], self.size[1])
    
        def change_color(self, *args):
            with self.canvas:
                Color(r(), 1, 1, mode='hsv')
                self.rect = Rectangle(pos=self.pos, size=self.size)
    
    
    class canvasTest(App):
        def build(self):
            root = BoxLayout()
            sideBar = BoxLayout(size=(200, 100), size_hint=(None, 1))
            widget = rootCanvas()
            root.add_widget(widget)
            btn_1 = Button(
                text='Change Canvas Color',
                width=200,
                on_press=widget.change_color)
            sideBar.add_widget(btn_1)
            root.add_widget(sideBar)
            return root
    
    
    if __name__ == '__main__':
        canvasTest().run()
    
    
    
    
    

    结果:

    【讨论】:

    • 我也更喜欢在代码中做事,但从 .kv 声明转换可能会很棘手,因为文档倾向于只使用 .kv。你如何进行转换?反复试验,还是有更面向程序的文档/教程?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多