Combobox fontsize in tkinter - python

Hi I am trying to use the ttk Combobox to create a dropdown with options .
While doing so i can configure the font size of the default value passed to it .
But when i click the arrow the font size of the other values remains the same .I am developing the app for touchscreen , so i need to provide proper size .
Heres the sample code , when i run the code the size of A is bigger , button the on clicking the arrow key i see the other values are of default size .
#! /usr/bin/python
from Tkinter import *
import ttk
class Application:
def __init__(self, parent):
self.parent = parent
self.combo()
def combo(self):
self.box_value = StringVar()
self.box = ttk.Combobox(self.parent, textvariable=self.box_value,font=("Helvetica",20))
self.box['values'] = ('A', 'B', 'C')
self.box.current(0)
self.box.grid(column=0, row=0)
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()

The thing is that the dropdown menu of the ttk Combobox is actually a simple Tkinter Listbox so it isn't affected by the ttk style. If it would be possible to get a reference to the Listbox from the Combobox, changing the font would be easy. However, I couldn't find a way to do so in Tkinter.
Edited as per patthoyts' very useful comment.
What you can do is change the font for all Listboxes that are part of a Combobox using
bigfont = tkFont.Font(family="Helvetica",size=20)
root.option_add("*TCombobox*Listbox*Font", bigfont)
That changes the font of all Listbox widgets that are part of a ttk Combobox and that are created after calling this.
This does affect all new Comboboxes, but I assume that's what you want. If you want the new font only for this Combobox, you could choose to create this Combobox as the last widget and call self.parent.option_add("*TCombobox*Listbox*Font", bigfont) right before creating this Combobox. Then only the Listbox under this Combobox will have the new font.
If you want all widgets to have the bigger font, you can use
root.option_add("*Font", bigfont)
or you can change the default font as described in this answer.

While working on the same issue as the OP, the problem of the arrow size mentioned in the comments of the accepted answer by Deepworks and fhdrsdg came up. Unfortunately I'm new and can't comment, hence I'm posting this as an answer. There is actually a way to set the arrow size via the Style "arrowsize" option.
style = ttk.Style()
style.configure('W.TCombobox',arrowsize = 60)
cBox = ttk.Combobox(self, style='W.TCombobox')
This allows you to increase the arrow size to match the font size of the rest of the widget.
I found the reference to the "arrowsize" option here:
Tcl8.6.10/Tk8.6.10 Documentation > Tk Commands > ttk_combobox

Related

How do i resize this labelframe in tkinter?

So I tried to make this labelframe wider by using the basic width and width option.
Here's my given minimal code.
from tkinter import *
from tkinter import ttk
app = Tk()
app.resizable(False, False)
mainLayout = ttk.Frame(app, padding=10)
mainLayout.grid()
settings = ttk.Labelframe(mainLayout, text="Settings", padding=10, width=1000)
settings.grid()
ttk.Label(settings, text="Length limit (in seconds)").grid()
ttk.Spinbox(settings, from_=60, to=600, width=4).grid()
app.mainloop()
minimalized preview:
used in application:
i want to get this labelframe little bit bigger and make the inside centered, But i had no knowledge to do so, Any help will apreciated!
It seems like you just want to have a main_frame in the app. For simplicity I've used .pack with the options fill and expand with the constants tkinter.BOTH to stretch the widget in both (x,y) direction and True to consume extra space. (This is one of the reasons why wildcard imports are discouraged, you can be unaware of overwriting something, use import tkinter as tk instead). Same happens with the LabelFrame, you may could delete one of the containers, but that is up to you.
In LabelFrame I have configured the grid and gave the instruction that the column 0 should get the extra space with the priority/weight 1.
In addition, I gave your Spinbox a little bit more width, changed the size of the window and separated the constructor from the geometrymethod.
To get in touch with the geometry management in tkinter, you could play around with the instructions (e.g. comment some out) and see what happens.
from tkinter import *
from tkinter import ttk
app = Tk()
app.geometry('500x500')
app.resizable(False, False)
mainLayout = ttk.Frame(app, padding=10)
mainLayout.pack(fill=BOTH,expand=True)
settings = ttk.Labelframe(mainLayout, text="Settings", padding=10, width=1000)
settings.pack(fill=BOTH,expand=True)
settings.columnconfigure(0,weight=1)
my_label = ttk.Label(settings, text="Length limit (in seconds)")
my_label.grid()
my_spinbox = ttk.Spinbox(settings, from_=60, to=600, width=20)
my_spinbox.grid()
app.mainloop()

