I'm trying to add a Tk.Scale widget to my application, but I have a problem with setting non-integer value to the resolution parameter. If I pass an integer value to Scale constructor, it works correctly, but with any non-integer value (say 0.1) my scale widget does not move. It appears at the right place and looks just fine, but doesn't respond to my attempts to move it.
Here is my code related to the creation of scale widget:
self.sliderValue = Tk.DoubleVar()
self.slider = Tk.Scale(self.frame,
from_=float(self.lowerValue.get()),
to=float(self.upperValue.get()),
orient=Tk.HORIZONTAL,
length=180,
variable=self.sliderValue,
resolution=0.1, # Here is the problem
command=self.sliderMoved)
The problem is I can not reproduce this issue outside of my application. In other words, if I create just a simple window with one scale widget, it works with any resolution values. So it seems that the problem is hidden somewhere outside of this constructor call, but I can not figure out where. May be someone had the same problem and can advise me what should I check.
Addition:
May be it is important: in standalone (working) case the value above the slider is in "1.0" format (with the dot as the separator), and in my broken application it is "1,0" format (with the comma as the separator). May by some kind of type/format mismatch is happening here.
Addition 2:
Here is minimal example:
import Tkinter as Tk
from pylab import *
# cla() # if you uncomment these two lines,
# clf() # scale will break for non-int resolutions
root = Tk.Tk()
var = Tk.DoubleVar()
scale = Tk.Scale(root, from_=6.0, to=8.5, variable = var,
resolution=0.1, orient=Tk.HORIZONTAL)
scale.grid(column=0, row=0, columnspan=3)
root.mainloop()
I've just updated to Ubuntu 16.04 and it seems that this problem does not appears anymore (Python 2.7.11+).
Related
I'd like to have a gracefully resizable TK user interface holding a ttk.Notebook. Meaning: If the window is dragged larger, the content should increase its size accordingly.
The first naive attempt was using the sticky parameter of the grid mechanism:
import tkinter as tk
import tkinter.ttk as ttk
[..]
notebook = ttk.Notebook(root)
notebook.grid(row=j, column=0, columnspan=2, sticky=tk.E + tk.W)
I had expected this to suffice, alas it had no effect. Eventually I resorted to configuration events:
root.bind('<Configure>', handle_resize) # << Btw. is there a way to restrict this to resize events?
def handle_resize(ev):
if ev.width:
width = root.winfo_width()
notebook.config(width=width - 4) # << Consider the fragile "-4" atrocity in this line!
If that dubious -4 is lacking, the Notebook will be a little too broad -- causing a resize -- causing an update that again is a little to broad, in theory ad infinitum! In practice creating a window that grows a little broader all the time until strange things happen.
Hence that -4, actually solving the problem on my PC. But this feels so very fragile! The question:
How do I go about properly auto-resizing the ttk.Notebook?
Even though you tell the grid manager to make the notebook to take up all the horizontal space of the cell, but you don't tell the grid manager to make the cell (column 0) to take up all the available horizontal space of the root window.
It can be done by adding root.columnconfigure(0, weight=1).
Note that with the above line, the binding is not required.
I am familiarizing myself with Tkinter, and I am attempting to write a very simple program, which displays a button in a window, using the pack geometry manager.
I was experimenting with various configuration options for pack(), such as expand, fill, and side, and I've run into a peculiar problem. I have written the following code:
from Tkinter import *
root = Tk()
widget = Button(root, text='text')
widget.pack(expand=YES, fill=BOTH)
root.mainloop()
The problem is that the button expands to fill the window in the horizontal direction, but not the vertical direction. This is the same result that I get if instead of specifying fill=BOTH I use fill=X. In addition, if I specify instead fill=Y the button does not expand in either direction. Something seems to be going wrong with the fill in the vertical direction, and I cannot figure out what it might be.
I attempted to Google this problem and surprisingly found no mention of this happening to anyone else. I am using a Mac with OS X Yosemite and running python 2.7.5. I also attempted to compile with python 3.4.1 and saw no change.
Edit:
Based off of the answer and comments below, it is clear that there is nothing wrong with my code, because it seems to work on other machines. If not an error in the code, does anyone know what could possibly be causing the button to not stretch vertically when I run the above code?
This is a feature of native buttons on OSX. Buttons on OSX will be a fixed height and will not expand vertically. There is nothing you can do, short of using a different widget such as a label.
try running this code to see the behavior of fill and expand
from Tkinter import *
root = Tk()
root.geometry("500x500")
widget = Button(root, text='text1')
widget.pack(fill=X, expand=1)
widget = Button(root, text='text2')
widget.pack(fill=Y, expand=1)
widget = Button(root, text='text3')
widget.pack(fill=BOTH, expand=1)
root.mainloop()
Argument fill does fill in vertical direction as well
I am also beginner, defining geometry for fill was missing in your code as given below:
from Tkinter import *
root = Tk()
root.geometry("600x400")
widget = Button(root, text='text')
widget.pack(expand=YES, fill=BOTH)
root.mainloop()
What is the equal function of PyQt setGeometry() in tkinter? Or Is there any function works like that? I searched a bit but couldn't find, all of examples looks like tkinter works on a specific widget and we just can set width-height.
EDIT:
The setGeometry() does two things. It locates the window on the
screen and sets its size. The first two parameters are the x and y
positions of the window. The third is the width and the fourth is the
height of the window.
The nearest thing tkinter has is probably the place geometry manager. With it you can set the x,y coordinates (either absolute or relative) and the width and height attributes (also absolute or relative).
For example, to place a label at 100,100 and with a width and height 50% of its parent you would do something like this:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.place(x=100, y=100, relwidth=.5, relheight=.5)
root.mainloop()
However, place is very rarely the right choice. Tkinter is very smart about picking the right size for widgets, and for laying them out. Without knowing the actual problem you're trying to solve it's hard to give good recommendations, but almost certainly, pack or grid will work better.
You can also do something similar to #BryanOakley's answer by the grid geometry manager:
from tkinter import *
root = Tk()
label = Label(root, bg='cyan')
label.grid(ipadx=100, ipady=50, padx=50, pady=50)
UPDATE: Please feedback why you think this answer is not useful.
How to create multi-lines in an entry widget in tkinter and use those inputs to create something?
For example, I want a textbox widget to come up and ask the user:
How many squares do you want? (ex: 4x4, 5x5)
What color do you want them?
And with the users input, I would like to create that many x-amount of squares in that specific height/width and specify the colors etc.
I am totally new to tkinter and I'm not really sure how to approach this.
I tried using this, but i'm not really sure how to add more lines and to use the values inputted.
import tkinter
from tkinter import *
class Squares:
root = Tk()
root.title('Random')
x = Label(text='How many squares? (ex: 4x4, 5x3)').pack(side=TOP,padx=10,pady=10)
Entry(root, width=10).pack(side=TOP,padx=10,pady=10)
Button(root, text='OK').pack(side= LEFT)
Button(root, text='CLOSE').pack(side= RIGHT)
You have a number of problems here.
I'm not sure what the Squares class is supposed to be doing, but it's basically not doing anything. You have a bunch of code that runs when you define the class, creating a few variables (which will end up as class attributes, shared by all instances of the class), and… that's it. Rather than try to figure out what you're intending here, I'm just going to scrap the class and make it all module-level code.
You never call root.mainloop(), so your program will just define a GUI and then never run it.
You don't bind your buttons to anything, so there's no way they can have any effect. You need to create some kind of function that does something, then pass it as the command argument, or .bind it later.
You don't store references for any of your controls, so there's no way to access them later. If you want to get the value out of the entry, you need some way to refer to it. (The exception is your x variable, but that's going to be None, because you're setting it to the result of calling pack on the Label, not the Label itself.)
Once you've done that, you just need to parse the value, which is pretty easy.
Putting it all together:
import tkinter
from tkinter import *
root = Tk()
root.title('Random')
Label(text='How many squares? (ex: 4x4, 5x3)').pack(side=TOP,padx=10,pady=10)
entry = Entry(root, width=10)
entry.pack(side=TOP,padx=10,pady=10)
def onok():
x, y = entry.get().split('x')
for row in range(int(y)):
for col in range(int(x)):
print((col, row))
Button(root, text='OK', command=onok).pack(side=LEFT)
Button(root, text='CLOSE').pack(side= RIGHT)
root.mainloop()
You just have to change that print to do something useful, like creating the squares.
If you don't need an outline for the text box, create_text would be the easiest thing, even though it doesn't have a wrap text feature(at least, in python 3 you can do this):
from tkinter import *
tk = Tk()
canvas = Canvas(tk, 1000, 1000)
canvas.pack()
canvas.create_text(200, 200, text="Example Text")
Try it!
I have a label sitting on a frame which is updated periodically to show the status of the application. Periodically, the name of the item being processed will not fit into the window, and with the way I currently have the label configured the window expands to accomidate the label.
Ideally, I'd like way to smartly truncate the text on the label (and then expand if someone expands the window). Is there an easy way to accomplish this?
Practically speaking, how can I just stop the window to expanding based on changes to text in the label?
Edit:
This is an aproximation of the code I'm working on that is not exhibiting the desired behavior (there is a link at the bottom to the actual code file):
r = tk.Tk()
statusFrame = tk.Frame(r, relief=tk.SUNKEN, borderwidth=2)
statusFrame.pack(anchor=tk.SW, fill=tk.X, side=tk.BOTTOM)
statusVar = tk.StringVar()
statusVar.set("String")
tk.Label(statusFrame, textvariable=statusVar).pack(side=tk.LEFT)
statusVar.set("this is a long text, window size should remain the same")
Actual code available here.
The answer depends very much on the way you currently have configured the widget.
For example, I can get the desired functionality as such:
>>> import Tkinter as tk
>>> r=tk.Tk()
>>> r.title('hello')
''
>>> l= tk.Label(r, name='lbl', width=20, text='reduce the window width')
>>> l.pack(fill=tk.BOTH) # or tk.X, depends; check interactive resizing now
>>> l['text']= "This is a long text, window size should remain the same"
Tell us what you do in your code for a more precise (appropriate for your code) answer.