How to show command addBox using button in the same frame - python

I am trying to create a NoteBook containing Tabs. One the these Tabs contains a Button that when clicked creates an EditText with this line of code
btn1 = ttk.Button(page1, text = "Add Site Code", command=addBox)
The problem is when I click this button it creates the EditText outside the frame like this
I need to show the EditText below the button inside the frame
However this is my code
from tkinter import *
import tkinter.ttk as ttk
import background as background
#------------------------------------
def addBox():
print ("ADD")
ent = Entry(root)
ent.pack()
all_entries.append( ent )
#------------------------------------
all_entries = []
root = Tk()
root.title('Notebook Demo')
# set the configuration of GUI window
w = 600
h = 400
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
x = (sw - w) / 2
y = (sh - h) / 2
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.config(background = '#A9A9A9')
rows = 0
while rows < 50:
root.rowconfigure(rows, weight=1)
root.columnconfigure(rows, weight=1)
rows += 1
nb = ttk.Notebook(root)
#nb.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW')
page1 = ttk.Frame(nb)
nb.add(page1, text='RDT & On-Air')
nb.pack(expand = 1, fill = "both")
page2 = ttk.Frame(nb)
nb.add(page2, text='Existing Sites')
nb.pack(expand = 1, fill = "both")
page3 = ttk.Frame(nb)
nb.add(page3, text='All Data')
nb.pack(expand = 1, fill = "both")
btn1 = ttk.Button(page1, text = "Add Site Code", command=addBox)
btn1.pack()
root.mainloop()

The problem is that you add the new Entry having root as a parent at line 9:
ent = Entry(root)
You should use the actual frame you want the entry to be in as a parent widget. Substitute root with page1
def addBox():
print ("ADD")
ent = Entry(page1)
ent.pack()
all_entries.append( ent )

Related

Reusing frame widget in canvas after canvas.delete("all") doesn't work

I have created a frame within a canvas where I place checkbuttons with a mouse click. Selecting another radiobutton I run the command canvas.delete("all") to clear the canvas (and the frame with checkbuttons) and then create the frame again to continue placing checkbuttons. The frame gets created, but i can't place the checkbuttons anymore (I get no error messages either). Anybody knows why?
from tkinter import *
root = Tk()
top_canvas = Canvas(root,width=676,height=768, bg='light blue')
top_canvas.pack()
frame = Frame(top_canvas, bg='light grey')
main_frame = top_canvas.create_window(500, 780, height = 1600, width = 600, window = frame)
def place_checkbutton_in_canvas(e): # order to insert the checkbutton
xx = e.x
yy = e.y
buttons = Checkbutton(frame)
buttons.place(x=xx, y=yy)
def place_checkbutton(): #to run when checkbutton is selected. Now the checkbutton will be placed where mouse clicked if choose_line is selected
frame.bind('<Button-1>', place_checkbutton_in_canvas)
def clear_canvas():
top_canvas.delete("all")
frame = Frame(top_canvas, bg='magenta')
main_frame = top_canvas.create_window(500, 780, height=1600, width=600, window=frame)
chosen_option = IntVar()
choose_checkbutton = Radiobutton(root, text = "place checkbutton", variable=chosen_option, value = 1, command = place_checkbutton)
choose_checkbutton.place(x=10, y=10)
clear_button = Radiobutton(root, text = "clear everything", variable=chosen_option, value = 2, command = clear_canvas)
clear_button.place(x=10, y=100)
root.mainloop()
There is no need to delete all the items on canvas.You could use a list to save all of the checkbuttons,and use .destroy() to "delete" them:
from tkinter import *
root = Tk()
top_canvas = Canvas(root,width=676,height=768, bg='light blue')
top_canvas.pack()
root.checkbutton_list = [] # initial a list
frame = Frame(top_canvas, bg='light grey')
main_frame = top_canvas.create_window(500, 780, height = 1600, width = 600, window = frame)
def place_checkbutton_in_canvas(e): # order to insert the checkbutton
xx = e.x
yy = e.y
buttons = Checkbutton(frame)
buttons.place(x=xx, y=yy)
root.checkbutton_list.append(buttons) # append the checkbutton to the list
def place_checkbutton(): #to run when checkbutton is selected. Now the checkbutton will be placed where mouse clicked if choose_line is selected
frame.bind('<Button-1>', place_checkbutton_in_canvas)
def clear_canvas():
for i in root.checkbutton_list:
i.destroy() # destroy all the checkbuttons in the list
root.checkbutton_list = [] # init it again
chosen_option = IntVar()
choose_checkbutton = Radiobutton(root, text = "place checkbutton", variable=chosen_option, value = 1, command = place_checkbutton)
choose_checkbutton.place(x=10, y=10)
clear_button = Radiobutton(root, text = "clear everything", variable=chosen_option, value = 2, command = clear_canvas)
clear_button.place(x=10, y=100)
root.mainloop()
If you really want to use it with .delete(ALL).You need to change the parent container of the checkbutton.I use root.frame to cover the previous frame.Like:
from tkinter import *
root = Tk()
top_canvas = Canvas(root,width=676,height=768, bg='light blue')
top_canvas.pack()
root.frame = Frame(top_canvas, bg='light grey')
main_frame = top_canvas.create_window(500, 780, height = 1600, width = 600, window = root.frame)
def place_checkbutton_in_canvas(e): # order to insert the checkbutton
xx = e.x
yy = e.y
buttons = Checkbutton(root.frame)
buttons.place(x=xx, y=yy)
def place_checkbutton(): #to run when checkbutton is selected. Now the checkbutton will be placed where mouse clicked if choose_line is selected
root.frame.bind('<Button-1>', place_checkbutton_in_canvas)
def clear_canvas():
top_canvas.delete("all")
root.frame = Frame(top_canvas, bg='magenta')
main_frame = top_canvas.create_window(500, 780, height=1600, width=600, window=root.frame)
chosen_option = IntVar()
choose_checkbutton = Radiobutton(root, text = "place checkbutton", variable=chosen_option, value = 1, command = place_checkbutton)
choose_checkbutton.place(x=10, y=10)
clear_button = Radiobutton(root, text = "clear everything", variable=chosen_option, value = 2, command = clear_canvas)
clear_button.place(x=10, y=100)
root.mainloop()

