hi is there any way to change width and height of widget even if there's widget?
i have code like this
form = Tk()
form.geometry("500x500")
def click():
global frame
frame.config(height = 0 ,width = 0)
frame = LabelFrame(form , text = "vaaja")
frame.place(x = 20 , y = 30)
Label(frame, text ="1").grid(row = 0,column = 0 )
Label(frame, text = "2").grid(row = 1 ,column = 0 )
Button(form , text="Click", command = click).place(x = 200 , y = 200)
form.mainloop()
and when I click the button the size of the frame is the same ( I'cant use grid_forget() for labels and then change the size of frame)
Because you are using place, you have two solutions: you can use place to set the width and height to zero, or you can turn geometry propagation off.
Using place to set the width and height
place allows you to define the width and the height of the placed widget, so in your click function you can do this:
def click():
frame.place_configure(width=0, height=0)
Turning geometry propagation off
A frame is resized to fit its contents by something called "geometry propagation". If you turn this off, you can control the size of the frame with the width and height options of the frame itself. Usually it's better to let Tkinter decide the size for you, but sometimes there's a need to have an explicit size, which is why it's possible to turn geometry propagation off.
Since you are using grid to manage the widgets internal to the frame, you need to use grid_propagate(False) to turn geometry propagation off for that frame:
frame.grid_propagate(False)
By doing so, you're responsible for setting the initial width and height of the widget, though you could leave propagation on to get the initial size, then turn it off with the button click in order to work around that issue.
There's an interesting bug (or feature...) in that if you set the width and height to zero, Tkinter won't redraw the window. At least, it doesn't on the Mac. I don't recall the workaround for that because I never, ever need to set a widget to a zero size, but setting it to 1x1 pixel makes it nearly invisible.
Related
I'm struggling with Tkinter now. I wanted to create layout but if I define window dimensions (800x600) and create frame which have to be wide 800 too, it have just half.
I tried googling and changing code, if I multiply width 2 times (to 1600) then frame fit the screen perfetly.
Here is code:
import tkinter as tk
SW, SH = 800, 600
win = tk.Tk()
win.geometry(f"{SW}x{SH}")
frm_appname = tk.Frame(
master = win,
bg = 'red'
)
frm_appname.place(
anchor = tk.N,
width = 800,
relheight = (1/6)
)
Here is output:
Can anyone explain me what happened here?
The anchor of "n" (tk.N) means that the top center portion of the frame is at the given coordinate. Since you didn't provide an x and y coordinate for place it defaults to 0,0. So, the top/middle (400,0) of the frame is at coordinate 0,0.
If you set the anchor to "n" or tk.NW, the top-left corner of your frame will be in the top-left corner of the window.
On an unrelated note, experience has taught me that layouts are nearly always easier to create with pack and/or grid. In my coupe of decades of using tk and tkinter, I've never used place for more than one or two special-case widgets.
I cannot seem to get the scroll on this text to work. The text will scroll to a certain extent, but then not appear afterwards. I believe that the height of the text widget is not what I want. For instance, the image below shows only about a half of what the actual result is for 遺伝子 (which I can find out by attempting to drag from a piece of text in the middle of the frame to the bottom). The width also is not the same size of the frame I would like it to be: the number 23 was just something that appeared to work.
If I do
txt = tk.Text(self.SEARCH_RESULTS_TEXT_FRAME,width=self.SEARCH_RESULTS_FRAME_WIDTH,height=20,background='#d9d9d9',relief=RIDGE)
... the width becomes much too large. I would have thought that it would only take up the size of the frame, which is 240.
Note the SEARCH_RESULTS_TEXT_FRAME is the frame in red.
Relevant code:
#search text frame
self.SEARCH_RESULTS_FRAME_HEIGHT = 240 #240
self.SEARCH_RESULTS_FRAME_WIDTH = self.TITLE_FRAME_WIDTH - 23
self.SEARCH_RESULTS_TEXT_FRAME = Frame(self.SEARCH_RESULTS_FRAME,height=self.SEARCH_RESULTS_FRAME_HEIGHT,width=self.SEARCH_RESULTS_FRAME_WIDTH)
self.SEARCH_RESULTS_TEXT_FRAME.place(x=10,y=10,anchor = NW)
self.SEARCH_RESULTS_TEXT_FRAME.config(background ="#adadad")
def print_dict_to_frame(self,results_list):
txt = tk.Text(self.SEARCH_RESULTS_TEXT_FRAME,width=34,height=20,background='#d9d9d9',relief=RIDGE)
txt.place(x=0,y=0)
txt.tag_configure('header',justify = 'center',font=("Meiryo",12,'bold'))
txt.tag_configure('entry',font=('Meiryo',8))
for r_list in results_list:
header = r_list[0]
entry = r_list[1]
txt.insert(tk.END, "{}\n".format(header),'header')
for single_result in entry:
txt.insert(tk.END,single_result+"\n",'entry')
txt.configure(state=DISABLED)
How can I get the text widget to only take up the width of the frame and the height of the frame, allowing for scrolling?
If I do txt = tk.Text(self.SEARCH_RESULTS_TEXT_FRAME,width=self.SEARCH_RESULTS_FRAME_WIDTH,height=20,background='#d9d9d9',relief=RIDGE) ... the width becomes much too large. I would have thought that it would only take up the size of the frame, which is 240.
The width option specifies a width in the number of characters, not pixels. If you use the value 240, the width will be 240 multiplied times the width of an average character in the font you are using.
How can I get the text widget to only take up the width of the frame and the height of the frame, allowing for scrolling?
Give the text widget a width and height of 1, and then let the geometry manager (pack, place, or grid) be responsible for stretching it to fit the frame.
Since you're using place, you can use the relwidth and relheight options to make it the full size of the frame:
txt.place(x=0,y=0, anchor="nw", relwidth=1.0, relheight=1.0)
Personally, I recommend using pack or grid in almost all cases. It's much easier to create a responsive UI with them than it is with place.
I was trying out something new on Tkinter (I am still a newbie), but it keeps failing...maybe someone could help out?
I wanted to create a window with several Frames, so that I can open and close them and show that way different content. However I am already stuck with not being able to "place" the, in this case a button, to the frame. Instead I get a blank frame with nothing inside...
The reason I want to use the place manager is so that I can easily choose the x and y coordinates. I don't want to create empty columns just in order to get a button appear in the middle of the screen.
Here the code:
from Tkinter import *
root = Tk()
root.title("Tkinter window")
root.geometry("800x600")
StartFrame = Frame(root)
StartFrame.pack()
Button1 = Button(StartFrame, command = StartTkinter, text = "Start", bg = "white", fg = "black", height = 2, width = 15)
Button1.place(x=0, y=50)
root.mainloop()
The problem is that you forgot to specify the dimensions of the frame. So, by default, it is created to be just 1 pixel high and 1 pixel wide. This means that its contents will not be visible on the window.
To fix the problem, you can either set exact values for these dimensions when you create the frame:
StartFrame = Frame(root, height=600, width=800)
or you can do:
StartFrame.pack(expand=True, fill="both")
to have the frame fill all available space.
Relevant code:
self.propertyListWrapper = ttk.Frame(self.propertyMenu)
self.propertyListWrapper.pack( fill = tk.BOTH, expand = tk.YES )
self.propertyListCanvas = tk.Canvas(self.propertyListWrapper)
self.propertyListCanvas.pack( fill = tk.BOTH, expand = tk.YES, side = tk.LEFT )
self.propertyGrid = ttk.Frame(self.propertyListCanvas)
self.propertyListScrollbar = ttk.Scrollbar(self.propertyListWrapper)
self.propertyListScrollbar.config(command = self.propertyListCanvas.yview)
self.propertyListCanvas.config(yscrollcommand = self.propertyListScrollbar.set)
self.propertyListScrollbar.pack(side = tk.RIGHT, fill = tk.Y)
...
# where stuff is added to self.propertyGrid
...
self.propertyListCanvas.config( scrollregion = (0, 0, self.propertyGrid.winfo_width(), self.propertyGrid.winfo_height()))
self.propertyListCanvas.create_window((0,0), window = self.propertyGrid, anchor='nw')
This is what is currently happening:
As you can see, the scrollbar doesn't have a bar. Not very useful.
What am I doing wrong?
Here's a simplified Github Gist that duplicates the problem. 20 labels should be there, and you should be able to scroll through them, but the scrollbar doesn't appear.
The default for pack is to put something along the top edge. When you packed the canvas you're using the default, so it takes up the top of the gui, leaving blank space below. When you packed the scrollbar, you told it to go to the right, so it is at the right edge of the empty space below the canvas. If you want the scrollbar and canvas side-by-side, pack both on the right, or pack one on the right and one on the left.
The problem with your gist is that you're trying to get the width and height of the frame before it has been drawn. Since the frame hasn't been mapped to the screen (because you haven't added it to the canvas yet) it's width and height is 1 (one). You must make a widget visible before you can measure its width and height. That means to add it to a canvas or pack/place/grid it to a visible window and then wait for a screen repaint.
Why can't I see a red frame with the following code?
import Tkinter
root = Tkinter.Tk()
root.geometry("220x300")
container_frame = Tkinter.Frame(background = "red", width = 100, height = 120)
container_frame.pack()
widget_button = Tkinter.Button(master = container_frame)
widget_button.pack()
root.mainloop()
You don't see it because you have no padding between the button and the frame. By default, containers "shrink to fit" around their contents. Even if you add an explicit width or height to the frame, it will shrink to exactly fit its children.
There are several ways to achieve the effect you're looking for, but it's not clear exactly what effect you want. You can turn off this "shrink-to-fit" behavior (using container_frame.pack_propagate(False)). Or, you can add padding around the widget. Or, you can apply the background to the container of the frame. Or you could pack the frame to fill its container (the main window), then make sure the containing window is large enough to expose the frame.
For an example of that last suggestion, you can change one line to be this:
container_frame.pack(side="top", fill="both", expand=True)
If you change to:
widget_button.pack(padx=10, pady=10)
You can see that the frame has been resized when call widget_button.pack(...)