My widgets are not centered on the MainFrame which uses a grid layout. So I've decided to put them on 3 different frames and add them into the MainFrame. Still, they are not centered. How to make them be on the squares that I've drawn?
from Tkinter import *
class MainFrame:
def __init__(self, master):
self.frame = Frame(master)#, width = 300, height = 250)
self.frame.pack()
self.createFrames()
self.createCheckBoxes()
self.createButtons()
def createButtons(self):
self.printButton = Button(self.frame0, text = "Print msg", command = self.printMsg)
self.printButton.grid()
self.printButton2 = Button(self.frame0, text = "Print msg 2", command = self.printMsg)
self.printButton2.grid()
self.quitButton = Button(self.frame2, text = "QUIT", command = self.frame.quit, fg = "red")
self.quitButton.grid(columnspan = 10)
def createCheckBoxes(self):
self.cb1var = IntVar()
self.cb1 = Checkbutton(self.frame1, text = "Checkbox 1", variable = self.cb1var, command = self.printMsgCb)
self.cb1.grid()
def createFrames(self):
self.frame0 = Frame(self.frame)
self.frame0.grid(row = 0, column = 0)
self.frame0.grid_rowconfigure(0, weight=1)
self.frame0.grid_columnconfigure(0, weight=1)
self.frame1 = Frame(self.frame)
self.frame1.grid(row = 0, column = 10)
self.frame1.grid_rowconfigure(0, weight=1)
self.frame1.grid_columnconfigure(0, weight=1)
self.frame2 = Frame(self.frame)
self.frame2.grid(row = 0, column = 20)
self.frame2.grid_rowconfigure(0, weight=1)
self.frame2.grid_columnconfigure(0, weight=1)
#button commands ----------------------------------
def printMsg(self):
print "Clicou no botao"
def printMsgCb(self):
print "Check box value = " + str(self.cb1var.get())
#--------------------------------------------------
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
frame = MainFrame(root)
root.geometry('1100x600+200+150')
root.mainloop()
First of all, let's lose some of the redundant parts that do nothing for the current code. Remove:
self.frame0.grid_rowconfigure(0, weight=1)
self.frame0.grid_columnconfigure(0, weight=1)
...
self.frame1.grid_rowconfigure(0, weight=1)
self.frame1.grid_columnconfigure(0, weight=1)
...
self.frame2.grid_rowconfigure(0, weight=1)
self.frame2.grid_columnconfigure(0, weight=1)
Above lines are configuring the inner layout of the subframes(self.frame0, self.frame1, self.frame2) which needs no configuration currently.
Then replace:
self.frame1.grid(row = 0, column = 10)
...
self.frame2.grid(row = 0, column = 20)
with:
self.frame1.grid(row = 0, column = 1)
...
self.frame2.grid(row = 0, column = 2)
As you shouldn't be needing that large of a grid currently.
Then replace:
self.frame.pack()
with:
self.frame.pack(fill='x', expand=True)
to bring your self.frame to the vertical center while being expanded horizontally.
Finally uniformly distribute the subframes of self.frame horizontally by configuring the columns they're in, by adding:
self.frame.grid_columnconfigure(0, weight=1, uniform=True)
self.frame.grid_columnconfigure(1, weight=1, uniform=True)
self.frame.grid_columnconfigure(2, weight=1, uniform=True)
anywhere after self.frame is defined.
Entire code with the changes have been made:
from Tkinter import *
class MainFrame:
def __init__(self, master):
self.frame = Frame(master)#, width = 300, height = 250)
self.frame.grid_columnconfigure(0, weight=1, uniform=True)
self.frame.grid_columnconfigure(1, weight=1, uniform=True)
self.frame.grid_columnconfigure(2, weight=1, uniform=True)
self.frame.pack(fill='x', expand=True)
self.createFrames()
self.createCheckBoxes()
self.createButtons()
def createButtons(self):
self.printButton = Button(self.frame0, text = "Print msg", command = self.printMsg)
self.printButton.grid() # add sticky='nsew' optionally
self.printButton2 = Button(self.frame0, text = "Print msg 2", command = self.printMsg)
self.printButton2.grid()
self.quitButton = Button(self.frame2, text = "QUIT", command = self.frame.quit, fg = "red")
self.quitButton.grid(columnspan = 10)
def createCheckBoxes(self):
self.cb1var = IntVar()
self.cb1 = Checkbutton(self.frame1, text = "Checkbox 1", variable = self.cb1var, command = self.printMsgCb)
self.cb1.grid()
def createFrames(self):
self.frame0 = Frame(self.frame)
self.frame0.grid(row = 0, column = 0)
self.frame1 = Frame(self.frame)
self.frame1.grid(row = 0, column = 1)
self.frame2 = Frame(self.frame)
self.frame2.grid(row = 0, column = 2)
#button commands ----------------------------------
def printMsg(self):
print "Clicou no botao"
def printMsgCb(self):
print "Check box value = " + str(self.cb1var.get())
#--------------------------------------------------
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
frame = MainFrame(root)
root.geometry('1100x600+200+150')
root.mainloop()
Related
I'm just learning Python and I don't know how to make this program to display result in label that I want and when I click button again I want to the new result replaces the previous one
I want to last class shows result in label or entry when i click 1st button and when i click it again the new result will replace previous.
This program is not finished yet. I don't want to write all code when i have problem with first function of program. Once I deal with this problem, writing the rest of the code will not be difficult
import tkinter as tk
from tkinter import ttk
class tkinterApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
windowWidth = 300
windowHeight = 200
offsetLeft = int( (self.winfo_screenwidth() - windowWidth) / 2 )
offsetTop = int( (self.winfo_screenheight() - windowHeight) / 2 )
self.geometry('{}x{}+{}+{}'.format(windowWidth, windowHeight, offsetLeft, offsetTop))
self.title('Konwerter systemów liczbowych')
self.minsize(300, 200)
container = tk.Frame(self, relief="ridge", width=300, height=200)
container.pack(expand = False)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for F in (StartPage, Decy, decBin):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Wybierz system do którego należy Twoja liczba.")
label.grid()
button1 = ttk.Button(self, text ="Decymalny",
command = lambda : controller.show_frame(Decy))
button1.grid(padx = 5, pady = 5)
button2 = ttk.Button(self, text ="Binarny",
command = lambda : controller.show_frame(Binar))
button2.grid(padx = 5, pady = 5)
button3 = ttk.Button(self, text ="Oktalny",
command = lambda : controller.show_frame(Oktal))
button3.grid(padx = 5, pady = 5)
button4 = ttk.Button(self, text ="Heksadecymalny",
command = lambda : controller.show_frame(Heksal))
button4.grid(padx = 5, pady = 5)
class Decy(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Wybierz system na jaki chcesz przekowertować")
label.grid()
label = ttk.Label(self, text ="swoją liczbę.")
label.grid()
button1 = ttk.Button(self, text ="Binarny",
command = lambda : controller.show_frame(decBin))
button1.grid(padx = 5, pady = 5)
button2 = ttk.Button(self, text ="Oktalny",
command = lambda : controller.show_frame(decOkt))
button2.grid(padx = 5, pady = 5)
button2 = ttk.Button(self, text ="Heksadecymalny",
command = lambda : controller.show_frame(decHex))
button2.grid(padx = 5, pady = 5)
button2 = ttk.Button(self, text ="Powrót",
command = lambda : controller.show_frame(StartPage))
button2.grid(padx = 5, pady = 5)
class decBin(tk.Frame):
def clearText(self):
self.entry1.confing(text='')
def oblicz():
dec = wpis.get()
dec = int(dec)
i = 0
bnum = []
while dec!=0:
rem = dec%2
bnum.insert(i, rem)
i = i+1
dec = int(dec/2)
i = i-1
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Wprowadź liczbę i zatwierdź.")
label.grid()
wpis = ttk.Entry(self)
wpis.grid()
button1 = ttk.Button(self, text="Konwertuj", command = oblicz)
button1.grid(padx = 10, pady = 10)
button2 = ttk.Button(self, text ="Powrót", command = lambda : controller.show_frame(StartPage))
button2.grid(padx = 10, pady = 10)
app = tkinterApp()
app.mainloop()
If you want to update an existing Label widget, declare a tk.StringVar() to store the label text, then bind that to your Label's textvariable attribute. Then your Label will automatically update whenever you set() the StringVar.
label_var = tk.StringVar(self, 'Default Value') # both of these args are optional
label = ttk.Label(self, textvariable=label_var) # instantiate Label and bind the var
To update the label:
label_var.set('New String Value')
When you grid()/pack()/place() your Label it will start with the text you gave the StringVar, if any.
i'm french so sorry for the translation and i'm beginner on python.
I have a items display problem in canvas. Refering to the following code, the script doesn't work properly if i want generate a high number of items into my canvas.
All items are not displayed properly
2)the script is freezing a little bit
I dont no why...Someone can help me please?
from tkinter import *
from tkinter import ttk
import tkinter as tk
class Main_frame(Frame):
# Init
def __init__(self, fenetre_principale=None):
tk.Frame.__init__(self, fenetre_principale)
self.grid(sticky = "news")
self.main_frame = tk.Frame(self, bg = "blue")
self.main_frame.grid(sticky = "news")
self.frame_canvas = tk.Frame(self.main_frame, bg = "yellow")
self.frame_canvas.grid(row = 2, column = 0, pady = 5, sticky="nw")
self.frame_canvas.grid_rowconfigure(0, weight=1)
self.frame_canvas.grid_columnconfigure(0, weight=1)
self.frame_canvas.grid_propagate(False)
self.canvas = tk.Canvas(self.frame_canvas, bg = "yellow")
self.canvas.grid(row = 0, column = 0, sticky='news')
self.vbar = tk.Scrollbar(self.frame_canvas, orient = "vertical", command = self.canvas.yview)
self.vbar.grid(row = 0, column = 1, sticky = "ns")
self.canvas.configure(yscrollcommand= self.vbar.set)
self.frame_buttons = tk.Frame(self.canvas, bg = "grey")
self.canvas.create_window((0, 0), window=self.frame_buttons, anchor="nw")
self.ajout()
def ajout(self):
self.bu_aj = tk.Button(self.main_frame, text = "Ajout", command = self.update_).grid(row = 0, column= 0, pady = 5, sticky="nw")
def update_(self):
for k in range(2000):
self.bu = tk.Button(self.frame_buttons, text = f"Test{k}")
self.bu.grid(row = k, column= 0, sticky="news")
self.frame_buttons.update_idletasks()
first5columns_width = sum([self.bu.winfo_width() for j in range(0, 15)])
first5rows_height = sum([self.bu.winfo_height() for i in range(0, 5)])
self.frame_canvas.config(width=first5columns_width + self.vbar.winfo_width(),height=first5rows_height)
self.canvas.config(scrollregion=self.canvas.bbox("all"))
print("ok")
if __name__ == "__main__":
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.title("Title")
interface = Main_frame(fenetre_principale=root)
interface.mainloop()
I cannot get x and y scrollbars to work in Tkinter with Python, although I have followed multiple examples:
How to add 2 scrollbars with tkinter in python 3.4
Adding a scrollbar to a group of widgets in tkinter
How to make a proper double scrollbar frame in tkinter
Vertical and Horizontal Scrollbars on Tkinter Widget
Scrolling a Canvas widget horizontally and vertically
The scrollbars appear, but do not activate when the window is smaller than the frame. How can I get this to work (see image below)?
Below is the minimal code that is producing my problem (Python 3.7)
import tkinter as tk
from tkinter import ttk
big_font = ("Arial", 50)
class DoubleScrollbarFrame(ttk.Frame):
def __init__(self,
parent,
*args,
**kwargs):
self.parent = parent
super().__init__(self.parent,
*args,
**kwargs)
#Set widgets to fill main window such that they are
#all the same size
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.create_widgets()
self.position_widgets()
def create_widgets(self):
self.canvas = tk.Canvas(self)
self.frame = ttk.Frame(self.canvas)
self.scroll_x = ttk.Scrollbar(self,
orient = tk.HORIZONTAL,
command = self.canvas.xview)
self.scroll_y = ttk.Scrollbar(self,
orient = tk.VERTICAL,
command = self.canvas.yview)
self.canvas.config(xscrollcommand = self.scroll_x.set,
yscrollcommand = self.scroll_y.set)
self.canvas.create_window((0,0),
window = self.frame,
anchor = 'nw')
self.frame.bind('<Configure>',
self.set_scrollregion)
self.sizegrip = ttk.Sizegrip(self)
#Test
self.test1 = tk.Label(self.frame,
text = 'Test 1',
font = big_font)
self.test2 = tk.Label(self.frame,
text = 'Test 2',
font = big_font)
self.test3 = tk.Label(self.frame,
text = 'Test 3',
font = big_font)
def position_widgets(self,
**kwargs):
self.test1.grid(row = 0,
column = 0,
sticky = 'w')
self.test2.grid(row = 1,
column = 0,
sticky = 'w')
self.test3.grid(row = 2,
column = 0,
sticky = 'w')
self.scroll_x.grid(row = 1,
column = 0,
sticky = 'ew')
self.scroll_y.grid(row = 0,
column = 1,
sticky = 'ns')
self.canvas.grid(row = 0,
column = 0,
sticky = 'nsew')
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
self.sizegrip.grid(row = 1,
column = 1,
sticky = 'se')
def set_scrollregion(self,
event):
print('Frame Dimensions: {} x {}'.format(self.frame.winfo_width(),
self.frame.winfo_height()))
print('Canvas Dimensions: {} x {}'.format(self.canvas.winfo_width(),
self.canvas.winfo_height()))
self.canvas.configure(scrollregion = self.canvas.bbox('all'))
class MainApp(tk.Tk):
def __init__(self,
*args,
**kwargs):
super().__init__(*args,
**kwargs)
#Set widgets to fill main window such that they are
#all the same size
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.create_widgets()
self.position_widgets()
def create_widgets(self):
self.frame = DoubleScrollbarFrame(self)
def position_widgets(self):
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
def exit(self):
self.destroy()
if __name__ == '__main__':
#Create GUI
root = MainApp()
#Run program
root.mainloop()
The problem is in these lines of code inside DoubleScrollbarFrame.position_widgets:
self.frame.grid(row = 0,
column = 0,
sticky = 'nsew')
This removes control of the widget from the canvas and gives control to grid. It is no longer a canvas object, so self.canvas.bbox("all") is returning (0, 0, 1, 1). If the scrollregion is set incorrectly, the scrollbars don't know how much to scroll.
The solution is simple: don't call grid on self.frame.
i'm trying to make this simple gui using grid layout where i have in one row a label an entry and a button, but for some reason the first button always takes the rowspan equal to the number of rows in previous column, even if i try to force it to have rowspan 1 it has no effect which makes me really confused.
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.grid()
#LABELS
self.l1 = tk.Label(self, text = "Source")
self.l1.grid(column = 0, row = 0, sticky = "E")
self.l2 = tk.Label(self, text = "Text files destination")
self.l2.grid(column = 0, row = 1, sticky = "E")
self.l3 = tk.Label(self, text = "Image files destination")
self.l3.grid(column = 0, row = 2, sticky = "E")
#ENTRIES
self.e1 = tk.Entry(self)
self.e1.grid(column = 1, row = 0)
self.e2 = tk.Entry(self)
self.e2.grid(column = 1, row = 1)
self.e3 = tk.Entry(self)
self.e3.grid(column = 1, row = 2)
#BUTTONS
self.b3 = tk.Button(text = "Select dir", command = self.cb2)
self.b3.grid(column = 2, row = 0)
self.b4 = tk.Button(text = "Select dir", command = self.cb2)
self.b4.grid(column = 2, row = 1)
self.b5 = tk.Button(text = "Select dir", command = self.cb2)
self.b5.grid(column = 2, row = 2)
if __name__ == "__main__":
root = tk.Tk()
app = MainApplication(root)
root.mainloop()
output:
http://i.imgur.com/AdWkHwi.png
You don't specify a parent for the buttons, so their parent is the root window. The labels and entries, on the other hand, have their parent attribute set to the frame. What happens is that in the root, the frame is in row zero, and the first button is in row zero, and the height of the row is determined by the height of the frame.
The solution is to make the parent of the buttons be the frame.
self.b3 = tk.Button(self, ...)
self.b4 = tk.Button(self, ...)
self.b5 = tk.Button(self, ...)
I'm trying to make a Tkinter window class that contains a canvas with a scrollbar based on the tkinter Toplevel class. When I run my code I don't receive any errors but the scrollbar in the window is disabled. The Frame or canvas that has the information wont stretch with the window when I stretch it manually after the program is running. Here is the bugged code:
class new_window(Toplevel):
def __init__(self,master):
Toplevel.__init__(self,master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
s = Scrollbar(self, orient = VERTICAL)
s.grid(row = 0, column = 1, sticky = NS)
self.can = Canvas(self, yscrollcommand=s.set)
self.can.grid(row = 0, column = 0, sticky = N+S+E+W)
self.win = Frame(self.can)
self.can.create_window(0,0, window = self.win, anchor = NW)
s.config(command = self.can.yview)
size = (self.win.winfo_reqwidth(), self.win.winfo_reqheight())
self.can.config(scrollregion="0 0 %s %s" % size)
self.win.update_idletasks()
self.ca.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
def create(self):
for i in range (100):
i = Label(self.win, text = str(i))
i.grid()
root = Tk()
win = new_window(root)
win.create()
root.mainloop()
It was working fine before I decided to implement classes:
from Tkinter import *
root = Tk()
window = Toplevel()
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)
s = Scrollbar(window, orient = VERTICAL)
s.grid(row = 6, column = 1, sticky = NS)
can = Canvas(window, width = 1600, height = 700, yscrollcommand=s.set)
can.grid(row = 6, column = 0, sticky = NSEW)
win = Frame(can)
can.create_window(0,0, window = win, anchor = NW)
s.config(command = can.yview)
for i in range(100):
lbl = Label(win, text = str(i))
lbl.grid()
win.update_idletasks()
can.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
root.mainloop()
Im not sure where I went wrong in the transition, any help would be greatly appreciated.
I think the issue is coming from here:
self.win.update_idletasks()
self.ca.configure(scrollregion = (1,1,win.winfo_width(),win.winfo_height()))
This is inside the initialization function, when it should be updating after the create function is called. There's still probably a more efficient way to structure this, but this should work in the meantime:
from Tkinter import *
class new_window(Toplevel):
def __init__(self,master):
Toplevel.__init__(self,master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
s = Scrollbar(self, orient = VERTICAL)
s.grid(row = 0, column = 1, sticky = NS)
self.can = Canvas(self, yscrollcommand=s.set)
self.can.grid(row = 0, column = 0, sticky = N+S+E+W)
self.win = Frame(self.can)
self.can.create_window(0,0, window = self.win, anchor = NW)
s.config(command = self.can.yview)
size = (self.win.winfo_reqwidth(), self.win.winfo_reqheight())
self.can.config(scrollregion="0 0 %s %s" % size)
def create(self):
for i in range (100):
i = Label(self.win, text = str(i))
i.grid()
self.win.update_idletasks()
self.can.configure(scrollregion = (1,1,self.win.winfo_width(),self.win.winfo_height()))
root = Tk()
win = new_window(root)
win.create()
root.mainloop()