Making a new window with an input widget using tkinter - python

I can't seem to make my new window display the inputer code
it only displays a new empty window without the labels and the input widget
i want to make a simple GUI for a school project, but i dont want to type the name in the python shell, but in the interface
please help and tell me where im wrong, im still new to python
from collections import deque
first = deque([])
last = deque([])
nom = 0
import tkinter as tk
from tkinter import *
class Application(tk.Frame):
def __init__(self, master=None, nom=0, priono=1, prio=1):
super().__init__(master)
self.pack()
self.create_widgets()
self.nom= nom
self.priono= priono
self.prio=prio
def create_widgets(self):
self.add = tk.Button(self, bg ="black", fg="pink")
self.add["text"] = "-----Add to queue-----\n(click me)"
self.add["command"] = self.create_window
self.add.pack(side="top", pady = 10, padx = 20)
self.add["font"] = "Times 16 bold"
self.remov = tk.Button(self, bg ="black", fg="pink")
self.remov["text"]= "---Remove in queue---\n(click me)"
self.remov["command"] = self.remov_
self.remov.pack(side="top", pady = 10, padx = 20)
self.remov["font"] = "Times 16 bold"
self.quit = tk.Button(self, text="QUIT", fg="white", bg = "red",
command=root.destroy)
self.quit.pack(side="bottom")
def create_window(self):
def inputer(self):
self.L1 = tk.Label(self, text = "Name")
self.L1.pack( side = LEFT)
self.E1 = tk.Entry(self, bd =5)
self.E1.pack(side = RIGHT)
win2 = Toplevel(self)
win2.button = Button(self, text='Ready?\nClick Here', command=inputer)
def say_hi(self):
print("hi there, everyone!")
def add_1(self):
name=input("What is your name? ")
first.append(name)
print("Good Day!",first[self.nom])
print("Your priority number is:","%03d" % (self.priono))
self.priono+=1
self.nom+= 1
def remov_(self):
if (len(first)) >= 1:
first.popleft()
else:
print("No one left in queue")
root = tk.Tk()
root.config(background="black")
app = Application(master=root)
app.master.title("ID QUEUEING SYSTEM beta")
app.master.minsize(540, 360)
app.master.maxsize(600, 500)
app.mainloop()

You must use your toplevel to indicate where the widgets must appear; you must also pack (place or grid) the widgets belonging to your toplevel window.
The code from inputer needed to be placed outside of the inner function; you can now write the code to have this inputer do what you need it to do:
I removed the star import and added the prefix tk. to all tkinter method calls.
import tkinter as tk
from collections import deque
class Application(tk.Frame):
def __init__(self, master=None, nom=0, priono=1, prio=1):
super().__init__(master)
self.pack()
self.create_widgets()
self.nom = nom
self.priono= priono
self.prio=prio
def create_widgets(self):
self.add = tk.Button(self, bg ="black", fg="pink")
self.add["text"] = "-----Add to queue-----\n(click me)"
self.add["command"] = self.create_window
self.add.pack(side="top", pady = 10, padx = 20)
self.add["font"] = "Times 16 bold"
self.remov = tk.Button(self, bg ="black", fg="pink")
self.remov["text"]= "---Remove in queue---\n(click me)"
self.remov["command"] = self.remov_
self.remov.pack(side="top", pady = 10, padx = 20)
self.remov["font"] = "Times 16 bold"
self.quit = tk.Button(self, text="QUIT", fg="white", bg = "red",
command=root.destroy)
self.quit.pack(side="bottom")
def create_window(self):
def inputer():
print('inputer ', end=': ')
print(self.E1.get())
win2 = tk.Toplevel(self)
win2_button = tk.Button(win2, text='Ready?\nClick Here', command=inputer)
win2_button.pack()
self.L1 = tk.Label(win2, text = "Name")
self.L1.pack( side=tk.LEFT)
self.E1 = tk.Entry(win2, bd =5)
self.E1.pack(side=tk.RIGHT)
def say_hi(self):
print("hi there, everyone!")
def add_1(self):
name=input("What is your name? ")
first.append(name)
print("Good Day!",first[self.nom])
print("Your priority number is:","%03d" % (self.priono))
self.priono+=1
self.nom+= 1
def remov_(self):
if (len(first)) >= 1:
first.popleft()
else:
print("No one left in queue")
root = tk.Tk()
root.config(background="black")
app = Application(master=root)
app.master.title("ID QUEUEING SYSTEM beta")
app.master.minsize(540, 360)
app.master.maxsize(600, 500)
app.mainloop()

