I have a tkinter GUI that, when opened, is an empty widget with a menu bar on top. Clicking on the options on the menu causes for text boxes, more buttons and more menus to appear in the widget. My problem is that everything overlaps.
I need an easy way to delete everything that is currently there, like a "clear window" option.
I've tried packing everything into a frame and then destroying a frame but, for some reason, it's not working.
Any suggestions?
Ideally, I would make something that checks to see if there is anything (button, text box, menu) in a designated space, and it would delete it all before creating the new widget attributes.
The Problem I was having was fixed by creating a new frame within each function and having the code destroy any previously existing frames with Frame.destroy().
My second problem, where widgets within my frame were not, appearing was being caused by how Tkinter frames automatically resize to fit the original widgets. Therefore, when I added widgets to the frame, the frame remained the size of the first widget and didn't show the new buttons. I used frame.pack_propagate(0) to force the frame to remain the specified size.
Related
I was trying to write a program that has each individual photo from a file shown as a Button, which worked up until I tried to add a Scrollbar to the Canvas in case there were more buttons than the screen could fit. But for some reason, all the buttons disappeared off the screen, and the scrollbar would be small, in the middle of the screen and not at all where I wanted it. The lines I used for making the scrollbar worked in a different part of the program before, but now they are not. I included pictures of what it looks like before and after the change
photoMenu=tk.Tk()
photoMenu.title("Insta-Copy")
photoMenu.geometry("1720x1080")
photoMenu.resizable(0,0)
photoCanvas=tk.Canvas(photoMenu,width=1720,height=900)
vsb=tk.Scrollbar(photoCanvas)
vsb.pack(side=RIGHT,fill=Y)
photoCanvas.config(yscrollcommand=vsb.set)
photoCanvas.pack()
vsb.config(command=photoCanvas.yview)
x=-100
y=50
y2=165
for file in pathList:
x+=150
fileName=file.replace(sourceDirectory+"/","")
with open ("InstaCopyFiles.txt") as fileList:
if file in fileList.read(): #File has already been copied before
tk.Label(photoCanvas,text=fileName,fg="red").place(x=x,y=y2)
else:
tk.Label(photoCanvas,text=fileName).place(x=x,y=y2)
photoButton=tk.Button(photoCanvas,image=photo,command=partial(photoSelected,file))
photoButton.image=photo
photoButton.place(x=x,y=y)
if x>=1500:
x=-100
y+=140
y2+=140
They disappeared because you put the scrollbar inside the canvas. That, combined with the fact you didn't use any options when calling pack, cause the canvas to shrink to fit the scrollbar.
It's not normal to put scrollbars inside the canvas. Typically you would use a frame, and make both the canvas and the scrollbars children of the frame.
Also, it's a bit unusual to put the image in a label and then call place on the label to put it inside a canvas. The canvas natively supports images, so you can put them directly on the canvas. If you use place, you won't be able to scroll the images because you can only scroll canvas items (items created with the create_* methods).
I've got a massive program that works flawlessly EXCEPT that I'm an idiot and all of the information is displayed via labels on the master/root window. When I remove one of the labels from the database it is pulling from it still shows the text as if the information still exists. If I close and reopen the entire program it loads the information correctly SO...
Rather than basically rewriting everyhing, within my update function I've placed:
global master
master.destroy()
master = Tk()
master.title('Encounter Manager')
And now the phantom information no longer shows, but it does exactly what you'd expect and closes/reopens the window. Is there a way to accomplish this without actually closing and reopening the window? It's annoying but still preferred to seeing the phantom information that I had since removed....
One solution is to add frame in the root window to hold the labels. So, root window -> frame -> labels. Then, you can destroy the frame and start over.
Another solution would be to iterate over the children of the root window and destroy them one by one:
for widget in root.winfo_children():
widget.destroy()
i am using python 3, GUI, tkinter.
i use grid method (row and column) to create a table containing info, a button is placed in the end of each row. if someone press that button, the whole row will disappear/destroy and next row will replace it, which function should i use to achieve that?
The grid_forget() method will cause the grid geometry manager to stop managing a widget. So if you put your widgets for a row into a frame and grid that, you can grid_forget the frame to have all the widgets in the frame removed from display together. However, you might want to investigate the Ttk treeview which can display tabular information or the tktable package (see this answer).
I must be missing something obvious, I have two frames in my Tkinter program, each with a bunch of labels in a grid layout. I want to bind the mouseclick to one of them but not the other. I currently use
root.bind("<Button-1>", mouse_function)
but that also triggers if I click in the other frame. I assumed that using
schedule_frame.bind("<Button-1>", mouse_function)
would work but then I get no response anywhere.
The function I am calling is:
def mouse_function(event):
y = event.widget.grid_info()['row']
x = event.widget.grid_info()['column']
widgets[(y, x)].configure(state="active")
shiftSelection(y,x)
When you bind to the root window, that binding applies to all widgets in that root window. That is why it triggered for either frame. This is standard behavior for tkinter.
When you move the binding to the frame, it stopped working because the frame never saw the event. When you click on the label, it is the label that sees the binding, not the frame (unless you click in the space between labels)
There are at least three ways to solve this problem. One is that you can put the binding on the labels rather than the frame. Another is to keep the binding on the root window, but within the function check to see if the widget is a child of that one frame.
A third solution involves changing the bind tags for the labels. For an in depth example see this answer: https://stackoverflow.com/a/32771893/7432
I have a frame which I use as the main form (mainFrame), it inherits from mainFrameBase, which inherits from wxFrame.
It has a "close" system button. When it is pressed the app shuts down. All very much to my liking.
I inherit another frame from mainFrameBase (progScreen). When a button is pressed, the progScreen is shown. When I click its system close button, the form does not close.
What I want to achieve with this setup is that you can click a button on the main frame and a slightly different view of the main frame is shown to allow the user to "progam" certain buttons.
By the way, I'm using WXFormBuilder (excellent program) to create the screens.
What I would do is create two panels with the controls you want, one for the regular screen and one for the programming screen. Then when you want to switch, you hide one panel and show the other. That way, both screens are contained in one frame that when closed, exits the program. I actually have a tutorial that is similar to this here:
http://www.blog.pythonlibrary.org/2010/06/16/wxpython-how-to-switch-between-panels/
Hope that helps!