for my application I designed a simple on screen keyboard (OSK), it is needed on touchscreens but may be used also with the mouse. Initially the happlication had to run on 1920x1080 screens only, but now I have many requests to port on different resolutions. The problem is that the OSK was designed in the simplest way to fulfill the 1920x1080 screen so I adapted the font to obtain the right width for the buttons set to 4, where 4 is the number of chars may be shown in the button. But now, to adapt the OSK to every resolution I should calculate the width of the buttons. The OSK has 14 columns, special buttons as Shift, Enter, Backspace, Tab etc. have a width of 2 columns (they extend on 2 columns) and there is an horizontal padding of 10 piels between the buttons and the external limit of the OSK, so there are 15 "spacers" for 14 columns of buttons. I am able to compute the buttons width in pixels but I am not able to set the buttons width in pixels... only in number of characters. Is there anything I missed? Or does exist a workaround? If may help I can set the font to a common non proprotional one. I made a little test program to see if is possible to set the width in pixels of a ttk.Button, seems I am not able to do it:
def testButtonsType():
def select(choice):
choice = choice
if choice=="yes":
print("yes")
else:
print("no")
#---------------------------------------------------------------------------
mainWin = Tk()
mainWin.title("Main Window")
mainWin.geometry('400x250')
pixel = tk.PhotoImage(width=1, height=1)
s = ttk.Style()
s.configure("osk.TButton",foreground="black",
background="white",
height=50,
# padding=[10, 10, 10, 10],
font = "None 14 bold")
btnYes = ttk.Button(mainWin, text='SI', image=pixel, compound='c', width=200, style="osk.TButton", command=lambda: select("yes"))
btnYes.grid(pady=(20,30), sticky='n', column=1, row=0)
btnNo = tk.Button(mainWin, text='NO', image=pixel, compound='c', width=100, height=50, font = ("None 14 bold"), command=lambda: select("no"))
btnNo.grid(padx=(20,20), pady=(20,30), sticky='n', column=0, row=0)
mainWin.mainloop()
#-------------------------------------------------------------------------
This is a simplified implementation of OSK class, it manages only the first row of buttons and assumes they have all the same width. The OSK is done for a 1600x900 screen but the width of the button is larger so only 11 and one third of the 12st button are visible. Obviously something is wrong but I do not understand what is wrong.
class OSK(Toplevel):
__metaclass__ = Singleton
def __init__(self, attach, rootWin, flgCloseOnEnter=True):
super().__init__()
self.title('On Screen Keyboard')
self.flgCloseOnEnter = flgCloseOnEnter
rW = 1600
rH = 900
oskHeight = 260
keyColsCount = 14
keysRowCount = 5
padXleft = 10
padYleft = 10
self.btnW = 5
self.btnH = 32
self.style = ttk.Style()
self.theme = "dark"
self.Theme()
self.geometry('%dx%d+%d+%d' % (rW, oskHeight, 0, rH-oskHeight))
self.frmTop = Frame(self, style="osk.TFrame")
self.grid_columnconfigure(0,weight=0)
# self.frmTop.grid(padx=(padXleft,padXleft), pady=(padYleft,padYleft), sticky='nwse')
self.frmTop.grid(sticky='nwse')
for i in range(15):
self.frmTop.grid_columnconfigure(i, minsize=self.btnW, weight=0)
for i in range(5):
self.frmTop.grid_rowconfigure(i, minsize=self.btnH)
self.mainWin = self
self.btnPadX = 10
self.btnPadY = 4
# showing all data in display
self.exp = " "
self.is_shift = False
self.attach = attach
self.overrideredirect(True)
tick = Button(self.frmTop, text='`', command=lambda: self.press('`'), style="osk.TButton")
tick.grid(row=0, column=0, sticky='nwes')
num1 = Button(self.frmTop, text='1', command=lambda: self.press('1'), style="osk.TButton")
num1.grid(row=0, column=1, sticky='nwes')
num2 = Button(self.frmTop, text='2', command=lambda: self.press('2'), style="osk.TButton")
num2.grid(row=0, column=2, sticky='nwes')
num3 = Button(self.frmTop, text='3', command=lambda: self.press('3'), style="osk.TButton")
num3.grid(row=0, column=3, sticky='nwes')
num4 = Button(self.frmTop, text='4', command=lambda: self.press('4'), style="osk.TButton")
num4.grid(row=0, column=4, sticky='nwes')
num5 = Button(self.frmTop, text='5', command=lambda: self.press('5'), style="osk.TButton")
num5.grid(row=0, column=5, sticky='nwes')
num6 = Button(self.frmTop, text='6', command=lambda: self.press('6'), style="osk.TButton")
num6.grid(row=0, column=6, sticky='nwes')
num7 = Button(self.frmTop, text='7', command=lambda: self.press('7'), style="osk.TButton")
num7.grid(row=0, column=7, sticky='nwes')
num8 = Button(self.frmTop, text='8', command=lambda: self.press('8'), style="osk.TButton")
num8.grid(row=0, column=8, sticky='nwes')
num9 = Button(self.frmTop, text='9', command=lambda: self.press('9'), style="osk.TButton")
num9.grid(row=0, column=9, sticky='nwes')
numA = Button(self.frmTop, text='A', command=lambda: self.press('A'), style="osk.TButton")
numA.grid(row=0, column=10, sticky='nwes')
numB = Button(self.frmTop, text='B', command=lambda: self.press('B'), style="osk.TButton")
numB.grid(row=0, column=11, sticky='nwes')
numC = Button(self.frmTop, text='C', command=lambda: self.press('C'), style="osk.TButton")
numC.grid(row=0, column=12, sticky='nwes')
numD = Button(self.frmTop, text='D', command=lambda: self.press('D'), style="osk.TButton")
numD.grid(row=0, column=13, sticky='nwes')
numE = Button(self.frmTop, text='E', command=lambda: self.press('E'), style="osk.TButton")
numE.grid(row=0, column=14, sticky='nwes')
#---------------------------------------------------------------------------
# Needed functions
def getAttach(self):
return self.attach
#---------------------------------------------------------------------------
def setAttach(self, org):
self.attach = org
#---------------------------------------------------------------------------
def press(self, num):
print(num)
#---------------------------------------------------------------------------
def Backspace(self):
n = len( self.attach.get() )
self.attach.delete(n-1)
#---------------------------------------------------------------------------
def Enter(self):
if self.flgCloseOnEnter == True:
self.destroy()
else:
self.attach.insert(END, '\n')
#---------------------------------------------------------------------------
def Shift(self):
if True:
self.is_shift = not self.is_shift
self.display()
else:
self.is_shift = not self.is_shift
self.display()
#---------------------------------------------------------------------------
def Clear(self):
self.attach.delete(0, END)
#---------------------------------------------------------------------------
def Theme(self):
font = (None, 16)
if True:
if self.theme == "dark":
self.configure(bg='gray27')
self.style.configure('osk.TButton', background='gray21', foreground='black', font=font)
self.style.configure('osk.TEntry', background='gray21', foreground='black')
self.style.configure('osk.TFrame', bg='gray27')
self.theme = "light"
elif self.theme == "light":
self.configure(bg='gray99')
self.style.configure('osk.TButton', background='azure', foreground='black', font=font)
self.style.configure('osk.TEntry', background='azure', foreground='black')
self.style.configure('osk.TFrame', bg='gray99')
self.theme = "dark"
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
if __name__ == '__main__':
def testMinOSK():
mainWin = Tk()
top = OSK(None, mainWin)
mainWin.mainloop()
#-------------------------------------------------------------------------
testMinOSK()
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------