Make text in a tkinter Listbox fit inside? - python

I've looked everywhere for a fix to this. I stumbled across this:
How to fit Tkinter listbox to contents
But this question is asking the reverse of what I want. I want the box to remain the size I've set it to, but the text runs off of the side like in the screenshot from the above linked question. Is there anyway to force a \n to be added to the string once its character count reaches the length of the listbox?
Also, I apologize if something is wrong with the format of my question, I've never posted here before.
class Stars(Tk):
def __init__(self):
Tk.__init__(self)
self.feed = Listbox(self, width = 55 , height = 31, relief = SUNKEN, borderwidth = 3)
self.feed.grid(row = 1, column = 2, columnspan = 2)
def simulate(self):
self.mass = eval(self.massEntry.get())
self.feed.insert(END, 'Star to be created with mass of {} * 10^30 kg; {} solar masses.'.format(1.98855 * self.mass, self.mass))
self.feed.insert(END, '0 years: Protostar formed in an interstellar gas cloud, and begins to compress due to gravity.')
This is all of the relevant code (trying to make a stellar evolution simulation). This is what it looks like when run, with the problem circled in red:
http://imgur.com/dZCYe6s

No, there is no way to have a Listbox wrap the text. If you want to support wrapping, use a Text widget. If you want to select items like in a listbox, you can add some custom bindings to do that.

Related

Make a program in which the user introduces the lenght value of the radius or side of a shape, then selects a shape, which is drawn with said value?

I need to make a program where the user enters the value that he wants the radius or side of the figure to have, and then chooses one figure from the possible ones from a list so that it is drawn with the previously entered value, and then the same with a second figure. For this I decided to use tkinter and turtle in python.
The problem is that when I want to store the value in a variable, I get this error: Entry.get() takes 1 positional argument but 2 were given"
Also, the code I use to trigger the select function and draw the circle, in this case, when that option is selected, ComboboxSelected doesn't seem to trigger anything. I don't know if I should put the option in another way inside the function. In this case, I imported turtle for drawing the figures, since it seemed less complex to me.
Obviously, the other figures still need to be programmed and the other list for the second figure, but I want it to work before continuing. All kind of advice is welcomed. Here is my code. Some parts are in spanish, but they are mostly the functions' and variable names and text displayed as titles, so I hope they dont become much of an obstacle.
from turtle import *
from tkinter import *
from tkinter import ttk
inicio = Tk()
inicio.geometry("600x500")
inicio.title("Dibujos de figuras")
texto = Entry(inicio, font = "Helvetica 15")
texto.place(relx=0, rely=0.1, relwidth=1, relheight=0.05)
m = None
radiolado = Label(inicio, text = "Radio o lado en cm")
radiolado.place(relx=0, rely=0.05)
def guardar_Valor():
global m
valor = Entry.get(1.0, "end-1c")
m = valor
def select(event):
if lista_1.get() == "Círculo":
c = Turtle()
c.circle(m)
figura_1 = Label(inicio, text = "Figura 1")
figura_1.place(relx=0.43,rely=0.25)
figura_2 = Label(inicio, text = "Figura 2")
figura_2.place(relx=0.43,rely=0.6)
lista_1 = ttk.Combobox(inicio, state="readonly",values=["Círculo", "Cuadrado", "Triángulo", "Pentágono", "Hexágono"])
lista_1.current(0)
lista_1.place(relx= 0.35,rely=0.3)
lista_1.bind("«ComboboxSelected»", select)
Boton1= Button(inicio, text = "Guardar", command = guardar_Valor)
Boton1.place(relx= 0.42,rely=0.18)
lista_2 = ttk.Combobox(inicio, state="readonly",values=["Círculo", "Cuadrado", "Triángulo", "Pentágono", "Hexágono"])
lista_2.current(1)
lista_2.place(relx= 0.35,rely=0.7)
inicio.mainloop()

Tkinter ~ how to space out elements WITHIN a grid box

I am trying to space the following widgets out correctly so that they don't stack on top of eachother, but I don't know how to do it having them all within the same .grid() box. An example of the problem can be seen in the problem above.
To answer the question of why I can't just stick the widgets in the next row down: On the left, you can see that the listbox takes up significant vertical space. If I place the text widgets on the next row down, there will be a huge space inbetween the elements.
Here is the relevant code. For context, I am broadly working with receipts.
test.py
receipt_number_input = Label(text="Receipt Number: ")
receipt_number_input.grid(row=0,column=3)
receipt_number_entry = Entry()
receipt_number_entry.grid(row=0,column=4)
order_total_input = Label(text="Order Total: ")
order_total_input.grid(row=0,column=3)
order_total_entry = Entry()
order_total_entry.grid(row=0,column=4)
date_input = Label(text="Date: ")
date_input.grid(row=0,column=3)
date_entry = Entry()
date_entry.grid(row=0,column=4)
I have looked into padding and sticky to shift the text down and into a more usable format, but none of them in my experience have fixed the problem.
What would I have to pass into .grid() to shift these boxes into their correct positions?

Fix Text widget size

