I want to set my buttons in my Tk window close to each other, but there is too much space between them. They actually have to sit very close to each other, but i can't change their position.
Code:
from tkinter import *
from tkinter import ttk
def Page():
Profile = Tk()
TreeSearchbar = Text(Profile, width=30, height=1, font="Arial 15")
TreeSearchbar.grid(row=0, column=0, sticky=W, pady=5, columnspan=2)
TreeSearchButton = ttk.Button(Profile, text="Search").grid(row=0, column=1, sticky=W, columnspan=2)
Tree = ttk.Treeview(Profile, height=20)
Tree["columns"] = ("value1", "value2", "value3", "value4", "value5", "value6")
Tree.column("#0", width=170)
Tree.column("#1", width=180)
Tree.column("#2", width=0)
Tree.heading("#0", text="1")
Tree.heading("#1", text="2")
Tree.grid(row=1, column=0, sticky="nw", columnspan=2)
Button1 = ttk.Button(Profile, text="Delete").grid(row=2, column=0, sticky=W, pady=12, padx=(20, 0))
Button2 = ttk.Button(Profile, text="Update").grid(row=2, column=1, sticky=W)
Button3 = ttk.Button(Profile, text="Edit").grid(row=2, column=2, sticky=W)
Profile.mainloop()
Page()
Using frames inside your grid cells you will be able to pack controls. That will give you more flexibility in the layout, like this:
from tkinter import *
from tkinter import ttk
def Page():
Profile = Tk()
TreeSearchbar = Text(Profile, width=30, height=1, font="Arial 15")
TreeSearchbar.grid(row=0, column=0, sticky=W, pady=5, columnspan=2)
TreeSearchButton = ttk.Button(Profile, text="Search").grid(row=0, column=1, sticky=W, columnspan=2)
Tree = ttk.Treeview(Profile, height=20)
Tree["columns"] = ("value1", "value2", "value3", "value4", "value5", "value6")
Tree.column("#0", width=170)
Tree.column("#1", width=180)
Tree.column("#2", width=0)
Tree.heading("#0", text="1")
Tree.heading("#1", text="2")
Tree.grid(row=1, column=0, sticky="nw", columnspan=2)
ButtonFrame = ttk.Frame(Profile)
Button1 = ttk.Button(ButtonFrame,
text="Delete").pack(side=LEFT, padx=5, pady=5)
Button2 = ttk.Button(ButtonFrame,
text="Update").pack(side=LEFT, padx=5, pady=5)
Button3 = ttk.Button(ButtonFrame,
text="Edit").pack(side=LEFT, padx=5, pady=5)
ButtonFrame.grid(row=2, column=0)
Profile.mainloop()
Page()
You should grid your areas in the UI and probably apply this principle in each of them, using either grid again, or packer, inside them (although you can use placer it is usually not recommended, to be able to adjust to window size...)
Related
I am working on a YouTube downloader project that takes a link and then puts the information about the video quality and sound quality of the link in the Combobox.
But when I try to put audio and video information in the Combobox, it gives this exception:
This is my code :
import tkinter
import tkinter.ttk
from tkinter import *
from tkinter import filedialog
from os import path
import pafy
from pafy import *
class Youtube():
def __init__(self):
self.label()
self.entry()
self.button()
self.combobox()
self.data=[]
def label(self):
Label(window, text='URL', font='bold').grid(row=0, column=0, padx=100)
Label(window, text='Destination', font='bold').grid(row=2, column=0, padx=100)
Label(window, text='File Name', font='bold').grid(row=4, column=0, padx=100)
Label(window, text='Video Quality', font='bold').grid(row=6, column=0, pady=20)
Label(window, text='Audio Quality', font='bold').grid(row=7, column=0, pady=5)
Label(window, text='Download Type', font='bold').grid(row=8, column=0, pady=15)
Label(window, text='Combine AV', font='bold').grid(row=8, column=1)
def entry(self):
global een
global en
en=Entry(window, width=35, borderwidth=10)
en.grid(row=1, column=0, padx=100, pady=5)
een=Entry(window, width=35, borderwidth=10)
een.grid(row=3, column=0, padx=100, pady=5)
Entry(window, width=35, borderwidth=10).grid(row=5, column=0, padx=100, pady=5)
def button(self):
Button(window, text='i', height=1, width=3, command=self.information).grid(row=1, column=1)
Button(window, text='d', height=1, width=3, command=self.destination).grid(row=3, column=1)
Button(window, text='Download', font='bold').grid(row=12, column=0, padx=150, pady=10, columnspan=3)
def combobox(self):
tkinter.ttk.Combobox(window, width=15).grid(row=6, column=1)
tkinter.ttk.Combobox(window, width=15).grid(row=7, column=1, pady=5)
tkinter.ttk.Combobox(window, values=['Audio only', 'Vido only', 'Audio and vido'],
width=15).grid(row=9, column=0)
tkinter.ttk.Combobox(window, values=['Yes', 'No'], width=15).grid(row=9, column=1, pady=20)
tkinter.ttk.Progressbar(window, orient=HORIZONTAL, length=300,
mode='determinate').grid(row=11, column=0, padx=200, pady=10, columnspan=3)
def destination(self):
path = str(filedialog.askdirectory())
een.insert(tkinter.END, path)
def information(self):
global link
link = en.get()
self.video()
self.audio()
def video(self):
video_quality_list = []
self.data = pafy.new(link)
video_streams = self.data.videostreams
for video_quality in video_streams:
video_quality_list.append(video_quality)
tkinter.ttk.Combobox(window, values=video_quality_list, width=15).grid(row=6, column=1, pady=5)
def audio(self):
audio_quality_list = []
self.data = pafy.new(link)
audio_streams = self.data.audiostreams
for audio_quality in audio_streams:
audio_quality_list.append(audio_quality)
tkinter.ttk.Combobox(window, values=audio_quality_list, width=15).grid(row=7, column=1)
window = Tk()
mywin = Youtube()
window.title('Youtube Downloader')
window.geometry("700x600+10+10")
window.mainloop()
I would be very grateful if anyone could help me to fix it.
Thanks!
I'm trying to adjust the buttons, but somehow even after changing the width, it won't change the size. This is my code:
if __name__ == '__main__':
# create application window
app = Tk()
# title
app.title("Music Players")
# geometry
app.geometry('500x300')
# background color
app.configure(bg='orange')
equation = StringVar()
window_1 = Label(app, textvariable=equation)
window_1.grid(columnspan=3, ipadx=100, ipady=10)
equation.set('music player')
window_2 = Entry(app, width=30)
window_2.grid(columnspan=5, ipadx=100, ipady=10)
# Create buttons and other accessories
button1 = Button(app, text='PLAY', fg='yellow', bg='purple',
command=lambda: press('PLAY'), height=2, width=1)
button1.grid(row=2, column=0, sticky="NSEW")
button2 = Button(app, text='STOP', fg='yellow', bg='purple',
command=lambda: press('STOP'), height=2, width=2)
button2.grid(row=2, column=1, sticky="NSEW")
button3 = Button(app, text='NEXT', fg='yellow', bg='purple',
command=lambda: press('NEXT'), height=2, width=2)
button3.grid(row=2, column=2, sticky="NSEW")
button4 = Button(app, text='PREVIOUS', fg='yellow', bg='purple',
command=lambda: press('PREVIOUS'), height=2, width=2)
button4.grid(row=2, column=3, sticky="NSEW")
I'm assuming it is because of sticky="NSEW", because when I remove it, the buttons change the size, but there is big spaces between the buttons and also, very spaced out, even though columns=0 and columns=1.
How can I change the size of buttons without getting rid of sticky? Or, without sticky, but having the buttons next to each other?
My expected output will be like this:
Thank you in advance!
I want to have a GUI with 2 buttons. Once clicked on either button, I want to see a new GUI which has a button to go back to the main GUI with the two buttons again.
This is what I've got right now but the 'Go back' button doesn't do anything. How can I go back to my first page using tkinter?
from tkinter import *
root = Tk()
root.title('Frames')
root.geometry('500x250+300+300')
# Position frame
frame = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame.pack(padx=10, pady=50)
# What do the buttons do
def bad():
frame.grid_forget()
b.grid_forget()
b2.grid_forget()
slechtekeuze = Label(frame, text='Bad choice')
slechtekeuze.grid(row=0, column=0, columnspan=2)
# Option to got back
homepage = Button(frame, text='Go back', command=back)
homepage.grid(row=1, column=0, columnspan=2, pady=10)
def good():
frame.grid_forget()
b.grid_forget()
b2.grid_forget()
slechtekeuze = Label(frame, text='Good choice')
slechtekeuze.grid(row=0, column=0, columnspan=2)
# Option to go back
homepage = Button(frame, text='Terug', command=back)
homepage.grid(row=1, column=0, columnspan=2, pady=10)
def back():
frame.grid_forget()
frame1 = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame1.pack(padx=10, pady=50)
b = Button(frame1, text="Don't click!!!", fg='red', command=bad)
b2 = Button(frame1, text='Click!!!', fg='green', command=good)
b.grid(row=0, column=0, padx=3)
b2.grid(row=0, column=1, padx=3)
# Create the buttons and put them in the frame
b = Button(frame, text="Don't click!!!", fg='red', command=bad)
b2 = Button(frame, text='Click!!!', fg='green', command=good)
b.grid(row=0, column=0, padx=3)
b2.grid(row=0, column=1, padx=3)
root.mainloop()
It does work, expand your screen a bit. The frames get added below.
I've edited it a bit as much in your style as possible:
from tkinter import *
root = Tk()
root.title('Frames')
root.geometry('500x250+300+300')
# Position frame
frame = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame.pack(padx=10, pady=50)
# What do the buttons do
def bad(frame):
frame.destroy()
frame = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame.pack(padx=10, pady=50)
slechtekeuze = Label(frame, text='Bad choice')
slechtekeuze.grid(row=0, column=0, columnspan=2)
# Option to got back
homepage = Button(frame, text='Go back', command=lambda:back(frame))
homepage.grid(row=1, column=0, columnspan=2, pady=10)
def good(frame):
frame.destroy()
frame = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame.pack(padx=10, pady=50)
slechtekeuze = Label(frame, text='Good choice')
slechtekeuze.grid(row=0, column=0, columnspan=2)
# Option to go back
homepage = Button(frame, text='Terug', command=lambda:back(frame))
homepage.grid(row=1, column=0, columnspan=2, pady=10)
def back(frame):
frame.destroy()
frame = LabelFrame(root, text='Such a dilemma', padx=25, pady=25)
frame.pack(padx=10, pady=50)
b = Button(frame, text="Don't click!!!", fg='red', command=lambda:bad(frame))
b2 = Button(frame, text='Click!!!', fg='green', command=lambda:good(frame))
b.grid(row=0, column=0, padx=3)
b2.grid(row=0, column=1, padx=3)
# Create the buttons and put them in the frame
b = Button(frame, text="Don't click!!!", fg='red', command=lambda:bad(frame))
b2 = Button(frame, text='Click!!!', fg='green', command=lambda:good(frame))
b.grid(row=0, column=0, padx=3)
b2.grid(row=0, column=1, padx=3)
root.mainloop()
I am little bit comfused with grid system in tkinter Python. Can anyone show how to make it in right way?! ListBox and Label items positions are not in the places where I expexted to see them.
CODE:
self.third_label = Label(self, text="TEXT")
self.third_label.grid(row=2, column=0, columnspan=4, padx=10, pady=10, sticky=W)
self.fourth_label = Label(self, text="LONG TEXT")
self.fourth_label.grid(row=2, column=1, columnspan=4, padx=10, pady=10, sticky=W)
self.fifth_label = Label(self, text="SOME TEXT")
self.fifth_label.grid(row=2, column=2, columnspan=6, padx=10, pady=10, sticky=W)
self.sixth_label = Label(self, text="BIG TEXT")
self.sixth_label.grid(row=2, column=3, columnspan=4, padx=10, pady=10, sticky=W)
self.first_listbox = Listbox(self, width=40, selectmode=EXTENDED)
self.first_listbox.grid(row=3, column=0, columnspan=4, padx=10, pady=10, sticky=W)
self.second_listbox = Listbox(self, width=40, selectmode=EXTENDED)
self.second_listbox.grid(row=3, column=2, columnspan=4, padx=10, pady=10, sticky=W)
self.third_listbox = Listbox(self, width=40, selectmode=EXTENDED)
self.third_listbox.grid(row=3, column=4, columnspan=4, padx=10, pady=10, sticky=W)
self.fourth_listbox = Listbox(self, width=40, selectmode=EXTENDED)
self.fourth_listbox.grid(row=3, column=6, columnspan=4, padx=10, pady=10, sticky=W)
What I have right now:
Just Example:
The grid system works fine. The problem is your columnspans, which don't make much sense. You're gridding the widgets into certain column positions then giving them a columnspan that is beyond the range of where the next widget is to be gridded so on and so forth.
Small example:
import string
import tkinter as tk
root = tk.Tk()
for i in range(3):
tk.Label(root, text=string.ascii_letters).grid(row=0, column=i)
tk.Listbox(root, width=40).grid(row=1, column=i)
root.mainloop()
Edit from comments (for listbox size):
To get the number of lines in a listbox you can use the .size() method.
Image:
This is the class I'm calling and the function from a different file
class CalcFunc:
def clearScreen(self):
self.log("CLEAR (CE)")
ent.delete(0, END)
This is the Entry Box
ent = Entry(root, textvariable=clc.getBtn, justify=RIGHT, font=10, relief=RIDGE, bd=2, width=15)
ent.grid(row=0, columnspan=3, pady=10)
This is the button I'm clicking to clear the Entry Box
buttonCC = Button(root, text="CLEAR (CE)", height=1, width=20, bg='orange', command=clc.clearScreen)
I'm not sure what the syntax is to be able to to clear an Entry widget from a class basically. That code worked when I had it in the same file but my project requires it to be in a separate file. It's a class project for a calculator and the "clear" button clears the Entry widget. I can post my entire code if that helps. Thank you.
----EDIT----
My Class
import time
class CalcFunc:
def log(self, val):
myFile = open(r".\log.dat", "a")
myFile.write("%s\n" % val)
myFile.close()
def onScreen(self, iVal):
self.log(iVal)
currentTxt = self.getBtn.get()
updateEnt = self.getBtn.set(currentTxt + iVal)
def clearScreen(self):
self.log("CLEAR (CE)")
ent.delete(0, END)
def evaL(self):
self.log("=")
self.getBtn.set(str(eval(self.getBtn.get())))
self.log(self.getBtn.get())
def logLbl(self):
myFile = open(r".\log.dat", "a")
myFile.write("\n==================================\n")
myFile.write("Date: " + str(time.strftime("%m/%d/%Y")) + " -- Time: " + str(time.strftime("%I:%M:%S")))
myFile.write("\n==================================\n")
myFile.close()
My Program
from tkinter import *
import time
import clcClass
root = Tk()
root.title('skClc v1')
clc = clcClass.CalcFunc()
clc.logLbl()
clc.getBtn = StringVar()
ent = Entry(root, textvariable=clc.getBtn, justify=RIGHT, font=10, relief=RIDGE, bd=2, width=15)
ent.grid(row=0, columnspan=3, pady=10)
button1 = Button(root, text="1", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('1'))
button2 = Button(root, text="2", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('2'))
button3 = Button(root, text="3", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('3'))
button4 = Button(root, text="4", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('4'))
button5 = Button(root, text="5", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('5'))
button6 = Button(root, text="6", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('6'))
button7 = Button(root, text="7", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('7'))
button8 = Button(root, text="8", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('8'))
button9 = Button(root, text="9", height=1, width=5, bg='light blue', command=lambda:clc.onScreen('9'))
button0 = Button(root, text="0", height=1, width=5, bg='light blue', command=lambda:onScreen('0'))
buttonP = Button(root, text="+", height=1, width=5, bg='gray', command=lambda:clc.onScreen('+'))
buttonM = Button(root, text="-", height=1, width=5, bg='gray', command=lambda:clc.onScreen('-'))
buttonMM = Button(root, text="x", height=1, width=5, bg='gray', command=lambda:clc.onScreen('*'))
buttonDD = Button(root, text="รท", height=1, width=5, bg='gray', command=lambda:clc.onScreen('/'))
buttonEE = Button(root, text="=", height=1, width=5, bg='light green', command=clc.evaL)
buttonCC = Button(root, text="CLEAR (CE)", height=1, width=20, bg='orange', command=clc.clearScreen)
button1.grid(row=1, column=0, pady=5)
button2.grid(row=1, column=1, pady=5)
button3.grid(row=1, column=2, pady=5)
button4.grid(row=2, column=0, pady=5)
button5.grid(row=2, column=1, pady=5)
button6.grid(row=2, column=2, pady=5)
button7.grid(row=3, column=0, pady=5)
button8.grid(row=3, column=1, pady=5)
button9.grid(row=3, column=2, pady=5)
button0.grid(row=4, column=0, pady=5)
buttonP.grid(row=4, column=1, pady=5)
buttonM.grid(row=4, column=2, pady=5)
buttonEE.grid(row=5, column=0, pady=5)
buttonDD.grid(row=5, column=1, pady=5)
buttonMM.grid(row=5, column=2, pady=5)
buttonCC.grid(row=6, column=0, pady=5, columnspan=3)
root.maxsize(140,245);
root.minsize(140,245);
root.mainloop()
ent = Entry(root, ....)
clc = clcClass.CalcFunc(ent)
class CalcFunc:
def __init__(self, entry):
self.entry = entry
def clearScreen(self):
self.log("CLEAR (CE)")
self.entry.delete(0, END)
Here's an abbreviated example:
#my_entry.py
from tkinter import END
import time
class EntryWithLogger:
def __init__(self, entry):
self.entry = entry
def log(self, val):
with open("log.dat", "a") as my_file: #Automatically closes the file--even if an exception occurs, which is not the case with my_file.close().
my_file.write("%s\n" % val)
def onScreen(self, i_val):
self.log(i_val)
self.entry.insert(END, i_val)
def clearScreen(self):
self.log("CLEAR (CE)")
self.entry.delete(0, END)
Note that I didn't use a StringVar(), which doesn't appear to be necessary. If you need it, you can always pass it as an argument to __init__(), then store it on self.
import my_entry as me
import tkinter as tk
root = tk.Tk()
root.title("Calculator")
root.geometry("+100+50") #("300x500+200+10") dimension, position
entry = tk.Entry(root, justify=tk.RIGHT, font=10, relief=tk.RIDGE, bd=2, width=15)
entry.grid(row=0, columnspan=3, pady=10)
entry_with_logger = me.EntryWithLogger(entry)
#Create the buttons in a loop:
for i in range(10):
row_num, col_num = divmod(i, 3) #divmod(7, 2) => (3, 1), divmod(0, 3) => (0, 0), divmod(4, 3) => (1, 1)
row_num += 1
button_text = str(i)
tk.Button(root, text=button_text,
height=1,
width=5,
bg='light blue',
command=lambda x=button_text: entry_with_logger.onScreen(x)
).grid(row=row_num, column=col_num, pady=5)
#Put the clear button at the bottom of the grid:
tk.Button(root, text="CLEAR (CE)",
height=1,
width=20,
bg='orange',
command=entry_with_logger.clearScreen
).grid(row=row_num+1, columnspan=3) #columnspan tells grid() to use 3 cells for the button,
#and the button will be centered by default.
root.mainloop()
Or, you could do it like this:
#my_entry.py
from tkinter import Entry, END
import time
class EntryWithLogger(Entry):
#Because __init__() is not implemented, the parent class's __init__() gets
#called, so you create an EntryWithLogger just like you would an Entry.
def log(self, val):
with open("log.dat", "a") as my_file: #Automatically closes the file--even if there is an exception, which is not the case with my_file.close().
my_file.write("%s\n" % val)
def onScreen(self, i_val):
self.log(i_val)
self.insert(END, i_val)
def clearScreen(self):
self.log("CLEAR (CE)")
self.delete(0, END)
import my_entry as me
import tkinter as tk
root = tk.Tk()
root.title("Calculator")
root.geometry("+100+50") #("300x500+200+10") dimension, position
entry = me.EntryWithLogger(root, justify=tk.RIGHT, font=10, relief=tk.RIDGE, bd=2, width=15)
entry.grid(row=0, columnspan=3, pady=10)
#Create the buttons in a loop:
for i in range(10):
row_num, col_num = divmod(i, 3) #divmod(7, 2) => (3, 1), divmod(0, 3) => (0, 0), divmod(4, 3) => (1, 1)
row_num += 1
button_text = str(i)
tk.Button(root, text=button_text,
height=1,
width=5,
bg='LightBlue',
command=lambda x=button_text: entry.onScreen(x)
).grid(row=row_num, column=col_num, pady=5)
#Put the clear button at the bottom of the grid:
tk.Button(root, text="CLEAR (CE)",
height=1,
width=20,
bg='orange',
command=entry.clearScreen
).grid(row=row_num+1, columnspan=3) #columnspan tells grid() to use 3 cells for the button,
#and the button will be centered by default.
root.mainloop()