如何为Kivy中用kivy.graphics.line绘制的宽图表添加ScrollView?
实现Kivy图表横向滚动查看
我用kivy.graphics.line绘制了一个图表,当图表宽度超过窗口时,只能通过拉大窗口才能查看完整内容。想给图表添加ScrollView,实现宽度超出时可滚动查看完整图表。
修改后的实现代码
main.py
from kivymd.app import MDApp from kivy.uix.screenmanager import Screen from kivy.lang import Builder from kivy.graphics import Color, Line from kivy.properties import ObjectProperty class Graph(Screen): graph_container = ObjectProperty(None) # 绑定绘图容器 def drawLine(self): # 清空之前的绘图内容 self.graph_container.canvas.before.clear() z = 18 Xs = 50 Ys = 150 Step = 50 h0=3 h1 = 40 h2 = 80 h3 = 90 s = 1.5 # 计算图表实际宽度,设置容器宽度(加20留边距) max_x = Xs + Step//2 + (z + s)*Step self.graph_container.width = max_x + 20 with self.graph_container.canvas.before: Color(0.2, 0.2, 0.2, 1) for i in range(1,z+2): Line(points=[Xs+(i*Step), Ys, Xs+(i*Step), Ys+h1],width=1.4) Line(points=[Xs+Step, Ys, Xs+((z+1)*Step), Ys],width=1.4) Line(points=[Xs+Step, Ys+h1, Xs+((z+1)*Step), Ys+h1],width=1.4) Color(1, 0.2, 0.2, 1) for i in [1,7,13]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i+s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) for i in [4,10,16]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i-s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) Color(0.2, 1, 0.2, 1) for i in [3,9,15]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i+s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) for i in [6,12,18]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i-s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) Color(0.2, 0.2, 1, 1) for i in [17,5,11]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i+s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) for i in [2,8,14]: Line(points=[Xs+Step//2+(i*Step), Ys+h1+h2, Xs+Step//2+((i-s)*Step), Ys+h1+h2+h3],width=2) Line(points=[Xs+Step//2+(i*Step), Ys+h0+h1, Xs+Step//2+(i*Step), Ys+h1+h2],width=2) Builder.load_file("Graph.kv") class myapp(MDApp): def build(self): return Graph() myapp().run()
Graph.kv
<Graph>: graph_container: graph_container MDGridLayout: cols:1 size: root.size pos: root.pos MDFillRoundFlatButton: text:"绘图" on_release: root.drawLine() ScrollView: do_scroll_x: True # 开启横向滚动 do_scroll_y: False # 关闭纵向滚动 size_hint_y: 0.9 # 分配90%高度给滚动区域 FloatLayout: id: graph_container size_hint_x: None # 禁用宽度自适应,使用计算出的图表宽度 height: self.parent.height # 高度匹配滚动区域
关键修改说明
- 新增绘图容器:用
FloatLayout作为图表的载体,所有绘图操作都在这个容器的canvas上进行,避免直接绘制在Screen上(Screen尺寸与窗口绑定,无法滚动)。 - 设置容器宽度:计算图表的最大横向坐标,设置容器宽度为该值加边距,让ScrollView识别出内容超出视口,触发滚动。
- 配置ScrollView:开启横向滚动、关闭纵向滚动,设置合理的尺寸比例,确保按钮和滚动区域布局协调。
- 清空旧绘图:每次点击绘图按钮时先清空容器canvas,避免重复绘制导致内容叠加。
内容的提问来源于stack exchange,提问作者yosef podine
相关产品推荐
相关产品推荐