How to make multiple windows through a loop?

I'm a beginner python coder and I'm trying to make a GUI where you can enter information for multiple semesters. Once the user inputs the number of semesters, I want to ask about each semester individually but when I use a loop to do this, all of the windows open at once. Is there a way to put them into a sequence?
this is what I have so far
def createSemesterWin(self, numSemesters):
for x in range(numSemesters):
semesterWin = Toplevel()
semesterg = SemesterGUI(semesterWin, x+1)
semesterWin.mainloop
Something like this should get you on your way:
from Tkinter import *
## Define root and geometry
root = Tk()
root.geometry('200x200')
# Define Frames
win1, win2, win3 = Frame(root, bg='red'), Frame(root, bg='green'), Frame(root, bg='blue')
# Configure Rows
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
# Place Frames
for window in [win1, win2, win3]:
window.grid(row=0, column = 0, sticky = 'news')
# Raises first window 'To the top'
win1.tkraise()
# Function to raise 'window' to the top
def raise_frame(window):
window.tkraise()
# Page1 label / button
l1 = Label(win1, text = 'This is Page1').pack(side=TOP)
P1 = Button(win1, text = 'Next Page', command = lambda:raise_frame(win2)).pack(side=BOTTOM)
# Page2 label / button
l2 = Label(win2, text = 'This is Page2').pack(side=TOP)
p2 = Button(win2, text = 'Next Page', command = lambda:raise_frame(win3)).pack(side=BOTTOM)
# Page3 label / button
l3 = Label(win3, text = 'This is Page3').pack(side=TOP)
p3 = Button(win3, text = 'Next Page', command = lambda:raise_frame(win1)).pack(side=BOTTOM)
root.mainloop()
Let me know what you think!

changing a buttons colour when that button clicked

