I create a sudoku solver and I want to show candidates for each cell. Sudoku grid is list of Label widgets and I have a problem with arranging these candidates into grid. My goal is something like this (without colors). I already have them in grid, but number "0" is still visible. And I´m asking you how to hide these zeros. I tried to substitute "0" with space (" "), but brackets are displayed instead.
My code:
from Tkinter import *
root = Tk()
text_good = [1,2,3,4,5,6,7,8,9]
text_wrong1 = [1,2,3,4,0,0,0,8,9]
text_wrong2 = [1,2,3,4," "," "," ",8,9]
L1 = Label(root,bg="red",text=text_good,wraplength=30)
L1.place(x=0,y=0,width=50,height=50)
L2 = Label(root,bg="red",text=text_wrong1,wraplength=30)
L2.place(x=50,y=0,width=50,height=50)
L3 = Label(root,bg="red",text=text_wrong2,wraplength=30)
L3.place(x=100,y=0,width=50,height=50)
root.mainloop()
I hope I described my problem well. I appreciate any answer.
Thank you
Use text_wrong2 = ' '.join(map(str,[1,2,3,4," "," "," ",8,9])) instead of passing directly the list as the text option. Remember that the default font is not monospaced, so the numbers won't be aligned as in the other two examples.
Apart from that, I recommend you to use grid instead of place, and represent each number using a Label, instead of using only one for each cell and relying on the new lines that are added because of the width. Thus, you don't have to worry about handling the offsets for each label.
from Tkinter import *
root = Tk()
text_good = [1,2,3,4,5,6,7,8,9]
text_wrong1 = [1,2,3,4,0,0,0,8,9]
text_wrong2 = [1,2,3,4," "," "," ",8,9]
def create_box(text_list, **grid_options):
frame = Frame(root, bg="red")
for i, text in enumerate(text_list):
Label(frame, text=text, bg="red").grid(row=i//3, column=i%3)
frame.grid(**grid_options)
create_box(text_good, row=0, column=0, padx=10)
create_box(text_wrong1, row=0, column=1, padx=10)
create_box(text_wrong2, row=0, column=2, padx=10)
root.mainloop()
Related
I know this question has been asked previously, but I'm having trouble understanding it and figuring out how to implement it in my own program. I am extremely new to tkinter (just started today) and I'm unable to properly format my widgets. My goal is for the two leftmost widgets to be in a column together, and for the four widgets on the right to be centered with each other as well. Currently, I am unable to align the two widgets with the left edge, and my text widget gives an error when I try to format it using the grid. While researching these issues, I've come the the conclusion that I need to configure the rows and columns-- I'm just having a hard time understanding how exactly to do it to make it work in my code. To be more specific, I don't know where to put the configuration code or the amount of weight it needs to have, likely due to my limited knowledge in the subject.
I keep getting this error with my text box, if that helps:
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
Here is some of my code:
def create_widget(self):
# name label and entry
self.name_label = Label(self,text='name')
self.name_label.grid(row=0,column=0)
self.name_entry = Entry(self)
self.name_entry.grid(row=0,column=1)
# score label and entry
self.score_label = Label(self,text='score')
self.score_label.grid(row=1,column=0)
self.score_entry = Entry(self)
self.score_entry.grid(row=1,column=1)
# button
self.btn = Button(self,text='add',command=self.add)
self.btn.grid(row=2,column=1)
# text box
self.text = Text(root, width=40, height=12)
self.text.pack()
# prints to text box
def add(self):
name = self.name_entry.get()
score = self.score_entry.get()
self.text.insert(END,(f'name:{name} score:{score}\n'))
root = Tk()
root.geometry("400x250")
root.mainloop()
Here is the current output:
And here is what I want the output to look like (without Jerry):
Let me know if any further information is necessary, and sorry if this question is a duplicate. Any further explanations, examples, or better methods would be very appreciated!
You can't use pack and grid on the same root widget. So you should use grid the the text widget and add some padding and a columnspan to stretch it over multiple columns.
def create_widget(self):
# name label and entry
self.name_label = Label(self,text='name')
self.name_label.grid(row=0,column=0, sticky=(E))
self.name_entry = Entry(self)
self.name_entry.grid(row=0,column=1)
# score label and entry
self.score_label = Label(self,text='score')
self.score_label.grid(row=1,column=0, sticky=(E))
self.score_entry = Entry(self)
self.score_entry.grid(row=1,column=1)
# button
self.btn = Button(self,text='add',command=self.add)
self.btn.grid(row=2,column=1)
# text box
self.text = Text(self, width=40, height=12)
self.text.grid(row=3,column=0,columnspan=4, sticky=(N,E), padx=10)
# prints to text box
def add(self):
name = self.name_entry.get()
score = self.score_entry.get()
self.text.insert(END,(f'name:{name} score:{score}\n'))
I am trying to make a calculator with Tkinter GUI. However, when I make buttons under an entry, they get pushed apart. Also, instead of the buttons being in their corresponding columns, they are way out of line. What is making this happen?
Code:
from tkinter import *
# Configure the window
gui = Tk()
gui.title("Calculator")
gui.geometry("400x500")
# Variables for displaying input and output
expression = StringVar()
input_ = ""
# Make the Entry
expression_entry = Entry(gui, textvariable=expression,
width=49).grid(column=0, row=0)
# Make the Buttons
number_1 = Button(gui, width=3, height=2)
number_1.grid(column=0, row=1)
number_2 = Button(gui, width=3, height=2)
number_2.grid(column=1, row=1)
gui.mainloop()
https://i.stack.imgur.com/8yGWn.png
It is because column 0 is very wide to hold the entry. By default, items are centered in their allocated space so the first button is centered under column 0, and the second is centered in column 1.
The solution is to decide how many columns you want under the entry widget, then have the entry widget span that many columns. Then, remove the width for the entry widget and use the sticky attribute so that it completely fills the space given to it rather than forcing it to be a specific width.
The following code adds a third column for more buttons
from tkinter import *
# Configure the window
gui = Tk()
gui.title("Calculator")
gui.geometry("400x500")
# Variables for displaying input and output
expression = StringVar()
input_ = ""
# Make the Entry
expression_entry = Entry(gui, textvariable=expression)
# Make the Buttons
number_1 = Button(gui, width=3, height=2)
number_2 = Button(gui, width=3, height=2)
number_3 = Button(gui, width=3, height=2)
# assuming there are three columns
expression_entry.grid(column=0, row=0, columnspan=3, sticky="ew")
number_1.grid(column=0, row=1)
number_2.grid(column=1, row=1)
number_3.grid(column=2, row=1)
gui.mainloop()
I'm trying to find a way to format this tkinter GUI so that I can have widgets in the same column that are different widths. I want to do this so that each label doesn't have an unnecessary amount of white space on either side and can be directly next to its entry box. I've tried shrinking the column, but that obscures the prompt. There might also be another way that I'm not aware of that would format this in a visually appealing way. I am open to any suggestions.
This is what it currently looks like.
import tkinter as tk
responses = ['running', 'reading', 'programming', 'fishing']
prompt_2 = "At what time do you want to do each activity?"
root = tk.Tk()
root.geometry("335x200")
root.title("Schedule Maker")
prompt = tk.Label(
root,
text=prompt_2
)
button = tk.Button(
root,
text="ENTER",
width=10,
height=2
)
button.grid(row=len(responses)+1, column=0)
prompt.grid(row=0, column=0)
prompt['text'] = prompt_2
label0_list = []
label1_list = []
entry0_list = []
entry1_list = []
for w in range(len(responses)):
label0 = tk.Label(root, text=responses[w] + ":")
label0.grid(row=w+1, column=0)
label0_list.append(label0)
label1 = tk.Label(root, text='to')
label1.grid(row=w+1, column=2)
label1_list.append(label1)
entry0 = tk.Entry(root, width=6)
entry0.grid(row=w+1, column=1)
entry0_list.append(entry0)
entry1 = tk.Entry(root, width=6)
entry1.grid(row=w+1, column=3)
entry1_list.append(entry1)
root.mainloop()
Think of tk.Tk() as a rectangle of space where you can put in your content.
The content is managed by the geometry manager of your choice, like pack or grid.
Sometimes people call these rectangle of space container.
Frames are used to have a seperated area where you can organize the content, with different settings. So frame are containers in your window. You could use pack in your root and use grid in a frame, without getting any error.
So what I usally do is to imagin the root as filled area of space and I seperate it in my head to some sort of chunks where I place my frames. Like this:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
header = tk.Frame(root)
body = tk.Frame(root)
bottom_line = tk.Frame(root)
header.pack(side='top')
body.pack()
bottom_line.pack(side='bottom')
After this I fill the containers/frames with the content it belongs to like:
#header content
headline = tk.Label(header, text='At what time do you want to do each?')
headline.pack(fill='x')
#body content
first_activity = tk.Label(body,text='running:')
first_from = tk.Entry(body)
first_sep = tk.Label(body, text='to')
first_to = tk.Entry(body)
first_activity.pack(side='left')
first_from.pack(side='left')
first_sep.pack(side='left')
first_to.pack(side='left')
#bottom content
my_button = tk.Button(bottom_line, text='Enter')
my_button.pack(fill='x')
For more details [click]
PS:
If you really want to use grid and your set of envoirment, you could also use
prompt.grid(row=0, column=0,columnspan=4). But it looks a little bit different.
You can use sticky="e" on label0.grid(...):
label0.grid(row=w+1, column=0, sticky="e")
I want to create a window, and content all in center, but I don't know how should I do, please help me.
def about_window():
win_about = tk.Toplevel(win)
win_about.geometry("340x500")
win_about.title("About Us")
win_about.resizable(0,0)
win_about.iconbitmap(r'C:/Users/810810/Desktop/python/eslogo.ico')
frame = tk.Frame(win_about)
frame.grid(row=0, column=2)
img_png = tk.PhotoImage(file = 'est.gif')
label = tk.Label(frame, image = img_png)
label.img_png = img_png
label.grid(row=0, column=1)
Message = 'Version: 1.0'
mess = tk.Label(frame, text=Message)
mess.grid(row=1, column=0)
I've also had a lot of problems with tkinter grid and prefer to use tkinter place.
Below I edited your code to use place instead of grid. anchor refers to the anchor point of the object you are moving around, relx refers to the relative x position as a percentage of the frame it's in (.5 meaning halfway through the frame), and rely refers to the y position in the frame from 0-1.
import tkinter as tk
win_about = tk.Tk()
win_about.geometry("340x500")
win_about.title("About Us")
win_about.resizable(0,0)
label = tk.Label(win_about, text="img_png", fg="black")
label.place(anchor='center', relx =.5, rely=.3)
mess = tk.Label(win_about, text='Version: 1.0', font=12)
mess.place(anchor='center', relx=.5, rely=.7)
win_about.mainloop()
this should work (It worked on my ubuntu 16 with python 2.7)
it opens 2 windows ,is that wanted or unwanted ?
it displays an image in the center and your text below.
it works by adding " " strings, just like neeraj nair suggested. (he suggested placing anything to adjust layout.)
(# Elvis Fan: i know you use windows, but it should work for windows too.)
import Tkinter as tk
def about_window():
win_about = tk.Toplevel()
win_about.geometry("340x500")
win_about.title("About Us")
win_about.resizable(0,0)
frame = tk.Frame(win_about)
frame.grid(row=0, column=2)
for i in range(0,12):
Message = " "
mess = tk.Label(frame, text=Message)
mess.grid(row=i, column=0)
img_png = tk.PhotoImage(file = 'gbsnode.png')
label = tk.Label(frame, image = img_png)
label.img_png = img_png
label.grid(row=21, column=2)
Message = ' '
mess = tk.Label(frame, text=Message)
mess.grid(row=23, column=1)
Message = 'Version 1'
mess = tk.Label(frame, text=Message)
mess.grid(row=24, column=2)
frame.mainloop()
about_window()
while True:
pass
I'm using a simple code that displays the square root of a number in a label, but for some reason the values get overlaped in a way that I couldn't avoid it, which means that, if I use it for a number that has a exact square root, then the answer goes messed up with the previous answer of many digits.
I've been use the next code so far:
from Tkinter import *
def square_calc():
x = x_val.get()
sqx = x ** 0.5
print x, "** 0.5 =", sqx
sqx_txt = Label(root, text = "x ** 0.5 =").grid(row=3, column=0)
sqx_lab = Label(root, text = sqx).grid(row=3, column=1)
root = Tk()
root.title("Calculating square root")
x_val = DoubleVar()
x_lab = Label(root, text = "x").grid(row=0, column=0)
nmb = Entry(root, textvariable = x_val).grid(row=0, column=1)
calc = Button(root, text = "Calculate", command=square_calc).grid(columnspan=2)
y_lab = Label(root, text = " ").grid(row=3, column=0)
root.mainloop()
The problem is that, every time you call square_calc(), you are simply creating and placing another Label. The right way to do this is to create a Label outside the function, then have the function update the Label's text with mylabel.config(text='new text').
The display is getting messed-up because every time your square_calc() function is called it creates new pair of Labels, but this may leave some parts of any previous ones visible. Since the one on the left is the same every time, so it's not noticeable with it, but the text in one on the right in column 1 is potentially different every time.
A simple way to fix that is to make the Label a global variable and create it outside the function, and then just change its contents in the function. As with all Tkinter widgets, this is can be done after it's created by calling the existing obj's config() method.
Here's a minimally-modified version of your code that illustrates doing that. Note, it also adds a sticky keyword arugment to the grid() method call for the label to left-justify it within the grid cell so it's closer to the text label immediately to its left (otherwise it would be center-justified within the cell).
from Tkinter import *
def square_calc():
x = x_val.get()
sqx = x ** 0.5
# print x, "** 0.5 =", sqx
sqx_txt = Label(root, text = "x ** 0.5 =").grid(row=3, column=0)
sqx_lab.config(text=sqx)
sqx_lab.grid(row=3, column=1, sticky=W)
root = Tk()
root.title("Calculating square root")
x_val = DoubleVar()
x_lab = Label(root, text = "x").grid(row=0, column=0)
nmb = Entry(root, textvariable = x_val).grid(row=0, column=1)
calc = Button(root, text = "Calculate", command=square_calc).grid(columnspan=2)
y_lab = Label(root, text = " ").grid(row=3, column=0)
sqx_lab = Label(root, text = " ")
root.mainloop()
There's another potentially serious flaw in your code. All those assignments of the form
variable = Widget(...).grid(...)
result in assigning the value None to the variable because that's what the grid() method returns. I didn't fix them because they do no harm in this cause since none of those variables are ever referenced again, but it would have been a problem if the new globally variable sqx_lab had been done that way since it is referenced elsewhere.