Python Tkinter - Option database only partially working

I'm making a GUI with a dark theme and would like to save time by setting the default parameters using an option database but only some of the options are working. Options like "background" and "font" are working correctly but other things like changing the activebackground or selectcolor for a Radiobutton do NOT work. Changing the "insertbackground" on an entry widget also doesn't work.
I'm not sure why some options are working and others are not. If I pass in the same parameters when creating the widget it does work. eg:
myRadio = Radiobutton(frame, selectcolor='#FF0000', **otherKwargs)
I tried this two ways.
import tkinter
from tkinter import Tk, ttk, Frame, Entry, Label, Button, Toplevel, BooleanVar, IntVar, Radiobutton, StringVar, Canvas
mw = Tk()
mw.option_readfile('StyleDatabase.txt')
# code here...
mw.mainloop()
The "StyleDatabase.txt" file contains the following:
*background: #000008
*foreground: grey90
*font: '', 11
*Entry*background: #404050
*Radiobutton*selectcolor: #FF0000 <---- This one doesn't work.
# also tried:
*selectcolor: #FF0000
*Radiobutton.selectcolor: #FF0000 <---- Neither worked
I also tried using the mw.option_add() function, none of the following worked:
mw.option_add('*selectbackground', 'blue')
mw.option_add('*Radiobutton*selectbackground', 'blue')
mw.option_add('*Radiobutton.selectbackground', 'blue')
As far as I know there aren't any other ways to do this.
EDIT: Here's a workable script to demonstrate the issue, Python 3.x
import tkinter
from tkinter import Tk, ttk, Frame, Entry, Label, Button, Toplevel, BooleanVar, IntVar, Radiobutton, StringVar, Canvas
class MainUI:
def __init__(self, master):
self.master = master
Label(self.master, text='Hello').pack(side='top')
Entry(self.master).pack(side='top')
Entry(self.master, insertbackground='red').pack(side='top')
Button(self.master, text='Cyan Button').pack(side='top')
mw = Tk()
mw.option_add('*background', 'blue') # works
mw.option_add('*foreground', 'white') # works
mw.option_add('*Button.foreground', 'cyan') # works
mw.option_add('*insertbackground', 'red') # does not work. Works if i pass the argument in when creating the widget.
mw.option_add('*Entry.insertbackground', 'red') # also does not work
mw.option_add('*Entry*insertbackground', 'red') # also does not work
mainUI = MainUI(mw)
mw.mainloop()
Question: Option database only partially working
You are stuck with the different option names and aliases use by tkinter and the underlying Tcl.
Your option parameter have to be, note the upercase Color:
*Radiobutton*selectColor: #FF0000
You can get the name used by .option_readfile or .option_add from .config:
myRadio = tk.Radiobutton(frame, selectcolor='#FF0000', **otherKwargs)
myRadio.grid()
print('{}'.format(myRadio.config()['selectcolor']))
>>> ('selectcolor', 'selectColor', 'Background', '#ffffff', '#FF0000')
This answer, What are these strange options returned by the method configure?, explains each option of the five values.
The Second name, here 'selectColor', are used by the option database.
Note: Options not shown from <widget instance>.config() can not be set.
Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6

Checkbutton responds to clicks on text