I am making a maze where the user enters the dimensions and can then click on a button to change the colour of that button to black. What i eventually want is to be making an ai which will try to navigate the maze the user created with the black rectangle the ai not being allowed to go on.
The problem is i dont know how to change the properties of the button clicked as due to a nested loop being used for creation they all have the same name.
from tkinter import *
import tkinter as tk
from tkinter.ttk import Combobox,Treeview,Scrollbar
class MainMenu(Frame):
def __init__(self, master):
""" Initialize the frame. """
super(MainMenu, self).__init__(master)
self.grid()
self.frame1 = tk.LabelFrame(self, text="entering diemsions", width=300, height=130, bd=5)
self.frame1.grid(row=0, column=0, columnspan=3, padx=8)
self.frame2 = tk.LabelFrame(self, text="creating maze", width=300, height=130, bd=5)
self.frame2.grid(row=1, column=0, columnspan=3, padx=8)
self.create_GUI()
def create_GUI(self):
self.width_lbl = Label(self.frame1, text = "width:")
self.width_lbl.grid(row = 1 , column = 1)
self.width_txt = Entry(self.frame1)
self.width_txt.grid(row = 1, column = 2)
self.getdimensions_btn = Button(self.frame1, text = "enter dimensions",command = lambda:self.createmaze())
self.getdimensions_btn.grid(row = 1 , column = 3)
self.height_lbl = Label(self.frame1, text = "height:")
self.height_lbl.grid(row = 1 , column = 4)
self.height_txt = Entry(self.frame1)
self.height_txt.grid(row = 1, column = 5)
def createmaze(self):
width = int(self.width_txt.get())
height = int(self.height_txt.get())
for widthcount in range (width):
for heightcount in range(height):
self.maze_btn = Button(self.frame2, text = "",width = 4, height = 2)
self.maze_btn.grid(row = heightcount , column = widthcount)
self.maze_btn.bind("<Button-1>", self.disablebtn)
def disablebtn(self,event):
grid_info = event.widget.grid_info()
col = grid_info["column"]
col = int(col)
row = grid_info["row"]
row = int(row)
root = Tk()
root.title("hi")
root.geometry("500x500")
root.configure(bg="white")
app = MainMenu(root)
root.mainloop()

Creating new entry boxes with button Tkinter

