You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy DropDown不显示及类方法外调用open报错问题咨询

两个Kivy DropDown问题的原因与修复方案

问题1:点击主按钮后下拉列表未显示

你的代码里下拉列表其实已经被触发了,但Dropdown内部的按钮没有设置合适的尺寸,导致你看不到它们。默认情况下,Kivy的Buttonsize_hint_y是1,这意味着每个按钮会占满Dropdown的整个高度——两个按钮叠加后,第二个会被完全挤出可视区域,第一个也可能因为Dropdown默认高度不够显示不全。

另外,全局定义Dropdown和按钮不是最佳实践,但这不是直接导致不显示的核心原因。

修复方法很简单,给Dropdown里的按钮设置固定高度,同时把Dropdown的创建逻辑放到类内部避免全局变量:

import kivy
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout

class MainButton(Button):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 在类内部创建Dropdown,避免全局变量带来的生命周期问题
        self.dropdown = DropDown()
        # 给下拉按钮设置固定高度,确保能全部显示
        btn1 = Button(text="attack", size_hint_y=None, height=44)
        btn2 = Button(text="item", size_hint_y=None, height=44)
        self.dropdown.add_widget(btn1)
        self.dropdown.add_widget(btn2)

    def on_release(self):
        super().on_release()
        print("something")
        self.dropdown.open(self)

class Layout(FloatLayout):
    pass

class theApp(App):
    def build(self):
        layout = Layout()
        btn = MainButton(text="Hello")
        btn.pos_hint = {'x': 0.5, 'y': 0.5}
        btn.size_hint = (0.25, 0.25)
        layout.add_widget(btn)
        return layout

app = theApp()
app.run()

调整后每个按钮都有固定高度,Dropdown会自动适配总高度,点击主按钮就能看到完整的下拉列表了。

问题2:在build方法中调用DropDown.open()报错Cannot open a dropdown list on a hidden widget

这个错误的核心原因是:在build方法执行时,你的按钮还没有被渲染到窗口中,处于“隐藏”状态。Kivy要求调用Dropdown.open()时,目标Widget必须已经完成布局并显示在屏幕上。

当你在build里刚把btn添加到layout,此时layout还没有被返回给应用,Widget树还没完成初始化,btn还不是“可见”的,自然无法打开下拉列表。

修复方法是用Clock.schedule_once延迟执行dropdown.open(),等到Widget渲染完成后再调用:

import kivy
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock

class theApp(App):
    def build(self):
        layout = FloatLayout()
        self.btn = Button(text="Hello")
        self.btn.pos_hint = {'x': 0.5, 'y': 0.5}
        self.btn.size_hint = (0.25, 0.25)
        layout.add_widget(self.btn)
        
        self.dropdown = DropDown()
        btn1 = Button(text="attack", size_hint_y=None, height=44)
        btn2 = Button(text="item", size_hint_y=None, height=44)
        self.dropdown.add_widget(btn1)
        self.dropdown.add_widget(btn2)
        
        # 延迟一帧执行,确保Widget已经完成渲染
        Clock.schedule_once(self.open_dropdown, 0)
        return layout
    
    def open_dropdown(self, dt):
        self.dropdown.open(self.btn)

app = theApp()
app.run()

Clock.schedule_once(func, 0)会让open_dropdown方法在当前帧渲染完成后立即执行,此时btn已经处于可见状态,就不会再报错了。


内容的提问来源于stack exchange,提问作者Arief

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:24:25