Question Details

No question body available.

Tags

python android kivy kivymd

Answers (1)

April 20, 2026 Score: 1 Rep: 150,022 Quality: Medium Completeness: 100%

I don't know if I resolve all problems but I describe what I found.

It seems MDButton works different than other widgets.

Here is original MDButton.init

    def init(self, args, kwargs):
        super().__init__(args, kwargs)
        Clock.scheduleonce(self.adjustwidth, 0.2)
        Clock.scheduleonce(self.adjustpos, 0.2)

It uses Clock to run self.adjustwidth after 0.2 seconds to create button with minimal width - so it doesn't allow to use self.width at once in own init because it will be replaced by width calculated in self.adjustwidth

(by the way: as I remember init can't calculate it directly because Kivy creates real objects later, sets values from files .kv, and after that code can change sizes - and this is why it has to use Clock to run code later)

I see two methods for this:

  1. use also Clock to run own function which will change width little later
from kivy.clock import Clock

class mkbtn(MDButton): def init(...):

# ... code ...

Clock.scheduleonce(self.updatelater, 0.2)

def updatelater(self, args): self.width = dp(120)

  1. replace adjustwidth with own function - empty code - and it will not calculate own width
class mkbtn(MDButton):
    def init(...):

# ... code ...

self.width = dp(120)

def adjustwidth(self, args): pass

Result on desktop Linux

enter image description here

I also centered text on button (but text+icon may need different method)

#from kivy.clock import Clock

if you put this before class mkbtn then you can use func=dummyfunc

def dummyfunc(x="", y=""): pass

class mkbtn(MDButton): def init( self, text, style="elevated", # radius=[20, 20, 20, 20], icon=None, # func=lambda x: dummyfunc(x), func=dummyfunc, kwargs ):

super().init(kwargs) self.style = style self.radius = radius self.sizehintx = None

# self.adaptivewidth=True # self.sizehintminx = 0.3 # self.wide = dp(120) self.width = dp(120)

if icon: self.addwidget(MDButtonIcon(icon)) self.addwidget(MDButtonText(text=text)) self.bind(onrelease=func)

# center text on button - has to be after addwidget(MDButtonText(..>)) self.buttontext.poshint = {"centerx": 0.5, "centery": 0.5}

# center button # self.poshint = {"centerx": 0.5, "centery": 0.5} # center Y

# Clock.scheduleonce(self.updatelater, 0.2)

# def updatelater(self, args): # self.width = dp(120)

def adjustwidth(self, args): pass


If in Button and TextField you use poshint = {"centey": 0.5} then both widgets will looks like in one line.

enter image description here

#from kivy.clock import Clock

class TxtField(MDTextField): def init(self, ilen=7, htxt="", shintx=0.7, kwargs): super().init(kwargs) self.mode = "outlined" # "filled" self.sizehintx = 0.5

# center textfield in layout (Box) self.poshint = {"centerx": 0.5, "centery": 0.5} # center Y

self.inputfilter = lambda s, u: ( s if (len(self.text) < ilen and s.isdigit()) else "" )

if not htxt: htxt = "input:"

self.addwidget(MDTextFieldHintText(text=htxt))

if you put this before class mkbtn then you can use func=dummyfunc

def dummyfunc(x="", y=""): pass

class mkbtn(MDButton): def init( self, text, style="elevated", # radius=[20, 20, 20, 20], icon=None, # func=lambda x: dummyfunc(x), func=dummyfunc, kwargs ):

super().init(kwargs) self.style = style self.radius = radius self.sizehintx = None

# self.adaptivewidth=True # self.sizehintminx = 0.3 # self.wide = dp(120) self.width = dp(120)

if icon: self.addwidget(MDButtonIcon(icon)) self.addwidget(MDButtonText(text=text)) self.bind(onrelease=func)

# center text on button - has to be after addwidget(MDButtonText(..>)) self.buttontext.poshint = {"centerx": 0.5, "centery": 0.5}

# center button in layout (Box) self.poshint = {"centerx": 0.5, "centery": 0.5} # center Y

# Clock.scheduleonce(self.updatelater, 0.2)

# def updatelater(self, args): # self.width = dp(120)

def adjustwidth(self, args): pass


If you add background color in MDBoxLayout then you see how it is centered

        self.hlay5 = MDBoxLayout(
            orientation="horizontal",
            padding=[5, 5, 5, 5],
            spacing=dp(10),
            mdbgcolor=[1, 0, 0, 1],
        )

Before centering:

enter image description here

After centering:

enter image description here


To reduce height in rows I have to use sizehinty=None in every hlay and bind function which will calculates minimal height for every hlay

self.hlay4.bind(minimumheight=self.hlay4.setter("height"))

enter image description here

class MainScreen(MDScreen):
    def init(self, kwargs):
        super().init(kwargs)

self.mdbgcolor = [1, 1, 1, 1] # mdbgcolor: self.themecls.secondaryContainerColor

self.mainlayout = MDBoxLayout(orientation="vertical")

self.appbar = MDTopAppBar(type="small") self.abtitle = MDTopAppBarTitle( text="WOS Squad Ratio (Bear/CJ)", halign="center" ) self.appbar.addwidget(self.abtitle)

self.contentlayout = MDBoxLayout( orientation="vertical", padding=[5, 5, 5, 5], spacing=dp(10), )

self.hlay1 = MDBoxLayout( orientation="horizontal", padding=[5, 5, 5, 5], spacing=dp(10), sizehinty=None, ) self.bdctf = TxtField(htxt="Bear DC", ilen=6) self.profbtn = mkbtn("Profiles", icon="triangle-small-down") self.hlay1.addwidget(self.bdctf) self.hlay1.addwidget(self.profbtn) self.hlay1.bind(minimumheight=self.hlay1.setter("height"))

### self.hlay2 = MDBoxLayout( orientation="horizontal", padding=[5, 5, 5, 5], spacing=dp(10), sizehinty=None, ) self.cdctf = TxtField(htxt="CJ DC", ilen=6) self.aprofbtn = mkbtn("Add Profiles") self.hlay2.addwidget(self.cdctf) self.hlay2.addwidget(self.aprofbtn) self.hlay2.bind(minimumheight=self.hlay2.setter("height"))

### self.hlay3 = MDBoxLayout( orientation="horizontal", padding=[5, 5, 5, 5], spacing=dp(10), sizehinty=None, ) self.titf = TxtField(htxt="Total Infantry", ilen=7) self.cbbtn = mkbtn("Calc Bear") self.hlay3.addwidget(self.titf) self.hlay3.addwidget(self.cbbtn) self.hlay3.bind(minimumheight=self.hlay3.setter("height"))

### self.hlay4 = MDBoxLayout( orientation="horizontal", padding=[5, 5, 5, 5], spacing=dp(10), sizehinty=None, ) self.tltf = TxtField(htxt="Total Lancer", ilen=7) self.ccbtn = mkbtn("Calc CJ") self.hlay4.addwidget(self.tltf) self.hlay4.addwidget(self.ccbtn) self.hlay4.bind(minimumheight=self.hlay4.setter("height"))

### self.hlay5 = MDBoxLayout( orientation="horizontal", padding=[5, 5, 5, 5], spacing=dp(10), mdbgcolor=[1, 0, 0, 1], sizehinty=None, ) self.tmtf = TxtField(htxt="Total Lancer", ilen=7) self.sdbtn = mkbtn("Save Data") self.hlay5.addwidget(self.tmtf) self.hlay5.addwidget(self.sdbtn) self.hlay5.bind(minimumheight=self.hlay5.setter("height"))

### self.tlbl = MDLabel( halign="left", role="large", padding=[5, 0, 0, 500], text="", )

def cnglbl(txt): self.tlbl.text = txt

### self.contentlayout.addwidget(self.hlay1) self.contentlayout.addwidget(self.hlay2) self.contentlayout.addwidget(self.hlay3) self.contentlayout.addwidget(self.hlay4) self.contentlayout.addwidget(self.hlay5) self.contentlayout.addwidget( MDWidget( # sizehinty=1, # doesn't need this mdbgcolor=[0, 1, 0, 1], ) )

### self.mainlayout.addwidget(self.appbar) self.mainlayout.addwidget(self.contentlayout)

### self.addwidget(self.main_layout)

It keeps sizes after resizing window.

enter image description here

but problem is when window is too small to keep all elements

enter image description here