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()
Related
I'm making a game for myself. The problem I am stuck with is that for some reason the program crashes after putting some objects on a canvas and deleting them. More in-depth:
I have the frame FrameMain with a canvas in it.
I have the frame FrameLower with a canvas in it. Also an image on canvas.
I am placing and deleting few FrameLower as FrameMain.obj on FrameMain canvas with FrameMain.__placeFrames() method.
The problem is that it seems like memory somewhere does not get cleared completely when I delete FrameMain.obj. So it leads to the program crashing after a while, depending on how many times FrameLower is placed and how many images it has on its canvas.
I have enough free RAM, as you can predict, ~6GB, so that's not a problem.
What I really want to understand is why it is crashing if there's free memory to store the objects and why those objects do not get deleted completely.
What I really want to do is get rid of this crash. In the following simplified example, I am placing 10000 frames, but in real program 100 of them is enough to kill my game - they are heavily filled with images.
(For this code to work as-is, any img.gif file in the root directory is needed)
from tkinter import *
class FrameMain(Frame):
def __init__(self,master):
super().__init__(master,height=100,width=100,bg='black')
self.grid()
self.canvas=Canvas(self,height=100,width=100,bg='white')
self.canvas.grid()
self.__placeFrames(10000)
def __placeFrames(self,number):
for counter in range(0,number):
self.obj=self.canvas.create_window(50,50,window=FrameLower(self.canvas))
self.canvas.delete(self.obj)
del self.obj
class FrameLower(Frame):
def __init__(self,master):
super().__init__(master,height=50,width=50,bg='red')
self.canvas=Canvas(self,height=50,width=50,bg='blue')
self.canvas.grid()
self.img=PhotoImage(file='img.gif')
self.canvas.create_image(0,0,image=self.img)
def Run():
root=Tk()
frameMain=FrameMain(root)
root.mainloop()
Run()
When you do self.canvas.delete(self.obj), all you're doing is deleting the object from the canvas. The frame that is associated with the object will not be destroyed. If you want to destroy the window object, you need to explicitly call destroy on it.
The canvas also has some known limitations when creating thousands upon thousands of items. It doesn't recycle canvas item ids, so they continue to take up a tiny amount of memory even if the canvas object itself has been removed. One solution to this is to not delete canvas items, but rather move them off-screen or configure them to be hidden when they are not needed, and then reconfigure them instead of creating a new item.
I am currently working on a project using Python and tkinter.
The problem is that I don't know what's the proper way to display multiple windows, or screens, I don't know how to call them. Let me explain better.
When the application starts the login screen appears. After that, if I click register, I want to go to the register screen, but I don't want it to be a separate window (I don't want to have 2 windows displayed at the same time), but rather another window with different content ?!
How should I handle properly this situation? Create a second window using Toplevel and hiding the first (can I do that?) or changing the widgets of the first?
Code I've written so far
You can do that- just call window.withdraw() on the Toplevel you need to hide after creating a new Toplevel. Changing the widgets in the first is also an option- if you like, you could always try a Notebook widget and disable manual flipping or just put each "screen" in a frame and grid_ or pack_forget them to remove them from the window.
So I've been working on a group project, some of use used pack and others used grid as a layout manager, I'm making the part of the application that puts everyones code together.
I've been working on a UI using pack, and what I want it to do is when I click on a button, a new tk.Tk() window is launched which then runs its code that is managed by grid.
Here is a snipped of the code to try and show you what I'm doing, I keep getting the error "cannot use the geometry manager grid inside . which already has slaves managed by pack"
def launchQuest(self, questType):
if(questType == "ham"):
ham = tk.Tk()
ham.configure(background='white')
app = HM(ham)
ham.mainloop()
If you need to see more code just ask, the whole class is around 400 lines so far but I don't think it is relevant.
Any help would be great!
Thanks!
Based on my first comment above, the answer is:
There should be only one Tk() root window. If you want other windows,
use Toplevel widget.
Only one type of positioning (grid, pack, or place) can be used at a time, within a container. Tk() gives you a window (Toplevel) which you use to contain other widgets, some of which can be containers themselves, like Frame, for example. You can pack two frames into a window, but you could not pack one frame and place another into the same window. This limitation only applies one level deep – you could place a frame, and then pack a frame inside that, and then grid inside that, if you wanted. It doesn't matter what method was used to position the container, only at the level of things directly contained by that container.
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.
I want to make a new PyQt window show up and hide the current window when I click a button. After playing around for hours, I haven't found a good way to do this.
When I try to show a new QDialog and hide the current one, the program closes. It works if another window is open. I believe this is because it is viewing the last window as closing and terminates, or maybe the new QDialog is falling off the stack.
My current method involves storing the QDialog as a variable in the current dialog, then showing it and hiding current dialog. This seems like a total hack, though.
Example below:
def _createQuestion(self):
# initialization of the UI and everything goes on in the constructor
self.dialog = QuestionBanks()
self.dialog.show()
self.hide()
Is there a better way of switching a single window to a distinct different single window in PyQt4?