Why is turtle not drawing in Python 3 in Line class? - python

I am writing a Line class to draw a line given the coordinates of two points. However, when I run this program, the turtle does not draw anything. Is there an error in the way I defined my Draw() method or called it? I'm not very familiar with Python3 and classes. Here is my code:
from turtle import *
g = Turtle()
class Line():
def __init__(self, x1, y1, x2, y2):
self.X1 = x1
self.Y1 = y1
self.X2 = x2
self.Y2 = y2
self.Draw(x1, y1, x2, y2)
def getX1():
return self.X1
def getY1():
return self.Y1
def getX2():
return self.X2
def getY2():
return self.Y2
def Draw(self, x1, y1, x2, y2):
g.penup()
g.goto(x1, y1)
g.pendown()
g.goto(x2, y2)
def main():
theLine = Line(0, 0, 100, 100)
theLine.Draw()

The function Draw you defined takes 5 arguments (self, x1, y1, x2, y2). But what you want is to get the coordinates information from the Line object.
That's why the self parameter exists. The self parameter is the object itself, so instead of using x1, y1, x2 and y2, you want to use the values stored in the object, like so:
self.x1, self.y1, self.x2 and self.y2. after you change the these, you should also remove the unnecessary arguments of the function (everything except self)
Final code
def Draw(self): # Removed the arguments
g.penup()
g.goto(self.X1, self.Y1) # Go to the starting point stored in the object
g.pendown()
g.goto(self.X2, self.Y2) # Go to the endpoint stored in the object

Related

How should I fix code where the rectangle I created with tkinter doesn't move with the arrow keys?

I am trying to create a program that draws a rectangle in the center of the canvas. The rectangle is supposed to get wider when the right arrow key is pressed, and narrower when the left arrow key is pressed. I seem to have the rectangle, but there is no movement.
So far, the code I have is:
from tkinter import *
root = Tk()
canvas = Canvas(root, width=400, height=300, bg="#000000")
canvas.pack()
x1 = 150
y1 = 100
x2 = 250
y2 = 200
class ResizeRect:
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.rect = canvas.create_rectangle(0,0,1,1)
def draw(self):
canvas.delete(self.rect)
self.rect = canvas.create_rectangle(x1, y1, x2, y2,
outline="#00B000", width=2)
def narrower(self):
self.x1 = self.x1 + 5
self.x2 = self.x2 - 5
def wider(self):
self.x1 = self.x1 - 5
self.x2 = self.x2 + 5
r = ResizeRect(150, 100, 250, 200)
r.draw()
def left():
r.narrower()
def right():
r.wider()
canvas.bind_all('<KeyPress-Left>', left)
canvas.bind_all('<KeyPress-Right>', right)
WHen I run this code, a rectangle appears but does not move when I press the arrow keys. How can I fix this without altering my original code too much?
You have two problems. First, left and right will automatically be passed an object representing the event. You need to make sure that these functions accept this parameter even if you don't use it.
def left(event):
r.narrower()
def right(event):
r.wider()
Second, simply setting the coordinate won't cause the rectangle to move. You must configure the rectangle with new coordinates using the coords method if you want the coordinates of the actual object to change.
def narrower(self):
self.x1 = self.x1 + 5
self.x2 = self.x2 - 5
canvas.coords(self.rect, self.x1, self.y1, self.x2, self.y2)
def wider(self):
self.x1 = self.x1 - 5
self.x2 = self.x2 + 5
canvas.coords(self.rect, self.x1, self.y1, self.x2, self.y2)

How can I bind KeyRelease of any spefic key in tkinter?

In the following code I'm trying to make two different rectangles change their color separately, each time I release key "d" for the first rectangle and key "f" for the second one(this is because otherwise the user can just freely hold one of the two keys and increase the click count without any difficulty), but I don't know how to bind a KeyRelease of any specific key.
from tkinter import *
import time
def round_rectangle(canvas ,x1, y1, x2, y2, radius=25, **kwargs):
points = [x1+radius, y1,
x1+radius, y1,
x2-radius, y1,
x2-radius, y1,
x2, y1,
x2, y1+radius,
x2, y1+radius,
x2, y2-radius,
x2, y2-radius,
x2, y2,
x2-radius, y2,
x2-radius, y2,
x1+radius, y2,
x1+radius, y2,
x1, y2,
x1, y2-radius,
x1, y2-radius,
x1, y1+radius,
x1, y1+radius,
x1, y1]
return canvas.create_polygon(points, **kwargs, smooth=True)
def click_one(event):
global Clicks
MainCanvas.itemconfig(FirstButton, fill="#ff0000")
window.update()
time.sleep(0.05)
MainCanvas.itemconfig(FirstButton, fill="#111111")
Clicks += 1
ClicksVar.set(Clicks)
def click_two(event):
global Clicks
MainCanvas.itemconfig(SecondButton, fill="#ff0000")
window.update()
time.sleep(0.05)
MainCanvas.itemconfig(SecondButton, fill="#111111")
Clicks += 1
ClicksVar.set(Clicks)
window = Tk()
window.geometry("960x600")
window.config(bg="#000000")
Clicks = 0
ClicksVar = IntVar()
window.bind("<KeyRelease>", click_one)
window.bind("<KeyRelease>", click_two)
MainCanvas = Canvas(window, width=960, height=600, bg="#000000")
MainCanvas.pack()
FirstButton = round_rectangle(MainCanvas ,385, 255, 475, 345, fill="#111111")
SecondButton = round_rectangle(MainCanvas ,485, 255, 575, 345, fill="#111111")
ClickLabel = Label(MainCanvas, font=("Premium", 15), width=3, height=1, textvariable=ClicksVar, bg="#111111", fg="#777777")
ClickLabel.place(x=462, y=350)
window.mainloop()
That would be the answer to your question.
If your ad an if-statement to the keydown and keyup-function you have a binding for a specific key.
def keydown(e):
print(e.char)
def keyup(e):
print(e.char)
widget.bind("<KeyPress>", keydown)
widget.bind("<KeyRelease>", keyup)
How can I bind KeyRelease of any spefic key in tkinter?
You can specify the specific key along with KeyRelease. For example, the following code calls click_one when the "d" key is released, and click_two when the "f" key is released.
window.bind("<KeyRelease-d>", click_one)
window.bind("<KeyRelease-f>", click_two)
For the authoritative documentation on event specifiers, see Event Patterns in the tcl/tk manual pages.
I use this when I want to bind a key to do an action. You can try the following:
import keyboard
shortcut = "F1"
if keyboard.is_pressed(shortcut):
<yourcode>

