I'm using tkinter in my app and I set a frame with this code:
from tkinter import *
from tkinter import ttk
from tkinter import simpledialog
class View:
def __init__(self,tab):
self.tab1 = tab
self.widgets()
def proxy_checkbox_clicked(self, event=None):
if self.proxyVar.get() == 0:
self.proxyIPTextEdit.config(state=DISABLED)
self.proxyPortTextEdit.config(state=DISABLED)
self.proxyUserTextEdit.config(state=DISABLED)
self.proxyPassTextEdit.config(state=DISABLED)
else:
self.proxyIPTextEdit.config(state=NORMAL)
self.proxyPortTextEdit.config(state=NORMAL)
self.proxyUserTextEdit.config(state=NORMAL)
self.proxyPassTextEdit.config(state=NORMAL)
def widgets(self):
self.mainFrame = Frame(self.tab1)
self.mainFrame.grid(column = 0, row = 0, padx = 0, pady = 0)
# Set Add Frame
self.loginFrame = Frame(self.mainFrame)
self.loginFrame.grid(column = 0, row = 0, padx = 0, pady = 0)
label = Label(self.loginFrame, text = "Name:")
label.grid(column = 0, row = 0, sticky = 'W')
self.nameTextEdit = Entry(self.loginFrame, width = 20)
self.nameTextEdit.grid(column = 1, row = 0)
label = Label(self.loginFrame, text = "Phone:")
label.grid(column = 0, row = 1, sticky = 'W')
self.phoneTextEdit = Entry(self.loginFrame, width = 20)
self.phoneTextEdit.grid(column = 1, row = 1)
self.proxyVar = IntVar()
self.proxyCheckBox = Checkbutton(self.loginFrame, text="Use Proxy", variable=self.proxyVar, command=self.proxy_checkbox_clicked)
self.proxyCheckBox.grid(column = 0, row = 2)
self.proxyFrame = Frame(self.loginFrame)
self.proxyFrame.grid(column = 0, row = 3)
label = Label(self.proxyFrame, text = "IP:")
label.grid(column = 0, row = 0, sticky = 'W')
self.proxyIPTextEdit = Entry(self.proxyFrame, width = 20)
self.proxyIPTextEdit.grid(column = 1, row = 0)
label = Label(self.proxyFrame, text = "Port:")
label.grid(column = 0, row = 1, sticky = 'W')
self.proxyPortTextEdit = Entry(self.proxyFrame, width = 20)
self.proxyPortTextEdit.grid(column = 1, row = 1)
label = Label(self.proxyFrame, text = "User:")
label.grid(column = 0, row = 2, sticky = 'W')
self.proxyUserTextEdit = Entry(self.proxyFrame, width = 20)
self.proxyUserTextEdit.grid(column = 1, row = 2)
label = Label(self.proxyFrame, text = "Password:")
label.grid(column = 0, row = 3, sticky = 'W')
self.proxyPassTextEdit = Entry(self.proxyFrame, width = 20)
self.proxyPassTextEdit.grid(column = 1, row = 3)
self.proxyIPTextEdit.config(state=DISABLED)
self.proxyPortTextEdit.config(state=DISABLED)
self.proxyUserTextEdit.config(state=DISABLED)
self.proxyPassTextEdit.config(state=DISABLED)
self.addButton = Button(self.loginFrame, text="Login", width = 10)
self.addButton.grid(column = 0, row = 4)
When i run it i get this frame, any idea what is the problem? What is missing?
Your problem is that self.proxyFrame fills column 1, of self.loginFrame. By definition, anything in column 2 must be to the right of column 1. One simple solution is to have that frame span two columns - both column 1 and column 2. With that, self.proxyFrame won't force column 1 to be as wide as the whole frame.
self.proxyFrame.grid(column = 0, row = 3, padx=20, pady=20, columnspan=2)
As for the checkbutton... widgets by default are centered in the space allocated to them by grid. If you want it to be left-aligned, add sticky="w" when adding it to the grid.
self.proxyCheckBox.grid(column = 0, row = 2, sticky="w")
Related
This question already has answers here:
I'm getting a TypeError. How do I fix it?
(2 answers)
TypeError: 'function' object is not subscriptable - Python
(4 answers)
Closed 6 months ago.
I'm working on a tkinter GUI API-based application.
I'm attempting to modularize my code in which each function has a specific task to do and some functions just call other functions.
In my case, I bind the search button to the function, search, whose job is to call other API-based functions, such as full_name.
When I did this, an error is thrown, saying that in search full_name() TypeError: 'Label' object is not callable
what's interesting is that
I see no mention of creating instances of Label classes in full_name()
when I bind the search button to function, full_name(), it works just fine. However, I want to bind it to a function that will call all API-based functions, and so far, it's not working
Here's the code below:
#MER for frames placement through .Grid()
#import necessary modules
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
from tkinter import messagebox
import requests
import json
root = Tk()
root.title("F1 Desktop Application")
root.geometry("500x600")
root.configure(bg="white")
#generate 2022 drivers-list [can scale to drivers-list by changing the]
drivers_list_request = requests.get("http://ergast.com/api/f1/2022/drivers.json")
#initialize empty-list
drivers_list = []
drivers_list_object = json.loads(drivers_list_request.content)
for elements in drivers_list_object["MRData"]["DriverTable"]["Drivers"]:
drivers_list.append(elements["givenName"] + " " + elements["familyName"])
#NEED TO UNDERSTAND PRECEDENCE BETWEEN WIDTH, HEIGHT SETTING, VS SPANS. STICKY MAKES PERFECT SENSE
top_frame = LabelFrame(root, width = 300, height = 125)
top_frame.grid(row = 0, column = 0, columnspan = 2)
top_frame.rowconfigure(0, minsize = 75)
top_frame.columnconfigure(0, minsize = 300)
# Update the Entry widget with the selected item in list
def check(e):
v= entry_box.get()
if v=='':
hide_button(menu)
else:
data=[]
for item in drivers_list:
if v.lower() in item.lower():
data.append(item)
update(data)
show_button(menu)
def update(data):
# Clear the Combobox
menu.delete(0, END)
# Add values to the combobox
for value in data:
menu.insert(END,value)
def fillout(event):
try:
entry_box.delete(0,END)
entry_box.insert(0,menu.get(menu.curselection()))
hide_button(menu)
#handle a complete deletion of entry-box via cursor double tap
except:
pass
def hide_button(widget):
widget.grid_remove()
def show_button(widget):
widget.grid()
def full_name():
user_input = entry_box.get()
lower_user_input = user_input.lower().split(" ")[1]
response = requests.get("http://ergast.com/api/f1/drivers/{}.json".format(lower_user_input))
print(response.status_code)
response_object = json.loads(response.content)
name = response_object["MRData"]["DriverTable"]["Drivers"][0]["givenName"] + " " + response_object["MRData"]["DriverTable"]["Drivers"][0]["familyName"]
print(name)
def search():
full_name()
#once works, then make API request
header_label = Label(top_frame, text = "F1 2022 Drivers App", font = ("Arial bold",14), bg = "white")
header_label.grid(row = 0, column = 0, padx = 30)
search_button = Button(top_frame, text = "search" , command = search)
search_button.grid(row = 1, column = 1)
entry_box= Entry(top_frame)
entry_box.grid(row = 1, column = 0)
entry_box.bind('<KeyRelease>',check)
menu= Listbox(top_frame, height = 4)
menu.grid(row = 2, column = 0)
menu.bind("<<ListboxSelect>>",fillout)
left_frame = LabelFrame(root, width = 250, height = 225, borderwidth = 0, highlightthickness = 2)
left_frame.grid(row = 1, column = 0, sticky = NW, padx = 10, pady = 15)
#left_frame.grid_propagate(False)
left_frame.rowconfigure(0, minsize = 100)
left_frame.columnconfigure(0, minsize = 200)
#left_frame_content = LabelFrame(, width = 125, height = 70)
#left_frame_content.grid(row = 1, column = 1, sticky = W)
basic_info = Label(left_frame, text = "Basic Info ", font = ("Arial bold",14))
basic_info.grid(row = 0, column = 0)
full_name = Label(left_frame, text = "Full Name :")
full_name.grid(row = 1, column = 0, sticky = W)
driver_code = Label(left_frame, text = "Driver Code : ")
driver_code.grid(row = 2, column = 0, sticky = W)
nationality = Label(left_frame, text = "Nationality : ")
nationality.grid(row = 3, column = 0, sticky = W)
bottom_left_frame = LabelFrame(root, width = 250, height = 225)
bottom_left_frame.grid(row = 2, column = 0, sticky = N, padx = 10)
bottom_left_frame.rowconfigure(0, minsize = 50)
bottom_left_frame.columnconfigure(0, minsize = 200)
F1_career = Label(bottom_left_frame, text = "F1 Career ", font = ("Arial bold",14))
F1_career.grid(row = 0, column = 0)
wins = Label(bottom_left_frame, text = "Wins :")
wins.grid(row = 1, column = 0, sticky = W)
wins.configure(text = "Wins :" + " 7")
poles = Label(bottom_left_frame, text = "Poles :")
poles.grid(row = 2, column = 0, sticky = W)
test = Label(bottom_left_frame, text = "test")
test.grid(row = 2, column = 1)
podiums = Label(bottom_left_frame, text = "Podiums :")
podiums.grid(row = 3, column = 0, sticky = W)
podiums.configure(text = "Podiums :" + "Lewis Hamilton")
drivers_championships = Label(bottom_left_frame, text = "Championships :")
drivers_championships.grid(row = 4, column = 0, sticky = W)
bottom_right_frame = LabelFrame(root, width = 250, height = 225)
bottom_right_frame.grid(row = 2, column = 1, sticky = W)
bottom_right_frame.rowconfigure(0, minsize = 50)
bottom_right_frame.columnconfigure(0, minsize = 150)
hide_button(menu)
root.mainloop()
Feel free to ask for more clarity. I would be grateful if anyone has a reason/solution
You have used the same name for a label:
full_name = Label(left_frame, text = "Full Name :")
So it will override the full_name().
Use another name for the label, for example full_name_label:
full_name_label = Label(left_frame, text = "Full Name :")
full_name_label.grid(row = 1, column = 0, sticky = W)
I am new to tkinter and am trying to create a GUI with a Combobox. If a certain value ('new subgroup') is chosen, other widgets should appear (label_4, label_5 and label_6). If any other value of the combobox is being chosen, label_7 should appear.
The issue that I am having right now, is that this works only the first time! If I change my mind, and chose another value than first chosen, the labels that appeared through my first choice still stay, with the second choice just appearing on top of it.
How can I only see the labels I want to see, even after having changed my mind and chosen another value from the combobox?
The code is somewhat long, but the important part starts at input_3, the rest is just for a bit of context ;).
from tkinter import *
from tkinter import ttk
root = Tk()
#configure the root
root.title('Add nodes')
root.columnconfigure(0, weight = 1)
root.rowconfigure(0, weight = 1)
#add frame on the root
frame_add = ttk.Frame(root)
frame_add.columnconfigure(0, weight = 1)
frame_add.columnconfigure(1, weight = 1)
frame_add.columnconfigure(2, weight = 1)
frame_add.rowconfigure(0, weight = 1)
frame_add.rowconfigure(1, weight = 1)
frame_add.rowconfigure(2, weight = 1)
frame_add.rowconfigure(3, weight = 1)
frame_add.rowconfigure(4, weight = 1)
frame_add.grid(column = 0, row = 0)
#first row
label_1 = ttk.Label(frame_add, text = 'Label (name of the .json file):')
label_1.grid(column = 0, row = 0, sticky = 'E')
label = ttk.Entry(frame_add)
label.insert(0, 'write label here')
label.grid(column = 1, row = 0, columnspan= 2, pady = 5)
#second row
label_2 = ttk.Label(frame_add, text = 'Node (name of the node \
in the graph database):')
label_2.grid(column = 0, row = 1, sticky = 'E')
Node = ttk.Entry(frame_add)
Node.insert(0, 'write node here')
Node.grid(column = 1, row = 1, columnspan = 2, pady = 5)
#third row
label_3 = ttk.Label(frame_add, text = 'Define subgroup of node:')
label_3.grid(column = 0, row = 2, sticky = 'E')
selected_colour = StringVar()
input_3 = ttk.Combobox(frame_add, textvariable = selected_colour, )
input_3['state'] = 'readonly'
input_3['values'] = ['requirement', 'property',
'measurement_calculate', 'measurement_value',
'measurement_signal_characterization',
'measurement_technology', 'calculate_value',
'measured_variables_expression', 'main_function',
'part_function', 'partial_solution',
'test_bed_module', 'electronics',
'mechanical_structure', 'new subgroup']
width = len(max(input_3['values'], key = len)) + 2
input_3['width'] = width
input_3.grid(column = 1, row = 2, columnspan = 2, pady = 5)
#after having chosen a value from input_3, this shows (depending on the value):
label_4 = ttk.Label(frame_add, text = 'Please insert the \
properties and corresponding values of the new subgroup:')
label_5 = ttk.Entry(frame_add)
label_5.insert(4, 'Category')
label_6 = ttk.Entry(frame_add)
label_6.insert(1, 'Carateristic to save')
label_7 = ttk.Entry(frame_add)
label_7.insert(1, 'Test')
#event to read the choice on input 3 and show the different widgets
def retrieve(event):
if 'new subgroup' == selected_colour.get():
label_4.grid(column = 0, row = 3, columnspan = 3)
label_5.grid(column = 0, row = 4, pady = 5)
label_6.grid(column = 1, row = 4, pady = 5)
label_7.destroy()
else:
label_4.destroy()
label_5.destroy()
label_6.destroy()
label_7.grid(column = 0, row = 3, pady = 5)
input_3.bind('<<ComboboxSelected>>', retrieve, "+")
root.mainloop()
Thanks everyone for your help!
I'm trying to create a user interface with Tkinter and there are a lot of labels and the command to create them it's very repetitive. I know in my guts there's a better more elegant way to do this but I don't know what it is :D
Could you please advise me how you would reduce my 100+lines?
import tkinter as tk
'create window'
BLK_Window = tk.Tk()
BLK_Window.title('Blackrock Primary Custom Baskets')
BLK_Window.geometry('1280x720')
BLK_Window.resizable(width=0, height=0)
BLK_Window.columnconfigure(4,minsize=50)
'set up min size for each column'
BLK_Window.columnconfigure(5,minsize=50)
BLK_Window.columnconfigure(6,minsize=50)
BLK_Window.columnconfigure(7,minsize=50)
BLK_Window.columnconfigure(8,minsize=50)
BLK_Window.columnconfigure(9,minsize=50)
BLK_Window.columnconfigure(10,minsize=50)
BLK_Window.columnconfigure(11,minsize=50)
BLK_Window.columnconfigure(12,minsize=50)
BLK_Window.columnconfigure(13,minsize=50)
BLK_Window.columnconfigure(14,minsize=50)
BLK_Window.columnconfigure(15,minsize=50)
BLK_Window.columnconfigure(16,minsize=50)
BLK_Window.columnconfigure(17,minsize=50)
BLK_Window.columnconfigure(18,minsize=50)
BLK_Window.columnconfigure(19,minsize=50)
'create every label'
A_L1 = tk.Label(text="1)")
A_L1.grid(row = 0, column = 0)
A_L2 = tk.Label(text="Event Description")
A_L2.grid(row = 0, column = 1)
A_E1 = tk.Entry(BLK_Window)
A_E1.grid(row = 0, column = 2)
A_L3 = tk.Label(text="EV Score")
A_L3.grid(row = 1, column = 1)
A_E2 = tk.Entry(BLK_Window)
A_E2.grid(row = 1, column = 2)
A_L5 = tk.Label(text="Ticker",borderwidth=2, relief="groove")
A_L5.grid(row = 0, column = 5,sticky="E"+"W")
A_L6 = tk.Label(text="Shs",borderwidth=2, relief="groove")
A_L6.grid(row = 0, column = 6,sticky="E"+"W")
A_L7 = tk.Label(text="MV",borderwidth=2, relief="groove")
A_L7.grid(row = 0, column = 7,sticky="E"+"W")
A_L8 = tk.Label(text="Units",borderwidth=2, relief="groove")
A_L8.grid(row = 0, column = 8,sticky="E"+"W")
A_L9 = tk.Label(text="Cr/Re",borderwidth=2, relief="groove")
A_L9.grid(row = 0, column = 9,sticky="E"+"W")
A_L10 = tk.Label(text="AP/MM",borderwidth=2, relief="groove")
A_L10.grid(row = 0, column = 10,sticky="E"+"W")
A_L11 = tk.Label(text="Type",borderwidth=2, relief="groove")
A_L11.grid(row = 0, column = 11,sticky="E"+"W")
A_L12 = tk.Label(text="Feedback",borderwidth=2, relief="groove")
A_L12.grid(row = 0, column = 12,sticky="E"+"W")
A_L13 = tk.Label(text="OP Cutoff",borderwidth=2, relief="groove")
A_L13.grid(row = 0, column = 13,sticky="E"+"W")
A_L14 = tk.Label(text="LG Cutoff",borderwidth=2, relief="groove")
A_L14.grid(row = 0, column = 14,sticky="E"+"W")
A_L15 = tk.Label(text="BBG Ticker",borderwidth=2, relief="groove")
A_L15.grid(row = 0, column = 15,sticky="E"+"W")
A_L16= tk.Label(text="Market Cap",borderwidth=2, relief="groove")
A_L16.grid(row = 0, column = 16,sticky="E"+"W")
A_L17 = tk.Label(text="Fund AUM",borderwidth=2, relief="groove")
A_L17.grid(row = 0, column = 17,sticky="E"+"W")
A_L18 = tk.Label(text="Min",borderwidth=2, relief="groove")
A_L18.grid(row = 0, column = 18,sticky="E"+"W")
A_L19 = tk.Label(text="Max",borderwidth=2, relief="groove")
A_L19.grid(row = 0, column = 19,sticky="E"+"W")
A_O5 = tk.Label(master=BLK_Window)
A_O5.grid(row = 1, column = 5)
A_O6 = tk.Label(master=BLK_Window)
A_O6.grid(row = 1, column = 6)
A_O7 = tk.Label(master=BLK_Window)
A_O7.grid(row = 1, column = 7)
'function to sqr and apply to 3 cells'
def sqr():
x1 = A_E2.get()
x2 = (float(x1))**2
A_O5["text"] = x2
A_O6["text"] = x2
A_O7["text"] = x2
A_B2 = tk.Button(
master=BLK_Window,
text="Text",
command=sqr
)
A_B2.grid(row = 1, column = 3,sticky="E"+"W")
A_B1 = tk.Button(text ="Check")
A_B1.grid(row = 0, column = 3)
BLK_Window.mainloop()
Thanks for your help
When you are creating variables with a number as part of a name, that's usually a sign that you can store the objects in a list or dictionary. In this case, however, it doesn't look like you need to store the label variables at all.
You can create them in a loop, and configure the columns in the same loop. If you need to keep references to the labels, I recommend you store them in a dictionary.
label_widgets = {}
labels = ("Ticker", "Shs", "MV", "Units", "Cr/Re", "AP/MM", "Type",
"Feedback", "OP Cutoff", "LG Cutoff", "BBG Ticker",
"Market Cap", "Fund AUM", "Min", "Max")
for c, text in enumerate(labels):
column = c+5
label = tk.Label(BLK_Window, text=text, borderwidth=2, relief="groove")
label_widgets[text] = label
label.grid(row=0, column=column, sticky="ew")
BLK_Window.grid_columnconfigure(column, minsize=50)
With that, you can later reference the label widget by its text:
label_widgets["OP Cutoff"].configure(...)
You can do looping for BLK_Window.columnconfigure in order to reduced duplicated. And will be adding #Bryan Oakley's snippet.
Completed code:
import tkinter as tk
'create window'
BLK_Window = tk.Tk()
BLK_Window.title('Blackrock Primary Custom Baskets')
BLK_Window.geometry('1280x720')
BLK_Window.resizable(width=0, height=0)
BLK_Window.columnconfigure(4,minsize=50)
'set up min size for each column'
for index in range(5, 20):
BLK_Window.columnconfigure(index,minsize=50)
'create every label'
label_widgets = {}
labels = ("Ticker", "Shs", "MV", "Units", "Cr/Re", "AP/MM", "Type",
"Feedback", "OP Cutoff", "LG Cutoff", "BBG Ticker",
"Market Cap", "Fund AUM", "Min", "Max")
for c, text in enumerate(labels):
column = c+5
label = tk.Label(BLK_Window, text=text, borderwidth=2, relief="groove")
label_widgets[text] = label
label.grid(row=0, column=column, sticky="ew")
'function to sqr and apply to 3 cells'
def sqr():
x1 = A_E2.get()
x2 = (float(x1))**2
A_O5["text"] = x2
A_O6["text"] = x2
A_O7["text"] = x2
A_B2 = tk.Button(
master=BLK_Window,
text="Text",
command=sqr
)
A_B2.grid(row = 1, column = 3,sticky="E"+"W")
A_B1 = tk.Button(text ="Check")
A_B1.grid(row = 0, column = 3)
BLK_Window.mainloop()
The problem i'm having is that it even though it executes, the tkinter window remains blank. and as a side issue the window doesn't refresh to update the Actions checkbutton.
from tkinter import *
Pieces = {}
Actions =[]
class GameCreation(Frame):
def __init(self,master):
super(GameCreation,self).__init__(master)
self.grid()
self.CreatePiece()
#Creating pieces function
def CreatePiece(self):
Label(self,text ="What piece are we working with?").grid(row =0,
column = 0,
sticky = W)
self.piece_entry = Entry(self)
self.piece_entry.grid(row =0,
column = 1,
sticky = W)
Label (self, text = "Tick all the actions which the piece has").grid (row =1,
column = 0,
sticky = W)
self.Actions = BooleanVar()
self.Actions.set(None)
column = 0
row = 4
for action in Actions:
Checkbutton(self,text = action, variable = self.checkButton, value = action).grid( row = row,
column = column,
sticky = W)
if column == 5:
row +=1
column = 0
else:
column +=1
Button(self,text = "Add action", command = self.AddAction).grid(row = 1,
column = 0,
sticky = W)
self.action_entry = Entry(self)
self.action_entry.grid(row = 1, column = 1, sticky = W)
Button (self, text = "Create piece and it's actions", command = Add_to_dict).grid(row =2,
column = 0,
sticky = W)
self.Add_dict = Text(self, width =10, height = 2, wrap = WORD)
self.Add_dict.grid( row = 3, column = 0, columnspan = 4)
This function should add to the Actions list
def addAction(self):
action = self.action_entry.get()
Actions.append(action)
This function should just print the name of the piece and the actions chosen for it
def Add_to_dict(self):
actions = Actions.get()
piece = piece_entry.get()
rules = piece, ":", actions
self.Add_dict.delete(0.0,END)
self.Add_dict.insert(0.0,rules)
You need to use __init__, not __init
Also, if you're using BooleanVar, you must set it to True or False, not None:
self.Actions.set(False)
Also, you have a method named addAction but you are calling it like self.AddAction, and you have a method named Add_to_dict that you are calling like Add_to_dict rather than self.Add_to_dict.
And finally, you don't appear to be creating an instance of GameCreation anywhere.
I'm not sure what I'm doing wrong, but it seems that my radiobutton only shows one option instead of two options(which is what I originally wanted).
PLAYERS = [("Black", "black"),
("White", "white")]
def first_player(self) -> str:
self.firstplayer = tkinter.StringVar(value = 'black')
self._player_text = tkinter.StringVar()
self._player_text.set('Which player moves first: ')
player_label = tkinter.Label(
master = self.root_window, textvariable = self._player_text,
background = 'yellow', height = 1, width = 20, font = DEFAULT_FONT)
player_label.grid(row=1, column = 0, padx = 10, pady=90, sticky = tkinter.W+tkinter.N)
for text,mode in PLAYERS:
first = tkinter.Radiobutton(self.root_window, text = text,
variable = self.firstplayer , value = mode)
first.grid(row = 1, column = 0, padx = 300, pady = 90, sticky = tkinter.W + tkinter.N)
return self.firstplayer.get()
You are placing both radiobuttons in the same place: row 1, column 0. The first one it thus invisible because it is under the second one. If you want the label and two radiobuttons on the same row but different columns, the solution is to give them all the same row, and different columns.
There are many ways to accomplish this, I'll show you one:
column = 1
for text,mode in PLAYERS:
first = tkinter.Radiobutton(self.root_window, text = text,
variable = self.firstplayer , value = mode)
first.grid(row = 1, column = column, sticky = tkinter.W + tkinter.N)
column += 1