I need to draw a few Polygons using tkinter and so I tried the following code:
from tkinter import *
master = Tk()
w = Canvas(master, width=200, height=200)
w.pack()
points = [0, 0, 200, 100, 0, 200]
w.create_polygon(points, outline="green",fill='yellow', width=0)
mainloop()
and I get the following output
But the problem is... the width isn't being set to 0. Is this is an internal issue with Tkinter or is there a way I can fix this?
You are specifying a color for an outline, so the canvas must draw an outline that is at least one pixel wide in order to show the outline. If you don't want an outline, set outline to None or the empty string.
Related
Quick question, when you put in something like padx = 10, pady = 10 into a Label/Button it will give you a rectangle.
Does anyone know what X by Y is a perfect square?
The width and height of a label is dependent on several factors - the font being used, the image being used, borderwidths, padding, etc. Many of those are symmetrical, however.
If you want a perfect square, you need to either start with an image (which causes width and height attributes to be treated as pixels), or a font where the characters are as wide as they are tall (even if you don't have any text).
Put another way, without an image height and width refer to a number of average size characters. Unless your font is the same in the x and y axis, these attributes will resolve to a different number of pixels. If you include an image in the label -- even just a one pixel image -- then width and height are in units of pixels rather than characters.
Here's an example that creates a square label using an image:
import tkinter as tk
root = tk.Tk()
root.geometry("200x200")
image = tk.PhotoImage(width=1, height=1)
label = tk.Label(root, image=image, width=50, height=50, background="red")
label.place(relx=.5, rely=.5, anchor="c")
root.mainloop()
I wanted to create a transparent box with a red outline between these two specified points at (614, 162) and (759, 306). However, it returns me an invisible or no box at all. But for (100, 50) and (160, 100), the box is visible.
import tkinter as tkr
app = tkr.Tk()
app.title("AI Cashier")
app.geometry("1366x768")
app.wm_attributes("-transparentcolor", "white")
app.config(bg = "White")
can = tkr.Canvas(app,bg = "White",highlightthickness = 0)
can.create_rectangle(100,50,160,100,outline = "red", width = 2)
can.pack()
app.mainloop()
Could anyone explain to me because I'm still new to tkinter. Or is it a bug?
Why does my create_rectangle disappears after specifying these points using tkinter?
It is because the canvas is only a couple hundred pixels wide and tall, so you are drawing outside the visible area of the canvas.
A simple fix for the code in the question is to make the canvas bigger. You can either give it an explicit width and height (eg: can = tkr.Canvas(..., width=800, height=400)), or force the canvas to fill the window (eg: can.pack(fill='both', expand=True')). In either of those cases, the image will be visible.
So I'm creating the game of life in python, and would like to create a grid on top of a canvas using the tkinter class of python. Thanks in advance.
To make the grid I'm using the create_line() function of the canvas class and looping through using the range() function so that my lines are drawn to the width and the height of the canvas, using two separate for loops one for width and one for the height. The loops I have gotten are taken from the following piece of code on stackoverflow: How to create a grid on tkinter in python?
I thought I understood what is happening but what I thought should happen has not
from tkinter import *
from random import *
window = Tk()
window.title('Game Of Life')
canvas = Canvas(window, background='white', width=800, height=600)
def create_grid(canvas):
width = canvas.winfo_width() # gets width of the canvas
height = canvas.winfo_height() # gets height of the canvas
for line in range(0, width, 1): # range(start, stop, step)
canvas.create_line([(line, 0), (line, height)], fill='black', tags='grid_line_w')
for line in range(0, height, 1):
canvas.create_line([(0, line), (width, line)], fill='black', tags='grid_line_h')
create_grid(canvas)
canvas.grid(row=0, column=0)
window.mainloop()
My expected results are to have a white canvas with vertical and horizontal lines stretching the width and height of the canvas. But my actual results are just a white canvas with no lines on top.
I don't trust winfo_width and winfo_height to give accurate values in this context. According to https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.winfo_height-method, the functions simply return 1 if you haven't packed/gridded/placed the widget yet, and even if you have, it might still return 1 if the window's event loop hasn't updated lately. You already know that you want the width to be 800 and the height to be 600, so you may as well define them as such directly.
Another problem is that your range calls have a step argument of 1. This means that the lines will be one pixel apart, which will effectively paint the entire canvas black. I recommend a larger step.
from tkinter import *
from random import *
window = Tk()
window.title('Game Of Life')
def create_grid(window):
width = 800
height = 600
canvas = Canvas(window, background='white', width=width, height=height)
for line in range(0, width, 10): # range(start, stop, step)
canvas.create_line([(line, 0), (line, height)], fill='black', tags='grid_line_w')
for line in range(0, height, 10):
canvas.create_line([(0, line), (width, line)], fill='black', tags='grid_line_h')
canvas.grid(row=0, column=0)
create_grid(window)
window.mainloop()
Result:
I'm trying to change the width of a Message widget in Tkinter by using the width parameter. I couldn't get it to work so I tried align, justify and aspect which all produced the same result - the box remains centred and the width of the text.
Here is my code:
console_Fetch = Message(text="test\ntest\ntest\ntest\ntest",bd=1,relief="sunken",width=300)
console_Fetch.grid(row=7,column=0,padx=5,pady=1,columnspan=2)
I'm obviously using .grid() to pack it into the window.
Here's a screenshot of my window:
Pragmatic answer
Often setting width in widgets is not working as expected, depending on priority of other aspects, cell width, you name it. It gets easily overruled, or depends on other conditions.
What I always do is give the grid a "skeleton" of canvases in adjecent cells, with height (or width) of zero. Subsequently stretch the widget with sticky inside their cells. Just look at the example below:
from tkinter import *
win = Tk()
console_Fetch = Message(text="test\ntest\ntest\ntest\ntest",bd=1,relief="sunken",width=3000)
canvas = Canvas(width = 500, height = 0)
canvas.grid(row=0,column=0)
console_Fetch.grid(row=1,column=0,padx=5,pady=1,columnspan=2, sticky = N+W+E+S)
win.mainloop()
The same I did in shaping the grid in the minesweeper- matrix in this answer.
I am trying to make a tkinter label containing text with width and height defined by pixel dimensions. It is made clear that a label widget containing text's size is defined in terms of its text size in the docs:
If the label displays text, the size is given in text units. If the label displays an image, the size is given in pixels (or screen units). If the size is set to 0, or omitted, it is calculated based on the label contents.
I have tried using this information to achieve what I am trying to do. I want to create labels of fixed width 700 and variable height as I am creating a timetable application. Here's an example of what I have tried so far:
import tkinter as tk
root = tk.Tk()
root.geometry("800x600")
height = 20
label = tk.Label(root,width=700,bg="white",text="test",borderwidth=0,font=("Calibri",height))
label.place(x=10,y=10)
root.mainloop()
This almost achieves what I want in terms of height, but I would expect the height to be 1 pixel when height = 1, but it is actually 5 pixels (I've got very good eyesight!). As for width, its completely off the screen as its 700 times the width of a character.
Using individual frames as each "label" and then creating label widgets as children of these frames does not work either, as the frame just gets resized to fit the label. My question is: is there a way to create a text-containing label sized by pixel dimensions?
I have found a solution in my case. I used a frame, disabled its pack_propagate and made a label the child of this frame. I hope others will find it useful. This question helped me a lot.
import tkinter as tk
root = tk.Tk()
root.geometry("800x600")
height = 20
label_frame = tk.Frame(root,width=700,height=height,bg="white")
label_frame.pack_propagate(0) # Stops child widgets of label_frame from resizing it
tk.Label(label_frame,bg="white",fg="black",text="test",font=("Calibri",15)).pack()
label_frame.place(x=10,y=10)
root.mainloop()
doing a timetable is something that lends itself to using the grid packing method, which has a grid_columnconfigure and a grid_rowconfigure method which can be used to set the minimum and maximum size of a row or column, and the rate at which they expand:
import tkinter as tk
root = tk.Tk()
tk.Label(root, text="Test").grid(column=1, row=1, sticky="nesw")
root.grid_columnconfigure(1, minsize=700)
root.mainloop()