Kivy按钮点击弹出弹窗及OntopLabel尺寸参数设置问题
Kivy开发问题解答
1. OntopLabel(BoxLayout子类)尺寸设置方法
你当前代码里OntopLabel实例化时没有指定任何尺寸参数,加上初始化逻辑有两处错误,才会出现尺寸不符合预期的问题:
- 第一处错误:
super().__init__()没有传入**kwargs,后续实例化时传的尺寸、位置参数都不会生效 - 第二处错误:画布上的背景矩形没有绑定组件的
pos和size变更事件,就算组件尺寸改了,背景也不会跟着同步变化
修正和设置尺寸的方式分两种:
方式一:组件内部固定默认尺寸
直接修改ontop_label.py代码:
from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.graphics import Color, Rectangle from kivy.utils import get_color_from_hex class OntopLabel(BoxLayout): def __init__(self, **kwargs): super().__init__(**kwargs) # 必须传入kwargs # 设置自身尺寸,两种模式二选一 # 固定像素尺寸 self.size_hint = (None, None) self.size = (200, 100) # 按父布局比例设置(比如宽占父布局80%,高占30%) # self.size_hint = (0.8, 0.3) # 设置居中 self.pos_hint = {"center_x": .5, "center_y": .5} with self.canvas.before: Color(rgba=get_color_from_hex("#6C5B7B")[:3] + [.5]) self.rect = Rectangle(size=self.size, pos=self.pos) # 绑定更新事件,让背景跟着组件走 self.bind(pos=self._update_rect, size=self._update_rect) lbl = Label(text='Hi', size_hint=(1, 1), pos_hint={"center_x": .5}) self.add_widget(lbl) def _update_rect(self, instance, value): self.rect.pos = instance.pos self.rect.size = instance.size
方式二:实例化时动态传参设置尺寸
不在组件内部固定尺寸,在添加组件的时候自定义参数即可:
# main.py 里的add_my_label方法 def add_my_label(self): lbl = OntopLabel( size_hint=(0.8, 0.3), pos_hint={"center_x": 0.5, "center_y": 0.5} ) self.add_widget(lbl)
注意:OntopLabel是直接add到TestWidget上的,层级会在内部BoxLayout和按钮的上方,不会被遮挡。
2. 点击弹出展示终端输出的弹窗实现方案
不需要更换现有基础布局,直接用Kivy自带的Popup组件实现即可,比自定义浮层更方便,自带焦点拦截、点外部关闭、标题栏等基础能力,不用重复造轮子。
最简实现步骤:
- 第一步:如果需要捕获所有
print的终端输出,在App启动时重定向标准输出流到内存缓存 - 第二步:给按钮绑定弹窗打开事件,弹窗内容用Label加载缓存里的输出内容即可
参考代码如下:
修改main.py:
import sys from io import StringIO from kivy.uix.popup import Popup from kivy.uix.label import Label from kivy.app import App from kivy.uix.widget import Widget from kivy.lang import Builder # 记得导入你写的OntopLabel类 class TestWidget(Widget): def show_output_popup(self): # 读取缓存的终端输出 output_text = MyApp.get_running_app().output_buffer.getvalue() if not output_text: output_text = "暂无终端输出" # 初始化弹窗 popup = Popup( title="终端输出内容", content=Label( text=output_text, text_size=(self.width*0.7, None), # 自动换行 halign="left", valign="top" ), size_hint=(0.8, 0.6), auto_dismiss=True ) popup.open() class MyApp(App): def build(self): # 重定向stdout捕获所有终端输出 self.output_buffer = StringIO() sys.stdout = self.output_buffer return Builder.load_file('main.kv') if __name__ == '__main__': MyApp().run()
修改main.kv里的按钮绑定事件:
TestWidget: <TestWidget>: BoxLayout: size: root.width, root.height orientation:'vertical' Button: size_hint: 1, 1 text: 'Press' on_press: root.show_output_popup()
补充:如果需要弹窗里的内容实时更新终端输出,加个Clock定时任务,每隔300毫秒读取一次缓存内容,更新弹窗里Label的text属性即可。
内容的提问来源于stack exchange,提问作者Melleo
相关产品推荐
相关产品推荐

