The title basically says it. Right now I have the two panedWindows attached to the root window. I would like the windows to either lift() or lower() one panedWindow on top of the other when a button is pressed rather than the panedWindows being stacked on top of each other in the same window.
I also understand there may be a better way of implementing this sort of menu feature. If you know a better way, that would be great too.
I used .grid(row = 0) on both panedWindows. Then I called lift on the window I wanted to raise up and it worked.
Related
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.
I don't know How structure the GUI of my program...
I don't have big experience with GUI programming, i know all the widgets, the
geometry managers, the "object-oriented" method in Tkinter, but i don't understand
how combine all this things...
I want to create a program with an image in background where there is a button and if i press this button i switch in another page and the button disappears
Like this : https://moqups.com/iampirla#gmail.com/wyM7CyET/p:a80e8d902
How i can structure my code to do this?
You could use pack_forget() this removes the widget although allows you to use it later if you wish. You could do the first page and then use some code like below. To clear the page. This could then reference the next thing you wish to do using in this example question().
def answred():
nameLabel.pack_forget()
nameEntry.pack_forget()
nameButton.pack_forget()
classQuestion.pack_forget()
button1.pack_forget()
button2.pack_forget()
button3.pack_forget()
question()
You could this but not remove the background widgets
Suppose I have a lovely window full of tkinter widgets all set with a function. One of these many widgets is a button. When this button is pressed, I want to 'move on to the next screen'. The next screen is in another function(including all the widgets I want to appear on that screen). I have tried to simply run the next procedure from the button, but If it does run correctly, it only adds the widgets to the existing window, and you end up with both screen#1 and screen#2 jumbled together. I have a feeling I need to use destroy, but I'm not sure how to do such, as the only way I could come up with was to group all the widgets in window 1 together in a frame, and destroy it, but I cant get access to destroy the frame from within function #2, as its a variable only within function/window #1. Sorry if that's confusing, The other option is the source, but there's a ton of widgets and other windows in progress which leads me to believe that would be even more confusing.
The simplest thing is to have your function create a single frame, and then place all of the widgets in that frame. The frame can then be placed in the main window such that it fills the whole window. Then, to delete everything you simply need to delete that one frame.
Another way to "move on to the next screen" is to use this same method, but create all of the frames ahead of time. You can stack these frames on top of each other, and use lift and/or lower to determine which one is on top. The one on top will obscure the ones below.
For an example of stacking, see Switch between two frames in tkinter
As for the problem of frame2 not knowing how to destroy frame1, you simply need to pass in a reference to the existing frame when creating a new frame, or pass in a reference to a "controller" - a function that knows about all the frames. You then ask the controller to delete the current frame, and the controller will know what the current frame is.
A button calling a function that deletes all existing frames and rebuilds another sounds like a design flaw. The propensity for errors (forgetting to delete certain elements in some places of the code etc) is pretty large.
If you don't have an insane number of UI elements, I suggest creating them all at once, and hiding/showing various elements as necessary.
Take a look at this SO answer for how you might go about creating GUI elements that can be shown/hidden, and how the callback function might look.
Edit: If you really need to do it based on these functions, then I guess an alternative approach might be this:
Say 'top_frame' is the frame that includes all your widgets which you want to destroy when you run function #2. Change all of your GUI elements in function #1 so that when you create them, you explicitly pass them top_frame so that they have a link to it (self.top_frame = top_frame). This means your button will also have an attribute self.top_frame. You pass that as one of the arguments to function #2, and function #2 now can refer to top_frame and destroy it.
But definitely prone to error and probably slower due to all the creation/destruction of GUI elements. I recommend going through the code in the answer above when you have the time, it really is a much better solution.
for my board game, I need to press a certain button and after that, disable it (to prevent the user or the computer to place a "peace" in the same place). The problem I have with this is basically design-wise: as you would know, when a button is disabled in tkinter, it turns grayed-out, kinda "visually blocking" the piece I placed... Here is an image of what I'm talking about:
My question is, how would I disable a button, but keep it as if it wasn't disabled? I searched and the only answer I came about was basically getting rid of the button and replacing it with an image... If that's my best bet, how would I do this? the grid is created with a for loop that fills a list with buttons, and then displays them into a frame using the grid() method. This would look like:
Is there another way to achieve this with tkinter methods? I would rather not change the buttons to an image with a bound event, that seems too complicated given that I'd have to mess with my loop. Thanks!!
Thanks!
You can control the foreground and background colors with a variety of options, such as foreground, background, disabledforeground, and highlightbackground. Have you tried setting any of those to get the visual behavior you want?
You also have the option of disabling the callback, so the button will press but it won't do anything. To disable it, simply configure the command option to be None:
the_button.configure(command=None)
Turns out in order to disable the button but keeping its appearance, you have to disable its callback to make it "unresponsive" (as stated by #Bryan Oakley and #martineau, thanks!) and also change its 'relief' as to make it stay "fixed" (it kind of shifts into the bottom right corner, but that's good enough).
Imagine you have this generic button:
button = tkinter.Button(frame, height=0, bg='blue',\
activebackground='blue',width = 0, text = " ", image = self.blank, \
command=lambda row=row_index, \
column=column_index: \
self.button_clicked(row,column))
Now when you want to disable it but keeping its original appearance, you change the following attributes of the button:
button['command'] = 0 #this disables the callback
button['relief'] = 'sunken' #makes the button fixed
As easy as that! thanks!
How can I auto scroll for the scroll area? For example, when there is a new update instead of the view of the scroll area staying the same, I want to go down with the new text. Think of it as in a CMD console, when you type a command it autoscroll with the output.
I was just going to respond to the other answer, but I just didn't know the best way to phrase it in the space allotted.
QScrollArea's are very useful widgets to use when designing custom PyQt widgets - I use them often. Things like rollout widgets, card widgets, anything where you could be displaying multiple sub-widgets with the need for scrolling can be a very useful utility. I don't agree with the idea that a QScrollArea isn't much use on its own.
The QTextEdit answer solves the problem the developer was facing - but only because it so happens the question is really about that. If you're trying to scroll a text edit, go with that answer.
However, if you are searching for an answer to the actual question and come across this thread, then the way to scroll down a QScrollArea is by actually modifying the scrollbar's value.
area = QScrollArea(parent)
vbar = area.verticalScrollBar()
vbar.setValue(vbar.maximum())
If you want to scroll to particular areas or anything (like implementing the ensureCursorVisible) then you want to take the location on the area's widget that you want to scroll to, figure out the percentage of the height of it, and apply that value to the vertical scrollbar. (Pseudocode)
Use QTextEdit.moveCursor to set the location you want to scroll to, and then use QTextEdit.ensureCursorVisible to scroll to it:
textedit.moveCursor(QtGui.QTextCursor.End)
textedit.ensureCursorVisible()