KivyMD2中MDTextField与MDButton水平布局空间分配异常及垂直间距过大问题求助
Fixing MDTextField Width and Vertical Spacing Issues in KivyMD2 Horizontal Layouts
我来帮你搞定这两个KivyMD布局问题——文本框占满宽度挤压按钮,还有垂直间距太松的情况。下面是问题分析和修改后的完整代码:
修改后的完整代码
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" # 移除水平布局中干扰宽度分配的居中属性 # self.pos_hint={"center_x": .5} 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 # 固定宽度必须设置为None self.width = dp(120) # 正确设置按钮固定宽度 # 移除水平布局中不需要的居中属性 # self.pos_hint={"center_x": .5} 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", spacing=dp(10)) # 文本框占70%宽度,按钮用固定宽度 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", spacing=dp(10)) 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", spacing=dp(10)) 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", spacing=dp(10)) 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", spacing=dp(10)) self.tmtf = TxtField(htxt="Total Mech", 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, 10, 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.content_layout.add_widget(MDWidget()) 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()
关键修改说明
1. 解决文本框挤压按钮的问题
- 移除了
TxtField和mkbtn类中的pos_hint={"center_x": .5}:在水平MDBoxLayout中,控件位置由布局自动管理,手动设置居中属性会干扰宽度分配,导致文本框强行占满空间挤压按钮。 - 给
TxtField添加了可配置的shintx参数:创建文本框时传递shintx=0.7,让文本框占70%宽度,按钮用固定宽度dp(120)(同时设置size_hint_x=None确保固定宽度生效)。 - 修复了
mkbtn类的错误:把无效的self.wide = dp(120)改为self.width = dp(120),并给radius参数设置默认值避免报错。
2. 解决垂直间距过大的问题
- 调小了
content_layout的spacing值:从dp(10)改为dp(5),减少行与行之间的垂直距离。 - 移除了每个水平布局的
padding:因为content_layout已经设置了全局padding,重复添加会让布局过于松散。 - 移除了
content_layout末尾的MDWidget():这个控件会占据所有剩余垂直空间,导致上面的布局行被挤到顶部,看起来间距异常大。 - 添加了之前定义的
tlbl标签到布局中,避免浪费空间。
内容的提问来源于stack exchange,提问作者UnBorn
相关产品推荐
相关产品推荐

