Python Tkinter Text Alignment - python

I am using Tkinter with Python2 to create a new window by clicking on the button. In this new window I want to Display text. Now I have Troubles with the alignment, is it possible to align it to the left? It is always centered and neither anchor=LEFT nor sticky="NSEW" help.
import tkinter as tki
btn3 = tki.Button(self.root, text="HELP", command=self.help, fg="black", bg="white", font=("Courier",22))
btn3.grid(row=1, column=2, padx=10, pady=10, sticky="NSEW" )
def help(self):
self.text = """ Hello.
You can find help here to the following subjects:
- getting started
- installation
- FAQ."""
self.top = tki.Toplevel()
self.top.title("Help")
self.label1 = tki.Label(self.top, text = self.text, height = 0, width=80, fg="black", bg="white", font=("Courier",18))
self.label1.pack()

When you use anchor = n you need to put anchor = "n" i.e. with the n in quotes. You're getting the global name is not defined error because of this.
Alternatively, use anchor = tki.N. Because you used import tkinter as tki you must prefix tkinter variables with tki. in order for python to know what you're referring to. However, I think you might want to try justify=tki.LEFT also if that doesn't work.

Related

Opening a Toplevel windows in tkinter

I am trying to open a toplevel window with a label from a function call but the label is not showing. What am I doing wrong?
Gratias.
from tkinter import *
import tkinter.font as fonte
def open_top():
top = Toplevel(master)
top.geometry("375x238+789+479")
top.resizable(width=FALSE, height=FALSE)
topFont = fonte.Font(family='Ubuntu', size=40)
label = Label(top, text='world', borderwidth=2, relief="sunk", width=24)
label.config(font = topFont, height=11, wraplength=350)
label.grid(row = 0, column = 0, columnspan=1, rowspan=1, sticky=W+E+N+S)
master.update()
# creating main tkinter window
master = Tk()
master.geometry("374x340+790+100")
master.resizable(width=FALSE, height=FALSE)
myFont = fonte.Font(family='Monospace', size=25)
view = Label(master, text='helo', borderwidth=2, relief="sunk", width=10)
view.config(font = ('Monospace', 36), height=3)
view.grid(row = 4, column = 0, columnspan=2, rowspan=1, sticky=W+E+N+S, padx=5, pady=5)
btn = Button(master, text ='toplevel', command = lambda: open_top())
btn.grid(row=6, column=0, columnspan=1, pady=4, padx=4)
btn = Button(master, text='Quit', command=master.destroy)
btn.grid(row=6, column=1, columnspan=1, pady=4, padx=4)
mainloop()
First about the problem:
When you create the label, you specify the width (and later) height arguments. Since your label contains text the units you pass as values to those arguments represent characters for width and lines for height (You can read about those attributes here)
#TheLizzard mention: wraplength's value also is in characters, and since you have set it to 350 and your font is not that small, it will wrap the text when a huge part of it is out of the window (and quite possibly even out of the screen) so with the current value it is quite useless. (it is also quite useless if you add static text because then you can simply add a newline or sth, a use case would be when you don't know how long the text is, for example, it was taken from user input)
Possible fixes:
Remove the width and height arguments (really the easiest):
label = Label(top, text='world', borderwidth=2, relief="sunk")
label.config(font=topFont, wraplength=350)
The widget can be also configured all at once, you don't need to use its method like this for initialization:
label = Label(top, text='world', borderwidth=2, relief="sunk", font=topFont, wraplength=350)
Change the height and width values (width tho really doesn't have to be used, especially if you use the wraplength argument):
label = Label(top, text='world', borderwidth=2, relief="sunk", font=topFont, wraplength=350, height=1)
Use anchor (really not that much of a fix or anything but will allow you to see the text (to an extent)):
label.config(anchor='nw')
Few other things:
Important (suggestions)
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
Also: I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but use if it is used for assigning a value (variable = 'some value'). Have two blank lines around function and class declarations.

How to know in which entry box on a list did I press enter?

I'm trying to make a table with Entry widgets in Tkinter, so I made a list with them. The problem is that I need to know in which box did the user press Enter to perform certain actions, for example if someone erases the content of the first cell of a row and press Enter, I want to erase the content of all the other cells in that row, or if someone writes the product code in the first cell of that row, the product description should appear on the cell in front.
I've tried with the methodology suggested here: Tkinter binding a function with arguments to a widget by unutbu but it doesn't seem to be working with my list of entry widgets.
Here is what I've tried:
from tkinter import *
root = Tk()
root.configure(background='gray')
item_list_fr = Frame(root, bg='gray', width=450, height=108, padx=3, pady=3)
item_list_fr.grid(row=2, column=0, rowspan=2)
info_tupple=[]
def show(eff=None, row_2=0, column_2=0):
print(str(row_2), str(column_2))
for row in range(15):
info_list=[None]*5
for column in range(5):
info_list[column]=Entry(item_list_fr)
info_list[column].bind('<Return>', lambda eff: show(eff, row_2=row, column_2=column))
info_list[column].grid(row=row+1, column=column)
info_tupple.append(info_list)
root.mainloop()
How can I rewrite my code to make it work?
You can use functools.partial like this:
from tkinter import *
import functools
root = Tk()
root.configure(background='gray')
item_list_fr = Frame(root, bg='gray', width=450, height=108, padx=3, pady=3)
item_list_fr.grid(row=2, column=0, rowspan=2)
info_tupple=[]
def show(eff=None, row_2=0, column_2=0, event=None):
print(str(row_2), str(column_2))
for row in range(15):
info_list=[None]*5
for column in range(5):
info_list[column]=Entry(item_list_fr)
command = functools.partial(show, row_2=row, column_2=column)
info_list[column].bind('<Return>', command)
info_list[column].grid(row=row+1, column=column)
info_tupple.append(info_list)
root.mainloop()
For more answers look here.

Get emoji working in tkinter and make it overridable by code but not end user during runtime

I need to create a field in tkinter that stores an emoji but when someone presses a button, that emoji is overwritten. I can't get emojis working in tkinter and I'm not sure how to then overwrite it.
import tkinter as tk
self.option4 = tk.Button(self, width=10)
self.option4["text"] = "no"
self.option4["command"] = self.wrong
self.option4.pack(side="top")
corecalc = "🔲"
self.answercheck = tk.Text(self, height=1, width=5)
self.answercheck.pack()
self.answercheck.insert(tk.END, corecalc)
self.QUIT = tk.Button(self, text="Quit", fg="red", command=root.destroy)
self.QUIT.pack(side="bottom")
def correct(self):
corecalc = "✅"
def wrong(self):
corecalc = "❌"
Expected 🔲 outputs in field and changes to ❌ upon button press. Also is there a better method than text box that makes the field fixed rather than editable by end user.
Error: _tkinter.TclError: character U+1f532 is above the range (U+0000-U+FFFF) allowed by Tcl
You can use any tkinter widget to display the characters - emojis or otherwise, that you will need - a Text widget if you want to display a single character is a poor choice, though possible.
If you really want to use Text, you can change it to not editable by setting its state Key to "disabled" (as oposed to the default "normal"):
self.answercheck = tk.Text(self, height=1, width=5, state="disabled")
A text box will require you to remove the previous text before insertig the new, you can simply use a tkinter.Label widget if you want programtic only changes to the characters:
import tkinter as tk
w = tk.Tk()
display = tk.Label(w, text="□")
display.pack()
def correct():
display["text"] = "✅"
def wrong():
display["text"] = "❌"
button = tk.Button(w, text="no", command=wrong)
button.pack()
button = tk.Button(w, text="yes", command=correct)
button.pack()
tkinter.mainloop()
(In the build I have here - Python 3.7 on a Linux fedora, tkinter can't handle your 🔲 character directly, as its codepoint is above \uffff)

Tkinter Input/Entry in Python

So I am trying to when the person clicks on the button I created, to display the text they wrote on the input field but for some reason when I click the button it displays:
.!entry
And I don't know what I am doing wrong since I am new to python so I wanted to know how to fix this problem, here's my code and thank you since any help is appreciated!
from tkinter import *
screen = Tk()
def print_input():
text2 = Label(screen, text=input_field)
text2.grid(row=1, columnspan=3)
text = Label(screen, text="Write to print:")
text.grid(row=0, column=0)
input_field = Entry(screen)
input_field.grid(row=0, column=1)
submit_button = Button(screen, text="Print!", fg="yellow", bg="purple",
command=print_input)
submit_button.grid(row=0, column=2)
screen.mainloop()
Change:
def print_input():
text2 = Label(screen, text=input_field)
to:
def print_input():
text2 = Label(screen, text=input_field.get())
# ^^^^^^
You're telling the text of the label to be set to the Entry widget instead of the Entry widget's content. To get the content of the Entry widget, use the .get() method.
The funky string you're seeing in the label is the tkinter name for the Entry widget.

Creating a GUI with Tkinter of Python

I have written the following code:
from Tkinter import *
root = Tk()
root.title("Power Method")
labeltext1 = StringVar()
labeltext2 = StringVar()
labeltext1.set('Parameters') # Set start value
labeltext2.set('Epsilon')
label1 = Label (root, textvariable = labeltext1, height = 4)
label1.pack()
Entry(root, textvariable = labeltext1). pack()
label2 = Label (root, textvariable = labeltext2)
label2.pack()
Entry(root, textvariable = labeltext2). pack()
checkBox1 = Checkbutton(root, text = "NumPy")
checkBox1.pack()
checkBox2 = Checkbutton(root, text = "Not NumPy")
checkBox2.pack()
Button(root, text = "Exit").pack(side = RIGHT)
Button(root, text = "Compute").pack(side = RIGHT)
root.mainloop()
This code, when run, creates a window that contains Parameters, Epsilon as two places that you could enter value and NumPy and Not NumPy as checkboxes and finally a compute and exit button.
I am trying to format the code, in a way that Parameters and Epsilon appear on the left of the window, Numpy and Not Numpy infront of them on the right and Compute and Exit stay in their current positions.
Any help regarding the formatting would be appreciated.
Alright you need to google .grid() and .pack() and .place() for tkinter to learn more about what each is good for. For your case you could use any of them, but .grid() is probably the best and easiest for you to use.
To do this you must change .pack() to .grid() everywhere you have it, then you should use the row and column options to put your widgets where you want them. E.G.
label1.grid(row = 1, column = 1)
label2.grid(row = 1, column = 2)
this will put label2 on the right side of label1. The way .grid() works is that the columns are as wide as the largest (widest) widget in that column, same applies for rows.
if you need anything else just ask, but please do look at the documentations as Bryan said.

Categories