Tkinter Rectangle connected to Keypress

The following program draws a rectangle in the center of the canvas. The rectangle is supposed to get wider when the right arrow key is pressed, and narrower when the left arrow key is pressed.
Here's the code:
from tkinter import *
root = Tk()
canvas = Canvas(root, width=400, height=300, bg="#000000")
canvas.pack()
x1 = 150
y1 = 100
x2 = 250
y2 = 200
class ResizeRect:
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.rect = canvas.create_rectangle(0,0,1,1)
def draw(self):
canvas.delete(self.rect)
self.rect = canvas.create_rectangle(x1, y1, x2, y2,
outline="#00B000", width=2)
def narrower(self):
self.x1 = self.x1 + 5
self.x2 = self.x2 - 5
def wider(self):
self.x1 = self.x1 - 5
self.x2 = self.x2 + 5
r = ResizeRect(150, 100, 250, 200)
r.draw()
def left(event):
r.narrower()
r.draw()
def right(event):
r.wider()
r.draw()
canvas.bind_all('<KeyPress-Left>', left)
canvas.bind_all('<KeyPress-Right>', right)
My teacher told me that I need to add the 'self' keyword to the parameters in the draw function but I don't know what he means. (I can't ask him more because he's in a bad mood right now.). Any help is much appreciated.

Constructing Rectangular with Python

Is there any way to make area() refer to check()?
Currently, codes of check() is the same in area().
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.x2 = x2
self.y1 = y1
self.y2 = y2
def check(self): #Checking this rectangle
if abs(self.x1-self.x2) == 0 or abs(self.y1-self.y2)==0:
return False
else :
return True
def area(self): #Calculating width
if abs(self.x1-self.x2) == 0 or abs(self.y1-self.y2)==0:
return False
else :
area = abs(self.x1-self.x2)*abs(self.y1-self.y2)
return area
In your check(self) method, you don't need any if nor abs().
You can just do:
def check(self):
return self.x1 != self.x2 and self.y1 != self.y2
About the area(self) method, you could just do:
def area(self):
if not self.check():
return False
else:
return abs(self.x1-self.x2)*abs(self.y1-self.y2)
Now your code should be cleaner.

Getting point coordinates in Matplotlib plot

I'm using Ipython interpreter in Spyder environment.
I would like to write a script to crop all the images in a folder at the same dimension.
I plot the *.jpg image using Matplotlib. I would like to be able to use the mouse to point two corners on the picture that would correspond to the top-left and bottom-right of the new picture.
I have written a code like that
import os
import scipy.ndimage as nd
import matplotlib.pyplot as plt
plt.close('all')
class Conoscopia:
def __init__(self, cono, nome):
self.x1 = 0.0
self.y1 = 0.0
self.x2 = 0.0
self.y2 = 0.0
self.cono = cono
self.nome = nome
def connect(self):
self.cid = self.cono.canvas.mpl_connect('button_press_event', self.onclick)
def onclick(self, event):
if self.x1==0.0 and self.y1==0.0:
self.x1=event.xdata
self.y1=event.ydata
print "x1 = ", event.xdata, " y1 = ", event.xdata
elif self.x2==0.0 and self.y2==0.0:
self.x2=event.xdata
self.y2=event.ydata
print "x2 = ", event.xdata, " y2 = ", event.xdata
def return_coo(self):
return self.x1, self.x2, self.y1, self.y2
def disegna(self):
plt.imshow(self.nome)
plt.show()
plt.ioff()
files = os.listdir(os.getcwd())
lista_nomi=[]
for nome in files:
if nome[len(nome)-4:len(nome)] == '.JPG' or nome[len(nome)-4:len(nome)] == '.jpg':
lista_nomi.append(nome)
foto = nd.imread(lista_nomi[0])
id_f = plt.figure()
cn = Conoscopia(id_f, foto)
cn.connect()
cn.disegna()
x1, y1, x2, y2 = cn.return_coo()
My problem is that the whole code is run at once and that at the end the values of x1, y1, x2 and y2 correspond to the intialization values.
I can then click on the picture to get the four values and if I run in the interpreter x1, y1, x2, y2 = cn.return_coo() they contain the right values.
But what can I do to retrieve them directly in my code and being able to use them?
What I would ideally like is that once that the two clicks are done, the window close and that I can use the coordinates (x1, y1) and (x2, y2) for the rest of my programming.
I have tried to add some extra waiting loop or looping on the function return_coo() until the coordinates are different from the initialization values but this block my computer and I never get the pricture displayed.
Thanks!

Categories