I have made an application and part of it involves entering a question and answer. I have this code:
import tkinter as tk
root = tk.Tk()
root.geometry("500x250")
#Main question/answer frame
createFrm = tk.Frame(root)
createFrm.pack(expand = True) #To centre the contents in the window
#Create question entry area
cnqFrm = tk.Frame(createFrm)
cnqFrm.pack()
cnqFrm.pack_propagate(False)
#Question entry
cnqLabQ = tk.Label(cnqFrm, text = "Question")
cnqLabQ.grid(column = 0, row = 0)
#Frame for question Text
cnqTxtQFrm = tk.Frame(cnqFrm, height = 100, width = 100)
cnqTxtQFrm.grid(column = 0, row = 1)
cnqTxtQFrm.grid_propagate(False)
#Question Text
cnqTxtQ = tk.Text(cnqTxtQFrm)
cnqTxtQ.pack()
cnqTxtQ.pack_propagate(False)
#Answer entry
cnqLabA = tk.Label(cnqFrm, text = "Answer")
cnqLabA.grid(column = 1, row = 0)
#Frame for answer text
cnqTxtAFrm = tk.Frame(cnqFrm, height = 100, width = 100)
cnqTxtAFrm.grid(column = 1, row = 1)
cnqTxtAFrm.grid_propagate(False)
#Answer Text
cnqTxtA = tk.Text(cnqTxtAFrm)
cnqTxtA.pack()
cnqTxtA.pack_propagate(False)
Despite the fact the Text widget is in a Frame with grid_propagate(False) and a fixed height and width, and the Text widget itself has pack_propagate(False), it still expands to far larger than it should be. Why is this and how can I fix it?
You don't give the text widget an explicit size, so it defaults to 40x80 average-sized characters. The most common way to force it to a specific size that is determined by its parent is to give it a size that is smaller than the containing widget, and then let grid or pack expand it to fit the space given to it. So, start by giving the text widget a width and height of 1 (one).
Next, in this specific case you are calling grid_propagate(False) on the containing frame, but you are using pack to manage the window. You should call pack_propagate if you're using pack. You also need to tell pack to expand the text widget to fill its frame.
Finally, there's no point in calling cnqTxtQ.pack_propagate(False) since that only affects children of the text widget and you've given it no children.
All of that being said, I strongly encourage you to not use grid_propagate(False) and pack_propagate(False). Tkinter is really good at arranging widgets. Instead of trying to force the text widget to a specific pixel size, set the text widget to the desired size in lines and characters, and let tkinter intelligently arrange everything else to line up with them.

Tkinter Checkbutton variable

I'm not great at tkinter or even python so I've run into what should be a simple problem.
I have something like this in the middle of my project:
visible = numLevels * [IntVar(value=1)]
top = Toplevel()
settingslabel = Label(top, text='Settings', height=0, width=100)
for i in range(0, numLevels ):
check = ttk.Checkbutton(settingslabel, text='Level ' + str(i), variable=visible[i])
check.grid(column = 0, row = i)
check.var = visible[i]
settingslabel.grid(column = 0, row=0)
I want to have settings screen with a checkbox for every level, while maintaining an array of integers that represent the status of each button.
However, all checkboxes are synchronized. Meaning, when I check a box, all other boxes also become checked. I believe that this is because of the 'variable' field of the checkbutton. As the loop continues, i is updated, and as a result, visible[i] changes as well. I want to preserve the variable when I created the checkbutton. I don't understand how tkinter/python work well enough to know.
The number is levels can be any integer > 0 and is determined at runtime so I can't just unroll the loop.
Is there a better way to do this? Thanks in advance.
This is a duplicate of this SO post, but explanation below.
Its because all your boxes are sharing the same tkinter.Intvar() object:
numlevels = 5
visible = numlevels * [IntVar(value = 1)]
for i in range(len(visible)):
print (hex(id(visible[i]))
# Outputs:
'0x67f8190'
'0x67f8190'
'0x67f8190'
'0x67f8190'
'0x67f8190'
To solve: visible = [IntVar(value = 1) for i in range(numlevels)]

Generating Radiobutton grid menu from an Array in Tkinter, Python

Edit: Sorry I can't answer my own post since I'm new but I figured it out: If you remove the line "tki.Button(master,..." (2nd to last code line), then the code runs perfectly fine. I guess the grid and the button don't work the way I put it.
sorry to bother but I'm having a little trouble figuring out what's off here. Basically I have an array that I want to loop through and set each of the values as a radiobutton IN A GRID. Later I'm going to loop through several arrays to generate a larger grid menu, but I can probably figure that out once I get this first loop working.
Here is my code:
import Tkinter as tki
master = tki.Tk()
frm = tki.Frame(master, bd = 16, relief = "sunken")
frm.grid()
tType = tki.StringVar()
tColumn = tki.IntVar()
tRow = tki.IntVar()
compType = ["iMac ", "Mac Mini ", "Mac Pro ", "Macbook ", "Macbook Air ", "Macbook Pro "]
tColumn.set(0)
tRow.set(0)
def radioCreate(typeArray):
for t in typeArray:
b = tki.Radiobutton(frm, text = t, variable = tType)
b.config(indicatoron = 0, bd = 4, width = 16, value = t)
b.grid(row = tRow.get(), column = tColumn.get())
tRow.set((tRow.get() + 1)) #increment tRow for next run-through
def p():
print tType.get()
radioCreate(compType)
tki.Button(master, command = p, text = "Display").pack()
master.mainloop()
Now remember, I'm trying to get this working in a grid, because I'm going to populate other columns with other data from different arrays.
The problem is i. These two lines:
frm.grid()
...
tki.Button(...).pack()
While it's perfectly acceptable to use pack and grid in the same application, you can't use them on two widgets that share the same master.
Grid will potentially change the size of a widget or its master depending on its options. Pack will notice the change, and may itself try to resize one or more widgets and/or the master based on its options. Grid will notice the change, and may resize... Pack will notice the change and resize, ...

Categories