在 Kivy 中程序 运行 时如何重绘 canvas?
how to redraw canvas while the program is running In Kivy?
我希望程序根据用户输入的两个值的比率重画线
我试过这个算法:
我有两个变量 pulse_length 和 distance_length。 these two points的坐标依比例=(distance_length/(distance_length+pulse_length)*540)+40
当我调用 TextInput 对象的 on_text_validate 事件时,我将输入的值写入变量并重绘 canvas。重绘canvas我用了self.canvas.ask_update(),但是不行
这里是简化的程序代码:
# input variables
pulse_length = 499
distance_length = 999
# calculations
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
class Line(Widget):
def __init__(self, **kwargs):
super(Line, self).__init__(**kwargs)
with self.canvas:
kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240),
# Other instructions ...
Callback(self.update)
def update(self, inst):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
self.canvas.ask_update()
class TextInputGrid(Widget):
def __init__(self, **kwargs):
super(TextInputGrid, self).__init__(**kwargs)
self.inputlayout = GridLayout(cols=1, size=(100, 30))
self.inputlayout.textfield = TextInput(multiline=False)
self.inputlayout.add_widget(self.inputlayout.textfield)
class MyFloatLayout(FloatLayout):
def __init__(self, **kwargs):
super(FloatLayout, self).__init__(**kwargs)
# Drawn line widget
self.add_widget(Line())
# TextInput 1
self.textinput1 = TextInputGrid()
self.textinput1.inputlayout.textfield.bind(on_text_validate=self.enter_pulse)
# TextInput 2
self.textinput2 = TextInputGrid()
self.textinput2.inputlayout.textfield.bind(on_text_validate=self.enter_distance)
self.add_widget(self.textinput1.inputlayout)
self.add_widget(self.textinput2.inputlayout)
def enter_pulse(self, instance):
global pulse_length
pulse_length = int(self.textinput1.inputlayout.textfield.text)
def enter_distance(self, instance):
global distance_length
distance_length = int(self.textinput2.inputlayout.textfield.text)
class GeneratorApp(App):
def build(self):
return MyFloatLayout()
if __name__ == '__main__':
GeneratorApp().run()
也许我不知道 ask_update() 是如何工作的?如果是,请解释如何重绘 canvas。或者如果算法不正确,请告诉我如何实现这样的程序。
我发现 kg
是 Kivy.graphics
。
当您在 Canvas
指令中使用 ratio
时,它使用 ratio
的当前值,并且不记得该值来自何处。因此,更改 ratio
的当前值不会更改 Line
。为了更新 Line
,您需要重新绘制它。这是对您的代码的修改,它删除了旧的 Line
并绘制了一个新版本:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
import kivy.graphics as kg
# input variables
pulse_length = 499
distance_length = 999
class Line(Widget):
def __init__(self, **kwargs):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
super(Line, self).__init__(**kwargs)
with self.canvas:
self.line = kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240))
# Other instructions ...
#Callback(self.update)
def update(self):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
self.canvas.remove(self.line)
with self.canvas:
self.line = kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240))
class TextInputGrid(Widget):
def __init__(self, **kwargs):
super(TextInputGrid, self).__init__(**kwargs)
self.inputlayout = GridLayout(cols=1, size=(100, 30))
self.inputlayout.textfield = TextInput(multiline=False)
self.inputlayout.add_widget(self.inputlayout.textfield)
class MyFloatLayout(FloatLayout):
def __init__(self, **kwargs):
super(FloatLayout, self).__init__(**kwargs)
# Drawn line widget
self.line = Line()
self.add_widget(self.line)
# TextInput 1
self.textinput1 = TextInputGrid(pos=(0,0))
self.textinput1.inputlayout.textfield.bind(on_text_validate=self.enter_pulse)
# TextInput 2
self.textinput2 = TextInputGrid(pos=(100,100))
self.textinput2.inputlayout.textfield.bind(on_text_validate=self.enter_distance)
self.add_widget(self.textinput1.inputlayout)
self.add_widget(self.textinput2.inputlayout)
def enter_pulse(self, instance):
global pulse_length
pulse_length = int(self.textinput1.inputlayout.textfield.text)
self.line.update()
def enter_distance(self, instance):
global distance_length
distance_length = int(self.textinput2.inputlayout.textfield.text)
self.line.update()
class GeneratorApp(App):
def build(self):
return MyFloatLayout()
if __name__ == '__main__':
GeneratorApp().run()
我希望程序根据用户输入的两个值的比率重画线
我试过这个算法: 我有两个变量 pulse_length 和 distance_length。 these two points的坐标依比例=(distance_length/(distance_length+pulse_length)*540)+40
当我调用 TextInput 对象的 on_text_validate 事件时,我将输入的值写入变量并重绘 canvas。重绘canvas我用了self.canvas.ask_update(),但是不行
这里是简化的程序代码:
# input variables
pulse_length = 499
distance_length = 999
# calculations
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
class Line(Widget):
def __init__(self, **kwargs):
super(Line, self).__init__(**kwargs)
with self.canvas:
kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240),
# Other instructions ...
Callback(self.update)
def update(self, inst):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
self.canvas.ask_update()
class TextInputGrid(Widget):
def __init__(self, **kwargs):
super(TextInputGrid, self).__init__(**kwargs)
self.inputlayout = GridLayout(cols=1, size=(100, 30))
self.inputlayout.textfield = TextInput(multiline=False)
self.inputlayout.add_widget(self.inputlayout.textfield)
class MyFloatLayout(FloatLayout):
def __init__(self, **kwargs):
super(FloatLayout, self).__init__(**kwargs)
# Drawn line widget
self.add_widget(Line())
# TextInput 1
self.textinput1 = TextInputGrid()
self.textinput1.inputlayout.textfield.bind(on_text_validate=self.enter_pulse)
# TextInput 2
self.textinput2 = TextInputGrid()
self.textinput2.inputlayout.textfield.bind(on_text_validate=self.enter_distance)
self.add_widget(self.textinput1.inputlayout)
self.add_widget(self.textinput2.inputlayout)
def enter_pulse(self, instance):
global pulse_length
pulse_length = int(self.textinput1.inputlayout.textfield.text)
def enter_distance(self, instance):
global distance_length
distance_length = int(self.textinput2.inputlayout.textfield.text)
class GeneratorApp(App):
def build(self):
return MyFloatLayout()
if __name__ == '__main__':
GeneratorApp().run()
也许我不知道 ask_update() 是如何工作的?如果是,请解释如何重绘 canvas。或者如果算法不正确,请告诉我如何实现这样的程序。
我发现 kg
是 Kivy.graphics
。
当您在 Canvas
指令中使用 ratio
时,它使用 ratio
的当前值,并且不记得该值来自何处。因此,更改 ratio
的当前值不会更改 Line
。为了更新 Line
,您需要重新绘制它。这是对您的代码的修改,它删除了旧的 Line
并绘制了一个新版本:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
import kivy.graphics as kg
# input variables
pulse_length = 499
distance_length = 999
class Line(Widget):
def __init__(self, **kwargs):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
super(Line, self).__init__(**kwargs)
with self.canvas:
self.line = kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240))
# Other instructions ...
#Callback(self.update)
def update(self):
ratio = (distance_length / (distance_length + pulse_length) * 540) + 40
self.canvas.remove(self.line)
with self.canvas:
self.line = kg.Line(
points=(
20, 350,
40, 350,
40, 240,
ratio, 240,
ratio, 350,
560, 350,
560, 240,
620, 240))
class TextInputGrid(Widget):
def __init__(self, **kwargs):
super(TextInputGrid, self).__init__(**kwargs)
self.inputlayout = GridLayout(cols=1, size=(100, 30))
self.inputlayout.textfield = TextInput(multiline=False)
self.inputlayout.add_widget(self.inputlayout.textfield)
class MyFloatLayout(FloatLayout):
def __init__(self, **kwargs):
super(FloatLayout, self).__init__(**kwargs)
# Drawn line widget
self.line = Line()
self.add_widget(self.line)
# TextInput 1
self.textinput1 = TextInputGrid(pos=(0,0))
self.textinput1.inputlayout.textfield.bind(on_text_validate=self.enter_pulse)
# TextInput 2
self.textinput2 = TextInputGrid(pos=(100,100))
self.textinput2.inputlayout.textfield.bind(on_text_validate=self.enter_distance)
self.add_widget(self.textinput1.inputlayout)
self.add_widget(self.textinput2.inputlayout)
def enter_pulse(self, instance):
global pulse_length
pulse_length = int(self.textinput1.inputlayout.textfield.text)
self.line.update()
def enter_distance(self, instance):
global distance_length
distance_length = int(self.textinput2.inputlayout.textfield.text)
self.line.update()
class GeneratorApp(App):
def build(self):
return MyFloatLayout()
if __name__ == '__main__':
GeneratorApp().run()