How to draw a face in Python (GUI) - python

Let me preface first with I have only ever worked with Java, so Python is really new to me. As a result, I'm having a lot of trouble even checking whether my programs work. It's frustrating. (By the way, I'm working with Python 2.7)
This currently produces an 'X' that can be moved around when I press the "Eyes" button, but I'm supposed to make a face like the one here: https://www.cs.montana.edu/hunterl/132/labs/Python/
I cannot figure out how to draw the face. I know it has something to do with
c = Circle(Point(50,50), 10)
c.draw(win)
But every time I try to implement it in python, nothing happens. I don't know what I need to do to change the 'X' and make a circle with two smaller circles for eyes and a line for a mouth. Any help would be much appreciated. I'm at a complete loss and seriously just want to give up.
Here's the code:
from button import Button
from tick import Tick
def main():
win = GraphWin("Face Mover", 250, 250)
win.setCoords(0, 0, 10, 10)
win.setBackground("green")
tic = Tick(win, Point(5,5), 2) #the window, middle, size of drawing
eyesButt = Button(win, Point(3, 1), 3, 1, "Eyes")
talkButt = Button(win, Point(7, 1), 3, 1, "Talk")
quitButt = Button(win, Point(5, 9), 2, 1, "Quit")
eyesButt.activate()
talkButt.activate()
quitButt.activate()
pt = win.getMouse()
while not quitButt.clicked(pt):
if eyesButt.clicked(pt):
tic.newSpot(win)
pt = win.getMouse()
win.close()
main()
next class
from graphics import *
from random import randint
class Tick:
def __init__(self, window, center, size):
self.center = center
p1 = Point(randint(1,9), randint(1,8))
self.p2, self.p3 = p1.clone(), p1.clone()
self.p2.move(-.3, -.3)
self.p3.move(.3, .3)
self.p4, self.p5 = p1.clone(), p1.clone()
self.p4.move(-.3, .3)
self.p5.move(.3, -.3)
self.line1 = Line(self.p2, self.p3)
self.line2 = Line(self.p4, self.p5)
self.line1.draw(window)
self.line2.draw(window)
def newSpot(self, window):
self.line1.undraw()
self.line2.undraw()
self.placeSpot()
self.line1 = Line(self.p2, self.p3)
self.line2 = Line(self.p4, self.p5)
self.line1.draw(window)
self.line2.draw(window)
def placeSpot(self):
p1 = Point(randint(1,9), randint(1,8))
self.p2, self.p3 = p1.clone(), p1.clone()
self.p2.move(-.3, -.3)
self.p3.move(.3, .3)
self.p4, self.p5 = p1.clone(), p1.clone()
self.p4.move(-.3, .3)
self.p5.move(.3, -.3)

Problem is
win.setCoords(0, 0, 10, 10)
with
Circle(Point(50,50), 10)
Your circle is outside window so you can't see it.
Remove win.setCoords(0, 0, 10, 10) or use ie. Circle(Point(5,5), 3) to see circle inside window.

Related

Python tkinter get color from canvas

I have created a simple Tkinter application with a canvas widget like this:
from tkinter import *
root = Tk()
root.geometry("500x500-500+500")
canvas = Canvas(root, width = 400, height = 400, bg = "white")
canvas.pack()
canvas.create_line(0, 0, 200, 100, width = 20, fill = "black")
root.mainloop()
My question is, how can I get the color of the canvas in a specific position? Say for instance I clicked somewhere on the line, how can I get back the color "black" from that?
In other words, if I wanted a function like this,
def getColor(cnvs, event = None):
x = event.x
y = event.y
# somehow gets the color of cnvs at position (x, y) and stores it as color
return color
how would I go about doing that?
You can take a screen shot of the canvas using Pillow.ImageGrab module and get the required pixel color from the snapshot image:
from PIL import ImageGrab
def get_color(cnvs, event):
x, y = cnvs.winfo_rootx()+event.x, cnvs.winfo_rooty()+event.y
# x, y = cnvs.winfo_pointerx(), cnvs.winfo_pointery()
image = ImageGrab.grab((x, y, x+1, y+1)) # 1 pixel image
return image.getpixel((0, 0))
Note that the color returned is in (R, G, B) format.

tkinter: Moving objects to random places using a for loop

I use python tkinter and I am trying to move my ark/sun (ONLY 1 onject) to random places across (0,500) to (800,500) using a for loop so every time I run it will be in a new place but i keep failing to do so. If someone could help me it would mean a lot.
from tkinter import *
from random import *
myInterface = Tk()
screen = Canvas( myInterface, width=800, height=800, background="white" )
screen.pack()
#sky
##Sky
y = 0
y2 = 22
skyOptions = ["#4C1D6D","#53236E","#5A2970","#623072","#693674","#703D75",\
"#784377","#7F4979","#86507B","#8E567C","#955D7E","#9C6380",\
"#A46A82","#AB7083","#B27685","#BA7D87","#C18389","#C88A8A",\
"#D0908C","#D7968E","#DE9D90","#E6A391", "#EDAA93","#F4B095"]
for sky in range (1,24):
skyColour = (skyOptions[sky%24])
screen.create_rectangle (0,y,1000,y2, fill = skyColour, outline = skyColour)
y = y + 22
y2 = y2 + 22
#sun (Make it randomly move plz)
screen.create_arc(150, 250, 500, 800 ,start=0, extent=180, fill= "#fd8953", outline = "#fd8953")
screen.update
spacing = 50
for x in range(0, 1000, spacing):
screen.create_line(x, 25, x, 1000, fill="red")
screen.create_text(x, 5, text=str(x), font="Times 9", anchor = N)
for y in range(0, 1000, spacing):
screen.create_line(25, y, 1000, y, fill="blue")
screen.create_text(5, y, text=str(y), font="Times 9", anchor = W)
screen.update()
A simple example of moving a widget on a canvas using the coords() function:
from tkinter import *
from random import *
myInterface = Tk()
screen = Canvas( myInterface, width=800, height=800, background="white" )
screen.pack()
#sun (Make it randomly move plz)
arc = screen.create_arc(150, 250, 500, 800 , start=0, extent=180,
fill= "#fd8953", outline = "#fd8953")
def random_move(event):
# Generate random numbers for x and y between 0 and 99
x = randrange(0, 100)
y = randrange(0, 100)
# Move arc to original + random x, y position
screen.coords(arc, [150+x, 250+y, 500+x, 800+y])
# Create binding so random_move() is easy to invoke.
myInterface.bind('<space>', random_move)
# start mainloop() which runs the application
myInterface.mainloop()
You need to start the application mainloop or the program will just stop after creating the window and widgets. The mainloop listens for events (mouse, keyboard ect).
Also: that was a lot of code, most of which was not relevant to your problem. Try to minimize the code in your questions.
I'm binding <space> to the random_move() function so just hit space for each move.
And; check out The Tkinter Canvas Widget.

Tkinter Key Binding in Different Regions of Window

I am trying to make a Tic Tac Toe program for 2 players, and so I need to be able to have mouse clicks in certain areas of the window do different things. How do I do that? This is what I have so far.
from tkinter import *
# Creates Window
tk = Tk()
canvas = Canvas(tk, width=600, height=600)
tk.title('Tic Tac Toe')
canvas.pack
# Creates Board
line1 = canvas.create_line(200, 0, 200, 600)
line2 = canvas.create_line(400, 0, 400, 600)
line3 = canvas.create_line(0, 200, 600, 200)
line4 = canvas.create_line(0, 400, 600, 400)
# Creates Functions for Xs being placed on board
def x1(event):
canvas.create_line(0, 0, 200, 200)
canvas.create_line(200, 0, 0, 200)
def x2(event):
canvas.create_line(200, 0, 400, 200)
canvas.create_line(400, 0, 200, 200)
# Creates the buttons to put the Xs on the board when clicked DOESN'T WORK
canvas.pack()
canvas.bind("<Button-1>", x1)
canvas.mainloop()
Sorry if I formatted the code wrong. The second to last line is the line I am having trouble with. I want button-1 (mouse click) to be able to do x1 and x2 (and eventually other functions) depending on the region of the window it is on. Please help.
Here is how you can use the event co-ordinates to identify which square of the tic-tac-toe board the user clicked on:
from tkinter import *
# Creates Window
tk = Tk()
width = 600
third = width / 3
canvas = Canvas(tk, width=width, height=width)
tk.title('Tic Tac Toe')
canvas.pack
# Creates Board
canvas.create_line(third, 0, third, width)
canvas.create_line(third*2, 0, third*2, width)
canvas.create_line(0, third, width, third)
canvas.create_line(0, third*2, width, third*2)
def draw_cross(row,col):
canvas.create_line(col * third, row * third, (col + 1) * third, (row + 1) * third)
canvas.create_line((col + 1) * third, row * third, col * third, (row + 1) * third)
def mouse_click(event):
col = int(event.x / third)
row = int(event.y / third)
draw_cross(row,col)
canvas.pack()
canvas.bind("<Button-1>", mouse_click)
canvas.mainloop()
First of all I parametrized the board dimensions using variables width and third - just change width, and everything will resize correctly.
Second, clicking a mouse button on the canvas calls the mouse_click event handler, which obtains the co-ordinates of the point in the canvas on which the mouse was clicked (event.x and event.y), and computes the corresponding row (0, 1 or 2) and column (0, 1 or 2) of the square on the tic-tac-tow board. These are then passed as parameters to the function draw_cross which draws the two diagonals for that square.
Hope that helps.
When function x1 is called in response to a mouse click, the event object has the mouse click x and y co-ordinates (event.x and event.y). Use those to detect which part of the canvas was clicked on and act accordingly.

How can I overlay images with transparencies over a background (which is an image, too) using Python, tkinter, and PIL

If the pics that are supossed to go on the upper layers have transparencies, but they show up with a gray square instead of the said transparency, covering the background.
I am coding a pinball game in Python, using Tkinter and PIL. I'm stuck because I need to display the elements of the game (flippers, bumpers, etc) over a background, however, when I try to overlay them, they show up with a gray square, instead of the transparency they already have.
This is the code:
import sys
from tkinter import *
from PIL import Image, ImageTk
#Secci�³n funciones
def botones():
juego_Nuevo_Boton = Button( menu_Principal, text = ("Juego nuevo"), command = juegoNuevo, font = ("Arial Black", 10), width = 20).place(x = 15, y = 125 )
continuar_Juego_Boton = Button( menu_Principal, text = "Continuar juego", font = ("Arial Black", 10), width = 20) .place(x = 15, y = 160)
cerrar_El_Juego = Button( menu_Principal, text = "Cerrar el juego", command = menu_Principal.destroy, font = ("Arial Black", 10), width = 20).place(x = 15, y = 195 )
def juegoNuevo():
ventana_Juego_Nuevo = Toplevel()
ventana_Juego_Nuevo.geometry("600x700")
ventana_Juego_Nuevo.title("Nueva partida")
imagen_Fondo_Juego_Nuevo = PhotoImage( file = "fondo_Juego.gif" )
fondo_Juego_Nuevo = Label(ventana_Juego_Nuevo, image=imagen_Fondo_Juego_Nuevo)
fondo_Juego_Nuevo.place( x = 0, y = 0, relwidth = 1, relheight = 1 )
fondo_Juego_Nuevo.image = imagen_Fondo_Juego_Nuevo
imagen_lanzador_Canal = PhotoImage( file = "LanzadorCanal.gif" )
Lanzador_Canal = Label(ventana_Juego_Nuevo, image = imagen_lanzador_Canal)
Lanzador_Canal.place( x = 0, y = 0 )
Lanzador_Canal.image = imagen_lanzador_Canal
############################################
#I ALSO TRIED THIS BUT IT SHOWS UP SOME KIND OF IMAGE EDITOR CALLED "IMAGE MAGIC",
#I don't need to edit the pictures, i just need them overlayed, so i can finish the game.
#fondo_Del_Juego = Image.open("fondo_Juego.png")
#lanzador_Canal = Image.open("LanzadorCanal.png")
#fondo_Del_Juego.paste(lanzador_Canal, (0, 0), lanzador_Canal)
#fondo_Del_Juego.show()
#############################################
ventana_Juego_Nuevo.mainloop()
#Crear pantalla y titulo
menu_Principal = Tk()
menu_Principal.title("Pinball - Proyecto : creado por Daniel Bonilla")
menu_Principal.geometry("200x400")
imagen_Fondo_Menu = PhotoImage(file = "MenuPrincipal.gif")
fondo_Menu = Label(menu_Principal, image = imagen_Fondo_Menu)
fondo_Menu.place( x = 0, y = 0, relwidth = 1, relheight = 1 )
botones()
#Llamado a la ventana
menu_Principal.mainloop()
Pay special attention to "JuegoNuevo()" function, there's where the problem is.
So, pretty much, this picture sums up my problem:
*The spring is transparent already, it just doesn't show up that way.
Have in mind that, later on, I need to put all the other elements, collisions,etc... so, that "Image Magic" thing (see the code above), I think, won't work.
*EDIT: I already tried as mentioned in the first answer with PNG files, but the problem is still there.
Use png instead of gif files will fix your problem. Also remove the unused packages:
from PIL import Image, ImageTk

tkinter's canvas.move makes object disappear

I am running a creature simulator in python 2.7 using tkinter as my visualizer. The map is made up of squares, where colors represent land types, and a red square represents the creature. I use canvas.move to move that red square around the board. It has to move quite a lot. But I know exactly where it should start and where it should end. The problem is, instead of moving, most of the time it just disappears. In the code below I call move in Simulation's init, and it works. When I call it any time in sim.simulate, the creature just disappears. Can anyone explain why?
class Map():
def __init__(self,):
self.root = Tk()
self.canvas = Canvas(self.root, width=1200, height=1200)
self.canvas.pack()
self.colors = {
"Land": "grey",
"Food": "green",
"Water": "blue",
"Shelter": "black"
}
self.canvasDict = {} # the keys are (x,y, "type"), the data is the id so it can be grabbed for item config.
for i, row in enumerate(land.landMass):
for j, tile in enumerate(row):
color = self.colors[tile.__class__.__name__]
self.canvasDict[i, j, "tile"] = self.canvas.create_rectangle(50 * i, 50 * j, 50 * (i + 1), 50 * (j + 1),
outline=color, fill=color)
info = tile.elevation
if color == "green":
info = tile.vegitation
elif color == "black":
info = tile.quality
self.canvasDict[i, j, "text"] = self.canvas.create_text(50 * i + 3, 50 * j, anchor=NW, fill="white", text=info)
self.canvasDict["creature"] = self.canvas.create_rectangle(0, 0, 50, 50,
outline="red", fill="red")
self.canvas.pack(fill=BOTH, expand=1)
sim = Simulation([], 1, 2, self.root, self.canvas, self.canvasDict)
self.root.after(1000, sim.simulate)
...
other functions
...
def simulate(self):
self.canvas.move(self.canvasDict["creature"], 1, 1)
if self.generations > 0:
self.root.after(10000, self.canvas.move, self.canvasDict["creature"], 2 * 50, 2 * 50)
...
I finally realized what was happening. I made the mistake of thinking that .move would move the object to that location on the canvas, instead it is moving it by that much. So when my square 'disappears' it is really just moving of the visible canvas. I thought that the .after would stall the movements so that I could see that happen, but apparently not.

Categories

Resources