What I need to know is if there is a way to put a widget into a different grid cell after already gridding it. The reason I need to do this is because I am making a tkinter program in python with multiple stacked frames, and I made a class that inherits from the Frame class called ParentFrame. All other frames in the program inherit from ParentFrame. Part of its function is to automatically grid all slave frames within it.
Here's where the problem comes in. I want one single slave frame to be positioned differently, but it has already been positioned by ParentFrame in the grid. Is it possible to reconfigure the slave frame's location after already being in the grid?
Thanks.
Yes, there is a way to put it in a different grid cell. Just call grid again with different parameters. There is no need to remove it first.
...
my_button.grid(row=0, column=1, ...)
...
my_button.grid(row=1, column=3, ...)
...
Related
I want to eliminate strange extra space that seems to resist any size tweaking in my layout when using grid() alone, but calling in pack() sometimes make things worse: The GUI simply disappear entirely!
I read a few eye-opening layout answers from #Bryan Oakley such as:
When to use pack or grid layouts in tkinter?
and
Tkinter: grid or pack inside a grid?
but when I get down to write my own stuff, I still often have troubles.
My understanding:
I must have a Frame to fill the root window, otherwise there'd be no hope to fill the extra space in the window, however I tweak widgets alone.
For all the child widgets sitting inside a common parent Frame, I must use either pack() or grid() but not both.
When using grid() in a Frame, it's mandatory to specify Frame.grid_rowconfigure() and .grid_columnconfigure() with non-zero weight arguments. Otherwise, nothing would show up.
It's thus possible to have the main Frame using pack(), but its immediate child Frames all using grid(); Inside each of these child Frames on the grid, we could then pack() their own child widgets. In other words, we could interleave grid() and pack() by "regions" or container hierarchy levels, but never mix them in the same container: The only restriction.
By a careful weight design, I could fill a horizontal space in a parent Frame with a child Frame full of widgets laid out horizontally, e.g., all widgets use grid(sticky='nsew'), and the child Frame uses pack(side='top', fill='both', expand=True).
If my understanding was correct, then I could never figure out why #5 couldn't work for me, e.g., there is always unused extra space towards the right end of my horizontal child Frame inside the main Frame of the root window.
UPDATE 2
I figured it out. #5 didn't work for me because I forgot to specify .grid_columnconfigure(0, weight=1) in the main Frame before using grid(). My bad! Case closed.
UPDATE
I'm on macOS High Sierra, running python 3.6.4 Homebrew.
In what cases Tkinter's grid() cannot be mixed with pack()?
In all cases, you cannot use both grid and pack for widgets that have a common master. Within a master, all direct children must use the same geometry manager. Within an application as a whole, you can mix pack and grid all you want as long as you follow that one rule that you can't use them both for widgets that have the same parent.
I must have a Frame to fill the root window, otherwise there'd be no hope to fill the extra space in the window, however I tweak widgets alone.
This is not correct. You can easily fill all of the space in the root window without using a frame.
For all the child widgets sitting inside a common parent Frame, I must use either pack() or grid() but not both.
That is correct. The third option is to use place, though it's rarely the best choice.
When using grid() in a Frame, it's mandatory to specify Frame.grid_rowconfigure() and .grid_columnconfigure() with non-zero weight arguments. Otherwise, nothing would show up.
That is not true -- configuring rows and columns to have a non-zero weight isn't mandatory. It's usually a best practice, but it's not required in order for widgets to show up. The weight only applies to how grid manages extra space. Any widgets with a non-zero size should appear whether you use weights or not.
It's thus possible to have the main Frame using pack(), but its immediate child Frames all using grid()
Correct.
By a careful weight design, I could fill a horizontal space in a parent Frame with a child Frame full of widgets laid out horizontally, e.g., all widgets use grid(sticky='nsew'), and the child Frame uses pack(side='top', fill='both', expand=True).
That is correct.
I'm try to use asciimatics for a TUI, which will be the front end for a test frame work. The TUI should have some parameters that are constant and are common for all tests, and another section where there are parameters based on the selected test.
I'm pretty sure I can get this to work if I create a main frame for the common parameters, and frames for each individual test, then, based on the selected test open the specific test frame when the user clicks a button to edit test parameters.
However, I would much rather have the test parameters shown along side the common ones. I was thinking about putting the second frame inside a layout, and swapping it on the fly when the selected test is changed. Is this possible to do with asciimatics?
Thanks,
o
As documented in https://asciimatics.readthedocs.io/en/stable/widgets.html#layouts-in-more-detail, a Layout belongs inside a Frame. You can't put a Frame in side a Layout.
However, there is no reason you can't just use two Frames next to each other. Simply create them with the right size and locations to be side by side.
I am trying to build a grid of frames in each there is a matplotlib figure.
When I resize the window the figure remain with fix size and are not resizing to fit the empty space.
Is there a way to make the figure change its size according to the canvas (hopefully that it does change with the window size)?
This is how I do the embedding in each frame:
self._figure = pyplot.figure(figsize=(4,4))
self._axes = self._figure.add_subplot(111)
self._canvas = FigureCanvasTkAgg(self._figure, master=self._root)
self._canvas.get_tk_widget().grid(row=1,column=1,rowspan = 4)
This is most likely related to this question. The gist is that there are two parts to making a Tk grid cell grow:
Use the sticky keyword when applying grid to your widget, e.g., widget.grid(..., sticky=Tkinter.NSEW (Python 2.7) to make widget be able to grow in all four directions. See this documentation for more details.
Tell the parent/master to make the respective column/row grow when resizing by calling parent.grid_columnconfigure(...) and/or parent.grid_rowconfigure(...) with the desired row, column, and weight keyword. E.g., parent.grid_columnconfigure(col=0, weight=1) makes the first column take all available space (as long as there are no other columns, or they have not been similary configured). See the grid_columnconfigure documentation and the grid_rowconfigure documentation for more details, e.g., about how the weights affect multiple columns/rows.
This page contains many more details about grid layouts.
I would like to know if it is possible and how to create an overlaying frame (or any other widget) at a fixed position that would overlaying the content of the MainWindow with PyQt4.
The idea is to get a html-like render we can get with position: fixed or position: absoute. From what i know, all widgets have to inherit from the MainWindow's widget but is there a way to change this behavior or any way to simulate a widget with such level ?
Thank you
I suppose your problem is to insert an object inside a frame that uses a layout, and avoid respecting that layout.
I am afraid the only thing i can come up with in your situation is either to avoid using layouts altogether (but that's very uncomfortable) or to extend a layout class and place the frame outside of the layout.
To make your frame stay on top, look for z-order.
http://qt-project.org/search/tag/z-order
What's the main difference between the Tkinter geometry managers grid and pack?
What do you use for your projects ?
If grid is better to align object, what the main purpose of pack?
grid is used to lay out widgets in a grid. Another answer says it "overlays a graph" which is a bit of a misnomer. It doesn't overlay anything, it merely arranges widgets along row and column boundaries. It is great for creating tables and other structured types of layouts.
pack lays things out along the sides of a box. It excels at doing layouts where everything is on a single row or in a single column (think rows of buttons in a toolbar or dialog box). It's also useful for very simple layouts such as a navigator on the left and a main work area on the right. It can be used to create very complex layouts but it gets tricky until you fully understand the packing algorithm.
You cannot use both grid and pack with widgets that have a common parent. Your app may work but it is much more likely to get into an infinite loop as each manager tries to layout the widgets, then the other notices the widgets change size and try to adjust, etc. etc.
The third manage is place. Place is great for doing either absolute positioning (ie: place widget at a given x/y) or relative (eg: place a widget on the right edge of some other widget).
While you cannot mix grid and pack within the same container (a container is typically a frame), you can use both grid and pack within a single application. This is very, very common since each has strengths and weaknesses. I use both on a regular basis.