KivyMD2中MDTextField与MDButton布局及行间距问题求助
问题修复方案
1. 解决文本框与按钮宽度分配问题
文本框(TxtField)调整
移除pos_hint={"center_x": .5}——在水平MDBoxLayout中,这个属性会强制文本框居中,直接挤压按钮空间。同时通过传入参数控制宽度比例,让按钮获得合理空间:
class TxtField(MDTextField): def __init__(self, ilen = 7, htxt="", shintx=0.7, **kwargs): super().__init__(**kwargs) self.mode = "outlined" self.size_hint_x = shintx # 用参数控制宽度占比 # 移除pos_hint={"center_x": .5} self.input_filter = lambda s, u: s if ( len(self.text) < ilen and s.isdigit() ) else "" if not htxt: htxt = "input:" self.add_widget( MDTextFieldHintText( text = htxt ) )
按钮(mkbtn)调整
把错误的self.wide = dp(120)改成self.width = dp(120),这是Kivy控件设置固定宽度的正确属性,同时移除pos_hint={"center_x": .5}避免布局错位:
class mkbtn(MDButton): def __init__( self, text, style="elevated", radius=[20,20,20,20], icon=None, func=lambda x: dummy_func(x), **kwargs): super().__init__(**kwargs) self.style = style self.radius = radius self.size_hint_x = None # 固定宽度时关闭比例控制 # 移除pos_hint={"center_x": .5} self.width = dp(120) # 设置固定宽度 if icon: self.add_widget(MDButtonIcon(icon)) self.add_widget(MDButtonText(text=text)) self.bind(on_release=func)
水平布局(hlay1~hlay5)调整
缩小水平布局的内边距和间距,同时给文本框传入合适的宽度比例参数:
self.hlay1 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5)) self.bdctf = TxtField(htxt="Bear DC", ilen=6, shintx=0.7) self.prof_btn = mkbtn("Profiles", icon="triangle-small-down") self.hlay1.add_widget(self.bdctf) self.hlay1.add_widget(self.prof_btn)
2. 解决垂直间距过大问题
- 调整
content_layout的spacing为更小的值,比如dp(5),减少行与行之间的垂直距离。 - 把每个水平布局的
padding=[5,5,5,5]改成padding=[5,0,5,0],去掉上下方向的多余内边距。 - 移除
content_layout里的MDWidget(),这个控件会占据大量垂直空白空间。
完整修复后代码
from kivymd.app import MDApp from kivymd.uix.screen import MDScreen from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.appbar import MDTopAppBar, MDTopAppBarTitle from kivymd.uix.label import MDLabel from kivymd.toast import toast from kivymd.uix.button import MDButton, MDButtonIcon, MDButtonText from kivymd.uix.widget import MDWidget from kivymd.icon_definitions import md_icons from kivymd.uix.textfield import ( MDTextField, MDTextFieldHintText, MDTextFieldMaxLengthText ) from kivymd.uix.segmentedbutton import ( MDSegmentedButton, MDSegmentedButtonItem, MDSegmentButtonLabel ) from kivymd.uix.dialog import ( MDDialog, MDDialogHeadlineText, MDDialogSupportingText, MDDialogButtonContainer ) from kivy.uix.widget import Widget from kivy.core.window import Window from kivy.core.text import Label as CoreLabel from kivy.metrics import dp class TxtField(MDTextField): def __init__(self, ilen = 7, htxt="", shintx=0.7, **kwargs): super().__init__(**kwargs) self.mode = "outlined" #"filled" self.size_hint_x = shintx self.input_filter = lambda s, u: s if ( len(self.text) < ilen and s.isdigit() ) else "" if not htxt: htxt = "input:" self.add_widget( MDTextFieldHintText( text = htxt ) ) class mkbtn(MDButton): def __init__( self, text, style="elevated", radius=[20,20,20,20], icon=None, func=lambda x: dummy_func(x), **kwargs): super().__init__(**kwargs) self.style = style self.radius = radius self.size_hint_x = None self.width = dp(120) if icon: self.add_widget(MDButtonIcon(icon)) self.add_widget(MDButtonText(text=text)) self.bind(on_release=func) def dummy_func(x="", y=""): pass class MainScreen(MDScreen): def __init__(self, **kwargs): super().__init__(**kwargs) self.md_bg_color = [1, 1, 1, 1] self.main_layout = MDBoxLayout(orientation="vertical") self.app_bar = MDTopAppBar(type="small") self.abtitle = MDTopAppBarTitle( text="WOS Squad Ratio (Bear/CJ)", halign="center" ) self.app_bar.add_widget(self.abtitle) self.content_layout = MDBoxLayout(orientation="vertical", padding=[5, 5, 5, 5], spacing=dp(5),) self.hlay1 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5)) self.bdctf = TxtField(htxt="Bear DC", ilen=6, shintx=0.7) self.prof_btn = mkbtn("Profiles", icon="triangle-small-down") self.hlay1.add_widget(self.bdctf) self.hlay1.add_widget(self.prof_btn) ### self.hlay2 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5),) self.cdctf = TxtField(htxt="CJ DC", ilen=6, shintx=0.7) self.aprof_btn = mkbtn("Add Profiles") self.hlay2.add_widget(self.cdctf) self.hlay2.add_widget(self.aprof_btn) ### self.hlay3 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5),) self.titf = TxtField(htxt="Total Infantry", ilen=7, shintx=0.7) self.cb_btn = mkbtn("Calc Bear") self.hlay3.add_widget(self.titf) self.hlay3.add_widget(self.cb_btn) ### self.hlay4 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5),) self.tltf = TxtField(htxt="Total Lancer", ilen=7, shintx=0.7) self.cc_btn = mkbtn("Calc CJ") self.hlay4.add_widget(self.tltf) self.hlay4.add_widget(self.cc_btn) ### self.hlay5 = MDBoxLayout(orientation="horizontal", padding=[5, 0, 5, 0], spacing=dp(5),) self.tmtf = TxtField(htxt="Total Lancer", ilen=7, shintx=0.7) self.sd_btn = mkbtn("Save Data") self.hlay5.add_widget(self.tmtf) self.hlay5.add_widget(self.sd_btn) ### self.tlbl = MDLabel(halign="left",role="large",padding=[5, 0, 0, 0],text = "") def cng_lbl(txt): self.tlbl.text = txt ### self.content_layout.add_widget(self.hlay1) self.content_layout.add_widget(self.hlay2) self.content_layout.add_widget(self.hlay3) self.content_layout.add_widget(self.hlay4) self.content_layout.add_widget(self.hlay5) self.content_layout.add_widget(self.tlbl) ### self.main_layout.add_widget(self.app_bar) self.main_layout.add_widget(self.content_layout) ### self.add_widget(self.main_layout) class MyApp(MDApp): def build(self): root = MainScreen() return root if __name__ == "__main__": MyApp().run()
关键修复点说明
- 移除
pos_hint={"center_x": .5}:该属性在水平布局中会打破宽度分配逻辑,导致元素错位挤压。 - 修正按钮宽度属性:
self.width是Kivy设置固定宽度的正确方式,原代码的self.wide是无效属性。 - 压缩布局间距:通过缩小垂直布局的
spacing和水平布局的上下padding,让整体布局更紧凑。 - 移除冗余控件:删除占据空白空间的
MDWidget(),避免底部出现不必要的间距。
内容的提问来源于stack exchange,提问作者UnBorn
相关产品推荐
相关产品推荐