How do i make the button to add two box (side by side) below when it is being clicked as the user decided to put more input?
def addBox():
labelframe = Tkinter.Frame()
labelframe.bind("<Add Input>", callback)
labelframe.pack()
labelframe = Tkinter.Frame()
labelFrom = Tkinter.Label(labelframe, text= "from")
labelFrom.grid(column=1, row=0)
e = Tkinter.Entry(labelframe)
e.grid(column=1, row=1)
labelTo = Tkinter.Label(labelframe, text= "to")
labelTo.grid(column=2, row=0)
e2 = Tkinter.Entry(labelframe)
e2.grid(column=2, row=1)
labelframe.pack()
addboxButton = Button( root,text='<Add Time Input>', fg="Red",command="addBox")
addboxButton.pack(side=Tkinter.TOP)
This is example how to add Entry.
Probably you get problem because you use quotation marks in command=addBox
Because you will have to get values from entries you have to remeber them on list.
I add button which print text from entries.
from Tkinter import *
#------------------------------------
def addBox():
print "ADD"
ent = Entry(root)
ent.pack()
all_entries.append( ent )
#------------------------------------
def showEntries():
for number, ent in enumerate(all_entries):
print number, ent.get()
#------------------------------------
all_entries = []
root = Tk()
showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()
addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()
root.mainloop()
#------------------------------------
EDIT:
Example with boxes side by side.
I use new frame to keep entries side by side using grid().
This way I don't mix grid() with pack() in main window/frame.
I use len(all_entries) to get number of next free column.
from Tkinter import *
#------------------------------------
def addBox():
print "ADD"
# I use len(all_entries) to get nuber of next free column
next_column = len(all_entries)
# add label in first row
lab = Label(frame_for_boxes, text=str(next_column+1))
lab.grid(row=0, column=next_column)
# add entry in second row
ent = Entry(frame_for_boxes)
ent.grid(row=1, column=next_column)
all_entries.append( ent )
#------------------------------------
def showEntries():
for number, ent in enumerate(all_entries):
print number, ent.get()
#------------------------------------
all_entries = []
root = Tk()
showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()
addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()
frame_for_boxes = Frame(root)
frame_for_boxes.pack()
root.mainloop()
#------------------------------------
EDIT:
Another example:
from Tkinter import *
#------------------------------------
def addBox():
print "ADD"
frame = Frame(root)
frame.pack()
Label(frame, text='From').grid(row=0, column=0)
ent1 = Entry(frame)
ent1.grid(row=1, column=0)
Label(frame, text='To').grid(row=0, column=1)
ent2 = Entry(frame)
ent2.grid(row=1, column=1)
all_entries.append( (ent1, ent2) )
#------------------------------------
def showEntries():
for number, (ent1, ent2) in enumerate(all_entries):
print number, ent1.get(), ent2.get()
#------------------------------------
all_entries = []
root = Tk()
showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()
addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()
root.mainloop()
#------------------------------------
First of all, the indentation is a whole mess, so I don't know where does the addBox function end ..
Second, I don't think you need a button, I suppose a checkbutton will do the same thing and it's also more common and familiar to users, I once had this problem and I simply created an entry box and put above it a label indicating that it's optional, and as for code, I simply ignored it if it was empty and verified the input if I found any input ..Howerver, that was for only one entry box, and you probably will need something more complex ..
See this ..
class OptionsView(Frame):
"""Frame for options in main window"""
def __init__(self, x, y, parent):
Frame.__init__(self, parent)
self.x = x
self.y = y
self.placed = False
self.hidden = False
self.btn = Button(self, text = 'Button attached to the frame ..', command = lambda: print('Button in frame clicked ..')).pack()
def pack(self):
self.place(x = self.x, y = self.y)
self.placed = True
def toggle_view(self):
if self.hidden:
self.pack()
self.hidden = False
else:
self.place_forget()
self.hidden = True
if __name__ == '__main__':
def m_frame():
if val.get() and not options_frame.placed:
print('Showing Frame ..')
options_frame.pack()
else:
print('Toggling Frame ..')
options_frame.toggle_view()
root = Tk()
root.geometry('300x400+500+600')
root.title('Testing Hiding Frames ..')
options_frame = OptionsView(200, 300, root)
val = BooleanVar(value = False)
Checkbutton(text = 'View more Options ..', var = val, command = m_frame).place(x=root.winfo_height()/2, y=root.winfo_width()/2)
try: root.mainloop()
except e: showerror('Error!', 'It seems there\'s a problem ..', str(e))
Ofcourse you can also modify the length and the x axis of the main window if you want to be more realistic ..

Run two Commands when you hit a Tkinter Button

I would like a Tkinter button to clear my current Grid, and also go to a function, and I cannot think of how to do it. I have a grid that is a menu, and in another function I have the code for what was just opened by hitting the button.
in short I want a button, when clicked to do this: self.studyGuide and this: self.frame.grid_forget.
Here is my code:
from tkinter import *
class App:
def __init__(self,master):
frame = Frame(master)
frame.grid()
self.sg = Button(frame, text = "Study Guide", command = self.buttonStart, fg="red")
self.sg.grid(row = 2, column = 1)
self.quizlet = Button(frame, text = "Quizlet", command = self.quizlet)
self.quizlet.grid(row = 2, column = 2)
self.flashcard = Button(frame, text = "Flash Cards", command = self.flashcard)
self.flashcard.grid(row = 2, column = 3)
self.quitButton = Button(frame, text = "Quit", command = frame.quit)
self.quitButton.grid(row = 3, column = 2)
self.text = Label(frame, text = "Social Studies Study Tool")
self.text.grid(row = 1, column = 2)
def buttonStart(frame):
self.studyGuide()
self.frame.grid_forget()
def studyGuide(self):
studyGuide = Frame()
studyGuide.pack()
self.sgText = Label(studyGuide, text = "This is not real.")
self.sgText.pack()
def quizlet(self):
print("Quizlet")
def flashcard(self):
print("Flashcards")
root = Tk()
app = App(root)
root.mainloop()
Simply, have the callback passed to the Button constructor call the other 2 functions:
def foo(self):
self.studyGuide()
self.frame.grid_forget()
root = Tk()
my_button = Button(root, text="I'm doing stuff", command=foo)

Categories

Resources