Related

How can I bind a combobox to a Radiobutton

I have some Radiobuttons. Depending of what Radio button was selected I want to have different Combobox values. I don't know how I can solve the problem. In a further step I want to create further comboboxes which are dependend on the value of the first.
The following code creates the list of user, but it does not show up in the combobox.
For me it is difficult to understand where the right position of functions is, and if I need a lambda function nor a binding.
import tkinter as tk
from tkinter import ttk
import pandas as pd
import os
global version
global df_MA
df_MA = []
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.geometry('300x100')
self.title('Toplevel Window')
self.btn = ttk.Button(self, text='Close',command=self.destroy).pack(expand=True)
class App(tk.Tk):
def __init__(self,*args, **kwargs):
super().__init__()
# def load_input_values(self):
def set_department(department):
if department == "produktion":
working_df_complete = path_input_produktion
if department == "service":
working_df_complete = path_input_service
working_df_complete = pd.read_excel(working_df_complete)
working_df_complete = pd.DataFrame(working_df_complete)
'''set worker df'''
df_MA = working_df_complete.loc[:,'MA']
df_MA = list(df_MA.values.tolist())
def select_working_step():
return
'''Define Variable Bereich aofter clicking of radio button '''
'''SEEMS TO ME UNECCESSARY COMPLICATED, but I dont't know how to do it properly. I am no progammer'''
border = 10
spacey = 10
'''paths for input file'''
path_input_produktion = os.path.abspath('input_data\werte_comboboxen_produktion.xlsx')
path_input_service = os.path.abspath('input_data\werte_comboboxen_service.xlsx')
self.geometry('500x600')
'''Variablen for department'''
department = tk.StringVar()
department.set(" ")
'''place Frame department'''
self.rb_frame_abteilung = tk.Frame(self)
'''Radiobuttons for department'''
rb_abteilung_produktion = tk.Radiobutton(self.rb_frame_abteilung, text="Produktion", variable= department,
value="produktion", command= lambda: set_department(department.get()))
rb_abteilung_service = tk.Radiobutton(self.rb_frame_abteilung, text="Service", variable= department,
value="service", command= lambda: set_department(department.get()) )
rb_abteilung_produktion.pack(side="left", fill=None, expand=False, padx=10)
rb_abteilung_service.pack(side="left", fill=None, expand=False, padx =10)
self.rb_frame_abteilung.grid(row=5, column=1, sticky="nw", columnspan=99)
self.label_user = ttk.Label(self, text='user').grid(row=15,
column=15, pady=spacey,padx=border, sticky='w')
self.combobox_user = ttk.Combobox(self, width = 10, value= df_MA)
self.combobox_user.bind("<<ComboboxSelected>>", select_working_step)
self.combobox_user.grid(row=15, column=20, pady=spacey, sticky='w')
if __name__ == "__main__":
app = App()
app.mainloop()
´´´
I rewrote everything using indexes and removing global variables...
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class App(tk.Tk):
"""Application start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_close)
self.title("Simple App")
self.option = tk.IntVar()
self.departments = ('Produktion','Service')
self.df_MA_1 = ['Peter','Hans','Alfred']
self.df_MA_2 = ['Otto','Friedrich','Tanja']
self.init_ui()
self.on_reset()
def init_ui(self):
w = ttk.Frame(self, padding=8)
r = 0
c = 1
ttk.Label(w, text="Combobox:").grid(row=r, sticky=tk.W)
self.cbCombo = ttk.Combobox(w, values="")
self.cbCombo.grid(row=r, column=c, padx=5, pady=5)
r += 1
ttk.Label(w, text="Radiobutton:").grid(row=r, sticky=tk.W)
for index, text in enumerate(self.departments):
ttk.Radiobutton(w,
text=text,
variable=self.option,
value=index,
command= self.set_combo_values).grid(row=r,
column=c,
sticky=tk.W,
padx=5, pady=5)
r +=1
r = 0
c = 2
b = ttk.LabelFrame(self, text="", relief=tk.GROOVE, padding=5)
bts = [("Reset", 0, self.on_reset, "<Alt-r>"),
("Close", 0, self.on_close, "<Alt-c>")]
for btn in bts:
ttk.Button(b, text=btn[0], underline=btn[1], command = btn[2]).grid(row=r,
column=c,
sticky=tk.N+tk.W+tk.E,
padx=5, pady=5)
self.bind(btn[3], btn[2])
r += 1
b.grid(row=0, column=1, sticky=tk.N+tk.W+tk.S+tk.E)
w.grid(row=0, column=0, sticky=tk.N+tk.W+tk.S+tk.E)
def set_combo_values(self):
print("you have selected {0} radio option".format(self.option.get()))
self.cbCombo.set("")
if self.option.get() == 0:
self.cbCombo["values"] = self.df_MA_1
else:
self.cbCombo["values"] = self.df_MA_2
def on_reset(self, evt=None):
self.cbCombo.set("")
self.option.set(0)
self.set_combo_values()
def on_close(self,evt=None):
"""Close all"""
if messagebox.askokcancel(self.title(), "Do you want to quit?", parent=self):
self.destroy()
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()

Modules and classes in Python for a desktop application

This is to be a desktop application for opening multiple small databases and running queries on them. So far I've written some code for opening forms as necessary. Is this a good way to do it? Also - the code shown opens two copies of each form - what am I doing wrong? It's my first attempt at Python and I'm a rudimentary programmer so simple answers would be of most help please. TIA (Python 3.9.6)
link_1.py
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
#if another function in the class is called, the __init__ function is run at start up
def __init__(self):
print("in link_1 __init__ instruction")
#the call_function function can be called at start up, or not, and will act accordingly
def call_function(self):
print("in call_function")
#the line below is run at start up whether or not another function in the class is called
print("in link_1")
root.withdraw() #hides the blank form at start up
#if __name__ == "__main__":
#the line below shows the link_2 form, whether or not the if __name__==__main__ condition is used as its condition
link_2.ClassLink_2(root).__init__(root)
#link_3.ClassLink_3(root).__init__(root)
#the line below runs call_function on start up to print text
ClassLink_1().call_function()
root.mainloop()
link_2.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
import link_3
root = Tk()
class ClassLink_2:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).__init__(root)
root.withdraw() #hides the blank form at start up
link_3.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
root = Tk()
class ClassLink_3:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_2")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_2").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_3", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).__init__(root) this file has not yet been made
root.withdraw() #hides the blank form at start up
This is a proposed solution, can be expanded as needed. Constructive suggestions for improvement of the structure or code would be appreciated. TIA. I've left in the details in case they are of use to anyone.
link_1
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
def __init__(self):
print("in link_1 __init__ instruction")
root.withdraw() #hides the blank form at start up
link_2.ClassLink_2(root).openNewWindow(0)
root.mainloop()
link_2
from tkinter import Tk, Button
from tkinter import *
import link_3
root = Tk()
class ClassLink_2:
root.withdraw() #hides the blank form at start up
class_var_1 = 0
inst_var_1 = 0
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
newWindow = Toplevel(root)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
self.add_button = Button(newWindow, text="increment class_var_1", command= self.inc_class_var_1)
self.add_button.grid(row=5, column=1)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).openNewWindow(0)
def inc_class_var_1(self):
ClassLink_2.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
link_3
from tkinter import Tk, Button
from tkinter import *
from tkinter.ttk import Combobox
import tkinter.scrolledtext as tkscrolled
# import link_4 <filename of next form>
root = Tk()
class ClassLink_3:
class_var_1 = 0
inst_var_1 = 0
# ------------------------------- START CLASS CONTROLS -----------------------------
root.withdraw()
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
new_window = Toplevel(root)
self.widget_factory(new_window)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).openNewWindow(0) # <filename of next form>
# ---------------------------------- END CLASS CONTROLS -----------------------------
# -------------------------------------- START CALCS --------------------------------------
def inc_class_var_1(self):
ClassLink_3.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
# ---------------------------------------- END CALCS --------------------------------------
# ---------------------------------------- START FACTORY SHOPS-----------------------------------------
def widget_factory(self, new_window):
self.shop_window(new_window)
self.shop_labels(new_window)
self.shop_buttons(new_window)
self.shop_menu(new_window)
self.shop_listbox(new_window)
self.shop_combobox(new_window)
self.shop_radiobuttons(new_window)
self.shop_checkbuttons(new_window)
self.shop_entries(new_window)
self.shop_canvas(new_window)
self.shop_scale(new_window)
self.shop_scrollbars(new_window)
self.shop_textbox(new_window)
self.shop_menu(new_window)
pass
# ------------------------
def shop_window(self, new_window):
new_window.title("Title opened from link_2")
new_window.geometry("800x900")
def shop_labels(self, new_window):
self.label_1 = Label(new_window, text ="Opened from link_2").grid(row=1, column=1)
def shop_buttons(self, new_window):
self.button_1 = Button(new_window, text="in ClassLink_3", command= self.do_add)
self.button_1.grid(row=3, column=1)
self.button_2 = Button(new_window, text="increment class_var_1", command= self.inc_class_var_1)
self.button_2.grid(row=5, column=1)
def shop_listbox(self, new_window):
data=("one", "two", "three", "four")
self.listbox_1 = Listbox(new_window, height=5, selectmode='multiple')
for num in data:
self.listbox_1.insert(END,num)
self.listbox_1.grid(row=7, column=1)
def shop_combobox(self, new_window):
data=("one", "two", "three", "four")
self.combobox_1 = Combobox(new_window, values=data)
self.combobox_1.grid(row=8, column=3)
def shop_radiobuttons(self, new_window):
var_1 = IntVar()
var_1.set(1)
self.rad_btn_1 = Radiobutton(new_window, text="male", variable=var_1, value=1)
self.rad_btn_2 = Radiobutton(new_window, text="female", variable=var_1, value=2)
self.rad_btn_1.grid(row=9, column=1)
self.rad_btn_2.grid(row=9, column=2)
def shop_checkbuttons(self, new_window):
var_1 = IntVar()
var_2 = IntVar()
self.checkbtn_1 = Checkbutton(new_window, text = "Cricket", variable = var_1)
self.checkbtn_2 = Checkbutton(new_window, text = "Tennis", variable = var_2)
self.checkbtn_1.grid(row=10, column=1)
self.checkbtn_2.grid(row=10, column=2)
def shop_entries(self, new_window):
self.entry_1 = Entry(new_window, width = 20)
self.entry_1.insert(0,'Username')
self.entry_1.grid(row= 11, column=2)
self.entry_2 = Entry(new_window, width = 15)
self.entry_2.insert(0,'password')
self.entry_2.grid(row= 12, column=2)
#might want to place on a frame, see example https://coderslegacy.com/python/list-of-tkinter-widgets/
def shop_canvas(self, new_window):
canvas = Canvas(new_window, bg= 'white', width = 260,height = 260) #this is the background for the figure
# left and top of figure is from [x from left, y from top] of canvas right and bottom of figure from [x from left, y from top] of canvas
coordinates = 20, 50, 210, 230
arc = canvas.create_arc(coordinates, start=0, extent=250, fill="blue") #start is from E, extent is in degrees CCW
arc = canvas.create_arc(coordinates, start=250, extent=50, fill="red")
arc = canvas.create_arc(coordinates, start=300, extent=60, fill="yellow")
canvas.grid(row=2, column=1)
def shop_scale(self, new_window):
self.scale_1 = Scale(new_window, from_=0, to=10, orient=VERTICAL)
self.scale_1.grid(row=15, column=2)
self.scale_2 = Scale(new_window, from_=0, to=10, orient = HORIZONTAL)
self.scale_2.grid(row=15, column=3)
def shop_scrollbars(self, new_window):
self.scroll_vert = Scrollbar(new_window)
self.scroll_vert.grid(row=19, column=3)
self.listbox_3 = Listbox(new_window, yscrollcommand = self.scroll_vert.set )
for line in range(1, 100):
self.listbox_3.insert(END, "Number " + str(line))
self.listbox_3.grid(row=19 , column=2)
self.scroll_vert.config(command = self.listbox_3.yview)
def shop_textbox(self, new_window):
#make a frame with parent new_window
self.frame_textbox_1 = Frame(new_window)
self.frame_textbox_1.grid(row=1, column=5)
#make the textbox with parent frame
self.textbox_1 = Text(self.frame_textbox_1)
self.textbox_1.config(wrap=NONE, width=15, height=8) #width, height are characters x rows permitted wrap values should be WORD CHAR, or NONE
#make the X scrollbar with parent frame
self.scroll_text_horiz = Scrollbar(self.frame_textbox_1, orient="horizontal")
self.scroll_text_horiz.config(command = self.textbox_1.xview)
#make the Y scrollbar with parent frame
self.scroll_text_vert = Scrollbar(self.frame_textbox_1, orient="vertical")
self.scroll_text_vert.config(command = self.textbox_1.yview)
#pack the scrollbars before the texbox to allow them to fill the frame width and height
self.scroll_text_horiz.pack(side=BOTTOM, fill=X)
self.scroll_text_vert.pack(side=RIGHT, fill=Y)
self.textbox_1.pack(fill="y")
#connect the scrollbars to the textbox
self.textbox_1["xscrollcommand"] = self.scroll_text_horiz.set
self.textbox_1["yscrollcommand"] = self.scroll_text_vert.set
message = "the quick brown fox"
self.textbox_1.insert(1.1, message)
# ----------------------------------------------
def shop_menu(self, new_window):
print("in shop menu1")
menubar = Menu(new_window)
print("in shop_menu2")
file = Menu(menubar, tearoff=0)
file.add_command(label="New")
file.add_command(label="Open")
file.add_command(label="Save")
file.add_command(label="Save as...")
file.add_command(label="Close")
file.add_separator()
file.add_command(label="Exit", command=new_window.quit)
menubar.add_cascade(label="File", menu=file)
edit = Menu(menubar, tearoff=0)
edit.add_command(label="Undo")
edit.add_separator()
edit.add_command(label="Cut")
edit.add_command(label="Copy")
edit.add_command(label="Paste")
edit.add_command(label="Delete")
edit.add_command(label="Select All")
menubar.add_cascade(label="Edit", menu=edit)
help = Menu(menubar, tearoff=0)
help.add_command(label="About")
menubar.add_cascade(label="Help", menu=help)
new_window.config(menu=menubar)
print("in shop menu3")
# --------------------------------------- END FACTORY SHOPS---------------------------------------

Trying to enable a button using an entry widget

I have two sets of code. One works the other doesn't and I don't know why. In the first set of code I am storing my application into a class and referencing everything there. In the second one I am storing everything in the main function and using it there.
The main details of the problem are here:
I am using a entry widget and a button widget which is initially disabled. I want the button's state to be normal when there is text in the entry widgets text field.
I have searched online for many answers to the first set of code but the closest I have gotten is the second set of code. First I tried to integrate it into my code however that did not work. So what I did was take the code and strip it to the bare minimum and put everything into the main function.
The main difference between the two is one is in a class and the other is in the main function.
import tkinter as tk
class Aplication(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
self.grid()
self.button_clicks = 0
something = tk.StringVar()
button3 = tk.Button(self, text="Print entry", padx = 10, height = 2, bg = "blue", state = "disabled")
entry = tk.Entry(self, textvariable = something)
something.trace('w', self.ActivateButton) #need this to always be exsecuted
entry.grid(column = 2, row = 1)
button3["command"] = lambda: self.PrintEntry(entry.get())
button3.grid(padx = 10, pady = 10)
def PrintEntry (self, entry):
print(entry)
def ActivateButton(self, *_):
if something.get():
button3['state'] = "normal"
else:
button3['state'] = "disabled"
if __name__ == '__main__':
top= tk.Tk()
top.title("Simple Button")
top.geometry("500x300")
app = Aplication(top)
top.mainloop()
def PrintEntry (entry):
print(entry)
def ActivateButton(*_):
if entry.get():
button3['state'] = "normal"
else:
button3['state'] = "disabled"
if __name__ == '__main__':
top= tk.Tk()
top.title("Simple Button")
top.geometry("500x300")
something = tk.StringVar()
button3 = tk.Button(top, text="Print entry", padx = 10, height = 2, bg = "blue", state = "disabled")
entry = tk.Entry(top, textvariable = something, bd = 2)
something.trace('w', ActivateButton)
entry.grid(column = 2, row = 3)
button3["command"] = lambda: PrintEntry(entry.get())
button3.grid(row = 3, column = 1, padx = 10, pady = 10)
top.mainloop()
There are no error messages; however you will find in the first set, the button's state never gets set to normal. Is there a way to do this for the first one? What is the difference between the two that makes it to where I can't enable the button in the first one if it is impossible?
You have to use self. to create class variables so they will be accesible in all methods in class. Currently you create local variable something in __init__ and it is deleted when Python ends __init__ - so finally it removes something.trace() and it doesn't check value in entry.
In this code I use self.something and self.button3 and it works correctly.
import tkinter as tk
class Aplication(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self,master)
self.grid()
self.button_clicks = 0
self.something = tk.StringVar()
self.button3 = tk.Button(self, text="Print entry", padx = 10, height = 2, bg = "blue", state = "disabled")
entry = tk.Entry(self, textvariable = self.something)
self.something.trace('w', self.ActivateButton) #need this to always be exsecuted
entry.grid(column = 2, row = 1)
self.button3["command"] = lambda: self.PrintEntry(entry.get())
self.button3.grid(padx = 10, pady = 10)
def PrintEntry (self, entry):
print(entry)
def ActivateButton(self, *_):
if self.something.get():
self.button3['state'] = "normal"
else:
self.button3['state'] = "disabled"
if __name__ == '__main__':
top= tk.Tk()
top.title("Simple Button")
top.geometry("500x300")
app = Aplication(top)
top.mainloop()
EDIT: the same little different - without lambda. I use self.entry (as class variable) directly in print_entry.
import tkinter as tk
class Aplication(tk.Frame):
def __init__(self, master):
super().__init__(master)#tk.Frame.__init__(self,master)
self.grid()
self.button_clicks = 0
self.something = tk.StringVar()
self.entry = tk.Entry(self, textvariable=self.something)
self.entry.grid(column=2, row=1)
self.button3 = tk.Button(self, command=self.print_entry, text="Print entry", padx=10, height=2, bg="blue", state="disabled")
self.button3.grid(padx=10, pady=10)
self.something.trace('w', self.activate_button) #need this to always be exsecuted
def print_entry(self):
print(self.entry.get())
def activate_button(self, *_):
if self.something.get():
self.button3['state'] = "normal"
else:
self.button3['state'] = "disabled"
if __name__ == '__main__':
top= tk.Tk()
top.title("Simple Button")
top.geometry("500x300")
app = Aplication(top)
top.mainloop()
As pointed out by #furas you need to prefix your variables in the constructor method def __init__ with self. so you can access attributes and methods since it literally represents an instance of the class. This link explains it in more detail https://stackoverflow.com/a/2709832/7585554.
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.grid()
self.button_clicks = 0
self.something = tk.StringVar()
self.button3 = tk.Button(self, text="Print entry", padx=10, height=2, bg="blue", state="disabled")
self.entry = tk.Entry(self, textvariable=self.something)
self.something.trace('w', self.ActivateButton)
self.entry.grid(column=2, row=1)
self.button3["command"] = lambda: self.PrintEntry()
self.button3.grid(padx=10, pady=10)
def PrintEntry (self):
print(self.entry.get())
def ActivateButton(self, *_):
if self.something.get():
self.button3['state'] = "normal"
else:
self.button3['state'] = "disabled"
if __name__ == '__main__':
top = tk.Tk()
top.title("Simple Button")
top.geometry("500x300")
app = Application(top)
top.mainloop()

How to add a scrollbar to window made with tkinter

A simple quiz game
I got this code and I need scrollbars, I tried to search how to add it on stackoverflow (ScrolledWindow with tix...) but I still can't get something that works properly. Could someone help me?
from tkinter import *
from random import randint
root = Tk()
root.title("Quiz")
root.geometry("400x300")
class Window:
def __init__(self, question, answer):
self.text = [question, answer]
self.createLabel()
# self.createText()
self.createEntry()
self.createButton()
def retrieve_input(self):
# inputValue = self.textBox.get("1.0", "end-1c")
# print(inputValue)
if self.mystring.get() == self.text[1]:
print("Esatto. è " + self.text[1])
self.left['text'] = "Esatto"
def createLabel(self):
self.labelframe = LabelFrame(root, text="Domanda:")
self.labelframe.pack(fill="both", expand="yes")
self.left = Label(self.labelframe, text=self.text[0])
self.left.pack()
def createText(self):
self.textBox = Text(height=1)
self.textBox.pack()
def createEntry(self):
self.mystring = StringVar()
self.myentry = Entry(root, textvariable=self.mystring).pack()
def createButton(self):
self.but = Button(text="Click", command=self.retrieve_input)
self.but.pack()
for i in range(10):
one = randint(1, 10)
two = randint(1, 10)
Window("Quanto fa " + str(one) + "+" + str(two) + "?", str(one + two))
root.mainloop()
output
With ScrolledFrame it can look like this
I renamed Window into Question because it makes more sense
I use self.question and self.answer instead of self.text = [question, answer] to make it more readable.
I put classes and functions before root = tk.Tk() to make it more readable.
I use import tkinter as tk instead of from tkinter import * to make it more readable.
Question gets inner frame from ScrolledFrame and use as parent for LabelFrame. Other widgets use labelframe as parent.
BTW: you had entry = Entry(..).pack() which assign None to entry because pack()/grid()/place() returns None. I put pack() in next line and now I can get text directly from Entry (without StringVar)
Code
import tkinter as tk
from random import randint
# --- classes ---
class ScrolledFrame(tk.Frame):
def __init__(self, parent, vertical=True, horizontal=False):
super().__init__(parent)
# canvas for inner frame
self._canvas = tk.Canvas(self)
self._canvas.grid(row=0, column=0, sticky='news') # changed
# create right scrollbar and connect to canvas Y
self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview)
if vertical:
self._vertical_bar.grid(row=0, column=1, sticky='ns')
self._canvas.configure(yscrollcommand=self._vertical_bar.set)
# create bottom scrollbar and connect to canvas X
self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview)
if horizontal:
self._horizontal_bar.grid(row=1, column=0, sticky='we')
self._canvas.configure(xscrollcommand=self._horizontal_bar.set)
# inner frame for widgets
self.inner = tk.Frame(self._canvas, bg='red')
self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw')
# autoresize inner frame
self.columnconfigure(0, weight=1) # changed
self.rowconfigure(0, weight=1) # changed
# resize when configure changed
self.inner.bind('<Configure>', self.resize)
self._canvas.bind('<Configure>', self.frame_width)
def frame_width(self, event):
# resize inner frame to canvas size
canvas_width = event.width
self._canvas.itemconfig(self._window, width = canvas_width)
def resize(self, event=None):
self._canvas.configure(scrollregion=self._canvas.bbox('all'))
class Question:
def __init__(self, parent, question, answer):
self.parent = parent
self.question = question
self.answer = answer
self.create_widgets()
def get_input(self):
value = self.entry.get()
print('value:', value)
if value == self.answer:
print("Esatto. è " + self.answer)
self.label['text'] = "Esatto"
def create_widgets(self):
self.labelframe = tk.LabelFrame(self.parent, text="Domanda:")
self.labelframe.pack(fill="both", expand=True)
self.label = tk.Label(self.labelframe, text=self.question)
self.label.pack(expand=True, fill='both')
self.entry = tk.Entry(self.labelframe)
self.entry.pack()
self.button = tk.Button(self.labelframe, text="Click", command=self.get_input)
self.button.pack()
# --- main ---
root = tk.Tk()
root.title("Quiz")
root.geometry("400x300")
window = ScrolledFrame(root)
window.pack(expand=True, fill='both')
for i in range(10):
one = randint(1, 10)
two = randint(1, 10)
Question(window.inner, "Quanto fa {} + {} ?".format(one, two), str(one + two))
root.mainloop()

AttributeError: class Frame has no attribute 'StringVar'

So i have this code below. Ive tried a various form of how to get to work the StringVar, but nothing happened. And thats why a turned to you oh, god of stackoverflow. Pls show me how to make it throught. I have an input in Entry1 and I need to get this input into an sql ( ive cut it out because of its uninportant) and return the value of it and write it into Entry1 insted of the original input. Please Lord of SO halp me!
#!usr/bin/python
#-*- coding: utf-8 -*-
import os
import time
import mysql.connector
import getpass
import smtplib
from email.mime.text import MIMEText
global atado_kartya_input
global atvevo_kartya_input
from PIL import Image, ImageTk
#from Tkinter import Tk, Text, TOP, BOTH, X, N, LEFT
from Tkinter import *
from Tkinter import Tk as tk
from ttk import Frame, Style, Entry, Label
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
self.addbutton()
def addbutton(self):
b = Button( self, text= "Get!", width = 10, command= self.callback)
b.pack()
def callback(self):
#07561847
#tk()
atvevoText = Frame.StringVar()
atvevoText = atvevo(self.entry1.get()) #from the "atvevo" function it gets a name of a worker form an SQL statement
self.entry1.delete(0, 'end')
self.entry1.insert(0, atvevoText)
#self.entry1 = Entry(self, textvariable = atvevoText )
print(atvevoText)
def initUI(self):
self.parent.title("Pozi")
self.pack(fill = BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
lbl1 = Label(frame1, text = "ĂtadĂł kártyája", width = 30)
lbl1.pack(side = LEFT, padx=5, expand=True)
self.entry1 = Entry(frame1)
self.entry1.pack(side = LEFT, padx=5, expand=True)
frame2 = Frame(self)
frame2.pack(fill=X)
lbl2 = Label(frame2, text = "ĂrvevĹ‘ kártyája", width = 30)
lbl2.pack(side = LEFT, padx=5, expand=True)
entry2 = Entry(frame2)
entry2.pack(side = LEFT, padx=5, expand=True)
frame3 = Frame(self)
frame3.pack(fill=X)
lbl3 = Label(frame3, text = "ĂrvevĹ‘ kártyája", width = 30)
lbl3.pack(side = LEFT, padx=5, expand=True)
entry3 = Entry(frame3)
entry3.pack(side = LEFT, padx=5, expand=True)
frame4 = Frame(self)
frame4.pack(fill=BOTH, expand = True)
lbl4 = Label(frame4, text = "Title", width = 30)
lbl4.pack(side = LEFT, anchor=N, padx=5, pady=5)
txt = Text(frame4)
txt.pack(fill = BOTH, padx=5, pady=5, expand=True)
#Style().configure("TFrame", backgroung = "#333") # tframe háttérszinét beállítjuk90%
def main():
root = Tk()
root.geometry("550x450+300+300") # width x heigth + x + y (on screen)
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Update
I have to change in a way like that:
def callback(self):
#07561847
#tk()
atvevoText = StringVar()
number = self.entry1.get()
self.entry1.delete(0, 'end')
#self.entry1.insert(0, atvevoText)
self.entry1 = Entry(self, textvariable = atvevoText )
atvevoText = atvevo(number)
print(atvevoText)
*And with it i got nothing to back nor error nor the value :( *
Change
Frame.StringVar()
to
StringVar()
Since StringVar is a class inside Tkinter(not tested just googled)

Categories

Resources