By default, tkinter's Checkbutton widget responds to clicks anywhere in the widget, rather than just in the check box field.
For example, consider the following (Python 2) code:
import Tkinter as tk
main = tk.Tk()
check = tk.Checkbutton(main, text="Click").pack()
main.mainloop()
Running this code results in a small window, with a single check box, accompanied by the word "Click". If you click on the check box, it is toggled.
However, this also happens if you click on the text of the widget, rather than the check box.
Is this preventable? I could make a separate widget to hold the text, but that still results in a small area around the check box that responds to clicks.
Two solutions come to mind:
Do as you suggest and create a separate widget for the checkbutton and for the label.
replace the bindings on the checkbutton with your own, and examine the x/y coordinates of the click and only accept the click if it happens in a small region of the widget.
This program creates a checkbutton and overrides the default event on it by binding a method to the checkbutton. When the button is clicked, the method checks a defined limit to allow the normal operation or to override. OP wanted to make sure that when text of the checkbutton is clicked, no default action is taken. That is essentially what this does.
import tkinter as tk
import tkinter.ttk as ttk
class App(tk.Frame):
def __init__(self, parent, *args, **kwargs):
self.checkvar = IntVar()
check = tk.Checkbutton(parent, text='Click', variable=self.checkvar)
check.bind('<Button-1>', self.checkCheck)
check.pack()
print(dir(check))
def checkCheck(self, event):
# Set limit based on your font and preference
limit = 18
print(event.x, event.y, self.checkvar.get())
if event.x > limit or event.y > limit:
self.checkvar.set(not self.checkvar.get())
else:
print("Normal behavior")
if __name__ == "__main__":
window = tk.Tk()
app = App(window)
window.mainloop()

How to implement a scrollbar when using grid manager on a tkinter window

I have a fairly large size GUI built in tkinter using the grid manager method. I need to add a scrollbar to the entire window and Im having some trouble. Here is a very crude version of a scroll-bar using the grid manager in Tkinter (i dont want to scroll the list box, i want to scroll the entire Tk window).
import Tkinter
from Tkinter import *
Tk = Tkinter.Tk
self=Tk()
listbox = Listbox(self, width = 10, height = 60)
listbox.grid(row =0, column=0)
scrollbar = Scrollbar(self)
scrollbar.grid(sticky=E, row = 0, rowspan = 100, column = 11, ipady = 1000)
mainloop()
Is it possible to fix the Tkinter window size (using grid manager) and add a scrollbar which then allows the user to view additional content? The window is too large and additional content needs to be viewed so the only option i see is a scrollbar. I only see examples using the pack method. As you can probably guess I am new to Tkinter and would appreciate any input.
Thanks to all in advance.
You cannot scroll the entire contents of a root window, a Toplevel window, or a Frame. The solution is to put all of your widgets in a canvas, and then add a scrollbar to the canvas. There are questions on this site that give examples, such as Python Tkinter scrollbar for frame

How do I prepopulate a text field with suggested text in Tkinter?

I'm trying to prepopulate a text field based on the most recent entry. As this is not a Listbox, I don't see how to do it, and I'm not seeing any examples on the web. Thanks.
Update. I've managed to find a partial way of doing this. Still wondering, is it possible to supply suggested text in Tkinter which fades when the text box is clicked?
from Tkinter import *
app = Tk()
app.title("GUI Example")
app.geometry('560x460+200+200')
x = Text(app)
x.insert(END, "Before")
x.pack()
def replace():
x.delete(1.0, END)
x.insert(END, "After")
abutton = Button(app, text="Click me", command=replace)
abutton.pack()
app.mainloop()
Well, I personally don't know of any options to do this (any answers giving one will easily trump this one).
However, you can closely mimic this behavior with a little coding. Namely, you can bind the textbox to a function that will insert/remove the default text for you.
Below is a simple script to demonstrate:
import Tkinter as tk
tk.Tk()
textbox = tk.Text(height=10, width=10)
textbox.insert(tk.END, "Default")
textbox.pack()
# This is for demonstration purposes
tk.Text(height=10, width=10).pack()
def default(event):
current = textbox.get("1.0", tk.END)
if current == "Default\n":
textbox.delete("1.0", tk.END)
elif current == "\n":
textbox.insert("1.0", "Default")
textbox.bind("<FocusIn>", default)
textbox.bind("<FocusOut>", default)
tk.mainloop()
Notice how:
When you click in the top textbox, the default text disappears.
When you click in the bottom textbox, the top one loses focus and the default text reappears.
This behavior will only occur if there is nothing in the top textbox.

Categories

Resources