Tkinter widgets placed incorrectly - python

I would like to create a frame with
combobox
then two labels
and then another combobox.
Instead I get a frame with
two comboboxes
and then two labels
Tkinter widgets seem to be grouped by the widget type. Please advise how to place the widgets correctly. Thanks!
I am using Python 3.4 on Win 7 64 bit and Tcl/Tk version 8.6.
import tkinter as tk
from tkinter import ttk
class App(tk.Frame):
def __init__(self,master=None):
super().__init__(master)
self.grid()
self.combo1=ttk.Combobox(self)
self.combo1["values"]=["1","2"]
self.combo1.grid(row=1)
self.lbl1=ttk.Label(text="AAA")
self.lbl1.grid(row=2)
self.lbl3=ttk.Label(text="BBB")
self.lbl3.grid(row=3)
self.combo2=ttk.Combobox(self)
self.combo2["values"]=["3","4"]
self.combo2.grid(row=4)
root=tk.Tk()
x=App()

This happened because you didn't set the parent of your Labels to self (the frame), try changing your labels to this:
self.lbl1=ttk.Label(self, text="AAA")
...
self.lbl3=ttk.Label(self, text="BBB")
Previously they had used the default parent, which is root, so they appeared below your frame.

Related

Tkinter - How can I use correctly the "ttk.style()" statement when I have different kind of classes?

In my real code I have a main window where the user can choose to open other kind of windows. In the main one, I defined the ttk style using the ttk.style() statement. It works, but if I define the same style in the other classes dedicated for the other windows, the ttk.style() doesn't work anymore. Why? Below is an example:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
self.parent=Tk()
self.parent.geometry("400x400")
self.parent.title(self.main_name)
self.parent.configure(background="#f0f0f0")
style=ttk.Style()
style.configure("TButton", background="red", padding=0)
MyButton=ttk.Button(self.parent, text="open a new window", command=self.Open)
MyButton.pack()
self.parent.mainloop()
def Open(self):
obj=NewWindow()
class NewWindow():
def __init__(self):
self.parent=Tk()
self.parent.geometry("400x400")
self.parent.configure(background="#f0f0f0")
style=ttk.Style()
style.configure("TButton", background="red", padding=0)
MyButton=ttk.Button(self.parent, text="This button has not a custom style.. why?")
MyButton.pack()
if __name__=="__main__":
app=MainWindow()
Why the window from the NewWindow class doesn't use the custom ttk style like the other one from the MainWindow class?
Then I want to write just one time the ttk instructions, because in my real code, all classes use the same style. What is the best way to do it?
Below is a screenshot about my example:
Every instance of Tk is a separate environment, and cannot share data with other instances of Tk. If you want multiple windows to be able to share information with the first window, you must create instances of Toplevel rather than Tk.
The reason your second window doesn't accept the new styling is that the Style object you created belongs to the original root window. If you want it to affect the new root window you must explicitly tell it so by specifying the master attribute.
style=ttk.Style(master=self.parent)

Python Tkinter ttk calendar

I am trying to create a drop down calendar for a date entry.
Below is a portion of my code:
The drop down portion of it dosen't work and I can't seem to find the syntax for DateEntry() of ttk calendar anywhere to include the calendar widget option!
#creating the frame
from tkinter import *
from tkcalendar import *
root = Tk()
f1=Frame(root,width=1500,height=100,relief=SUNKEN,bd=4,bg='light steel blue')
f1.pack(side=TOP)
f2=Frame(root,width=1500,height=550,relief=SUNKEN,bd=4,bg='white')
f2.pack()
f3=Frame(root,width=1600,height=100,relief=SUNKEN,bd=4,bg='white')
f3.pack(side=BOTTOM)
#Creating the date column
l4=Label(f2,text='DATE',font=('tahoma',20,'bold'),fg='black',anchor='w')
l4.grid(row=0,column=3)
cal=DateEntry(f2,dateformat=3,width=12, background='darkblue',
foreground='white', borderwidth=4,Calendar =2018)
cal.grid(row=1,column=3,sticky='nsew')
I want it to look like this:
UPDATE: I have fixed the issue and published a new version of tkcalendar.
EDIT: the problem is that in Windows, the drop-down does not open when the downarrow button is clicked. It seems that it comes from the default ttk theme for Windows because it works with other themes. So the workaround is to switch theme and use 'clam' for instance ('alt' should work as well). Meanwhile, I will look into it and see if I can fix the DateEntry for the other themes and release a new version (https://github.com/j4321/tkcalendar/issues/3).
I am not sure what you want to achieve exactly with the DateEntry, but if your goal is to make it look like the one in the picture, it can be done the following way:
import tkinter as tk
from tkinter import ttk
from tkcalendar import DateEntry
from datetime import date
root = tk.Tk()
# change ttk theme to 'clam' to fix issue with downarrow button
style = ttk.Style(root)
style.theme_use('clam')
class MyDateEntry(DateEntry):
def __init__(self, master=None, **kw):
DateEntry.__init__(self, master=None, **kw)
# add black border around drop-down calendar
self._top_cal.configure(bg='black', bd=1)
# add label displaying today's date below
tk.Label(self._top_cal, bg='gray90', anchor='w',
text='Today: %s' % date.today().strftime('%x')).pack(fill='x')
# create the entry and configure the calendar colors
de = MyDateEntry(root, year=2016, month=9, day=6,
selectbackground='gray80',
selectforeground='black',
normalbackground='white',
normalforeground='black',
background='gray90',
foreground='black',
bordercolor='gray90',
othermonthforeground='gray50',
othermonthbackground='white',
othermonthweforeground='gray50',
othermonthwebackground='white',
weekendbackground='white',
weekendforeground='black',
headersbackground='white',
headersforeground='gray70')
de.pack()
root.mainloop()
I created a class inheriting from DateEntry to add the label with today's date below the calendar and to create a black border around the drop-down (self._top_cal is the Toplevel containing the calendar).
Then, I created an instance of MyDateEntry and with all calendar options needed to make it look like the picture. In addition, I used the year, month, day options to define the initial date inside the entry.
Here is the result:

Why is my tkinter button not displaying, have I installed everything in the module if not how can I install it?

#snakes and ladder
from tkinter import * #pygame is the module that has collections of functions that is used to create a window import everything from tkinter
import time
class window(Frame): #Frame comes from tkinter is what you think as a window
def __init__(self, master = None):#The master widget defines the settings upon initialisation
Frame.__init__(self, master) #This is called the frame class that has been built in python
self.master = master
def __init__window(self): #creation of the init window
self.master.title("Reagan Kambayi") #It changes the title of the title of our widget
self.pack(fill=BOTH, expand=1)#The pack function will pack this in our frame
#placing the button
stop = Button(self, master, message= "Stop")
#intialising the button that will start the stopwatch
stop.place(x=0, y=0)
screen = Tk() #It must be written with capitalised T because there will be an error and it holds the components of the tkinter module
screen.geometry("700x500")
app = window(screen) #The app variable is assigned to the window creation which has the tkinter module
screen.mainloop()
Ok, here we go.
from tkinter import * #pygame is the module that has collections of functions that is used to create a window import everything from tkinter
Pygame has nothing to do with tkinter and you're not importing pygame here, you're importing tkinter.
class window(Frame): #Frame comes from tkinter is what you think as a window
No, it isn't. A Frame widget is just that, a frame inside a window. It doesn't draw a window in and of itself. The parameter Frame in your example isn't even a Frame widget at all, it's value is Tk() which is the function called to draw the first window in tkinter.
def __init__(self, master = None):#The master widget defines the settings upon initialisation
I'm actually at a loss for what you're attempting to do here. master should equal Frame which equals screen which equals Tk() but if I'm correct you're overriding that and telling it to equal None?
Frame.__init__(self, master) #This is called the frame class that has been built in python
I don't think you're doing what you think you're doing here. This answer explains it better than I could.
def __init__window(self): #creation of the init window
If I'm reading your program correctly then window.__init__window() is never called, so none of this function ever actually happens.
self.pack(fill=BOTH, expand=1)#The pack function will pack this in our frame
You're attempting to call .pack() on self which is calling .pack() on Frame. Typically we wouldn't assign a value to self in this way (although this is valid), read this to find out what self should be used for.
#placing the button
stop = Button(self, master, message= "Stop")
This isn't placing the Button widget, this is assigning the Button widget to a variable. Also, Button widgets are declared as Button(parent, *attributes) and there is no message attribute built in. Meaning what you meant to call was Button(self.master, text="Stop").
#intialising the button that will start the stopwatch
stop.place(x=0, y=0)
This is where you're placing the button, but the function that contains this is never called, so it never happens.
app = window(screen) #The app variable is assigned to the window creation which has the tkinter module
What you're actually doing here is calling the class window, all this does in your current program is call window.__init__(), which in itself does essentially nothing.
This is meant with no offence but I think you're lacking a very basic understanding of tkinter and possibly even Pythonic OOP.
I believe what you're trying to do in your program is the below:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.root.title("Reagan Kambayi")
self.stop = Button(self.root, text="Stop")
self.stop.place(x=0, y=0)
root = Tk()
App(root)
root.mainloop()

A Tkinter Frame is instantiated with super(). Why can I not make a Label widget its child?

This concerns Python and Tkinter.
I wish to have a Label widget display the word "Meow".
The Label widget should be the child of a Frame in a Tk window.
This seems simple, yet the code below does not work - nothing appears:
import tkinter as tk
class Options(tk.Frame):
def __init__(self, gui_parent):
super().__init__()
tk.Label(self, text="Meow").pack()
class Gui(tk.Tk):
def __init__(self):
super().__init__()
Options(self)
gui = Gui()
gui.mainloop()
I then experimented: if I change the Label widget to tk.Label(gui_parent, text="Meow").pack(), the content of the window then appears. (However this is not the 'correct' behaviour, since I wish for the Label widget to be a direct child of the Frame widget, not of the Tk parent window.)
To my understanding, super().__init__() should have instantiated a Frame. The Label widget should then be able to access the Frame via self. This is not so.
Where have I gone wrong?
You do not pack your Options widget. Try with:
Options(self).pack()
Also, I would explicitly state that Options is the child of Gui, so you should pass gui_parent to the __init__ function of Options objects:
def __init__(self, gui_parent):
super().__init__(gui_parent)
tk.Label(self, text="Meow").pack()

Combobox fontsize in tkinter

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

Categories

Resources