Creating a rectangle class that accepts parameters - python-3.x

I am trying to create a create a rectangle class that accepts length and width as parameters. I would like the user to be able to enter a number and have python calculate the perimeter of the rectangle.
I tried using Input() to allow the user to do this, but python does not like that. I also tried using raw_input but, I received a 'this is not-defined' error.
I was hoping someone could point me in the right direction.
class circle:
def __init__ (self):
self.radius = 1
self.width = 1
self. length = 1
my_circle = circle ()
print(2 * 3.14 * my_circle.radius)
my_circle.radius = input('Input here:')
print(float(2 * 3.14 * my_circle.radius))
my_circle.radius = 48
print(2 * 3.14 * my_circle.radius)
I would like to enter length and width and have the perimeter returned. I also will do this for the area, but I should be able to replicate the perimeter code once I figure it out.

To begin with, you can use the __init__ constructor to pass your length and width argument instead of doing a attribute assignmnent like rectange.width = ...
So the Rectangle class will look like. You can see I am passing width and length in the constructor
class Rectangle:
def __init__ (self, width, length):
self.width = width
self.length = length
def perimeter(self):
return 2*(self.length + self.width)
After this, you can call your class and function like so.
Here I convert the width and length to float (which you did not do in your circle class), pass them when I create the object of the class and then calculate parameter
length = float(input('enter length:'))
width = float(input('enter width:'))
rectangle = Rectangle(length, width)
print( rectangle.perimeter())
A sample run will then look like
enter length:5
enter width:10
30.0
Similarly your circle class will look like
class circle:
def __init__ (self, radius):
self.radius = radius
def area(self):
return 2*3.14*self.radius
radius = float(input("Enter radius of circle"))
my_circle = circle (radius)
print(my_circle.area())
#Enter radius of curcle1
#6.28

Related

TypeError : Circle() takes no arguments

I'm getting the error TypeError : Circle() takes no arguments when trying to run the code above. Does anyone know what I'm missing?
class Circle:
is_shape = True
radius,color=0,""
def __init__(self, color, radius):
self.color = color
self.radius = radius
def display(self):
print("radius:",self.radius)
print("color:",self.color)
first_circle = Circle("red",2)
first_circle.display()
Actually you have an indentation problem in your code. Your functions aren't defined under classes, that's why it shows your class Circle() takes no argument.
To correct this put your functions inside a class :
class Circle:
is_shape = True
radius, color = 0, ""
def __init__(self, color, radius):
self.color = color
self.radius = radius
def display(self):
print("radius:", self.radius)
print("color:", self.color)
first_circle = Circle("red", 2)
first_circle.display()

How do I simulate a Scrollbar in tkInter Canvas

I'm creating a game launcher specially in Python 3.7 tkInter, and I want to make my own styled Scrollbar (in Windows 10 (version 1903)).
I've tried adding a hidden Scrollbar, and hiding works but i can't simulate it:
def scroll(self, i, reqHeight, vbarValue):
print("vbarValue", vbarValue)
value = -i / 1.4
a1 = int(self.canvass.coords(self.scroll2)[1]) == 5
a2 = value > 0
a = not(a1 ^ a2)
b1 = ((self.canvass.coords(self.scroll2)[3] > self.cHeight))
b2 = value < 0
b = not(b1 ^ b2)
print(value, value < 0)
print(a1, 5)
print("====")
print(a1, a2)
print(a)
print("----")
print(b1, b2)
print(b)
print("====\n\n")
print("OK")
x1, y1, x2, y2 = self.canvass.coords(self.scroll2)
_y1, _y2 = vbarValue
print("1:",y1, y2)
print("2:",_y1, _y2)
print("3:",(_y2 - _y1) / 2 - y2)
print("4:",(_y1 + (_y2 - _y1) / 120) * self.cHeight)
print("5:",(_y1 + (_y2 - _y1) / 120) * self.cHeight - (y2 / y1))
print("6:",((_y2 - _y1) / 120) * self.cHeight - y2* -i)
print("7:",(_y1 + (_y2 - _y1) / 120))
value = (_y1 + (_y2 - _y1) / 120) * self.cHeight / (y1 / y2)
print("8:",(y2 / y1))
# value = value - (y1 / y2)
print("Dynamic Canvas Region Height:")
print("DCRH:", self.cHeight)
print("Value: %s", value)
self.canvass.move(self.scroll2, 0, -y2)
self.canvass.move(self.scroll2, 0, value)
print("coords: %s" % self.canvass.coords(self.scroll2))
print("reqHeight: %s" % reqHeight)
Event:
def _bound_to_mousewheel(self, event): # <Enter> Event
self.canv.bind_all("<MouseWheel>", self._on_mousewheel)
def _unbound_to_mousewheel(self, event): # <Leave> Event
self.canv.unbind_all("<MouseWheel>")
def _on_mousewheel(self, event): # <Configure> Event
self.canv.yview_scroll(int(-1 * (event.delta / 120)), "units")
self.scrollCommand(int(-1 * (event.delta / 120)), self.scrollwindow.winfo_reqheight(), self.vbar.get())
def _configure_window(self, event):
# update the scrollbars to match the size of the inner frame
size = (self.scrollwindow.winfo_reqwidth(), self.scrollwindow.winfo_reqheight()+1)
self.canv.config(scrollregion='0 0 %s %s' % size)
# if self.scrollwindow.winfo_reqwidth() != self.canv.winfo_width():
# # update the canvas's width to fit the inner frame
# # self.canv.config(width=self.scrollwindow.winfo_reqwidth())
# if self.scrollwindow.winfo_reqheight() != self.canv.winfo_height():
# # update the canvas's width to fit the inner frame
# # self.canv.config(height=self.scrollwindow.winfo_reqheight())
By the way, self.scrollCommand(...) is the same as scroll on the first code.
I expect to get some x and y output for the canvas.move method.
How do i simulate a Scrollbar in Tkinter Canvas
The scrollbar has a well defined interface. To simulate a scrollbar all you need to do is implement this interface. This is most easily done by creating a class that has the following attributes:
you need to define the set method, which is called whenever the widget being scrolled wants to update the scrollbar
you need to add mouse bindings to call the yview method of the widget being controlled by the scrollbar (or xview if creating a horizontal widget).
If you do those two things, your scrollbar can be used exactly like a built-in scrollbar.
For the rest of this answer, I'm going to assume you want to simulate a vertical scrollbar. Simulating a horizontal scrollbar works identically, but instead of 'top' and 'bottom', you are dealing with 'left' and right'.
Defining the set method
The set method will be called with two fractions. The canonical documentation describes it like this:
This command is invoked by the scrollbar's associated widget to tell the scrollbar about the current view in the widget. The command takes two arguments, each of which is a real fraction between 0 and 1. The fractions describe the range of the document that is visible in the associated widget. For example, if first is 0.2 and last is 0.4, it means that the first part of the document visible in the window is 20% of the way through the document, and the last visible part is 40% of the way through.
Defining the bindings
The other half of the equation is when the user interacts with the scrollbar to scroll another widget. The way this happens is that the scrollbar should call the yview command of the widget to be controlled (eg: canvas, text, listbox, etc).
The first argument you must pass to the command is either the string "moveto" or "scroll".
If "moveto", the second argument is a fraction which represents the amount that has been scrolled off of the top. This is typically called when clicking on the scrollbar, to immediately move the scrollbar to a new position
if "scroll", the second argument is an integer representing an amount, and the third argument is either the string "units" or "pages". The definition of "units" refers to the value of the yscrollincrement option. "pages" represents 9/10ths of the window height. This is typically called when dragging the mouse over the scrollbar.
The options are spelled out in the man pages for each scrollable widget.
Example
The following is an example of a uses a text widget, so that you can see that when you type, the scrollbar properly grows and shrinks. If you click anywhere in the scrollbar, it will scroll to that point in the documentation.
To keep the example short, this code doesn't handle dragging the scrollbar, and it hard-codes a lot of values that probably ought to be configurable. The point is to show that all you need to do to simulate a scrollbar is create a class that has a set method and which calls the yview or xview method of the connected widget.
First, the scrollbar class
import tkinter as tk
class CustomScrollbar(tk.Canvas):
def __init__(self, parent, **kwargs):
self.command = kwargs.pop("command", None)
tk.Canvas.__init__(self, parent, **kwargs)
# coordinates are irrelevant; they will be recomputed
# in the 'set' method
self.create_rectangle(0,0,1,1, fill="red", tags=("thumb",))
self.bind("<ButtonPress-1>", self.on_click)
def set(self, first, last):
first = float(first)
last = float(last)
height = self.winfo_height()
x0 = 2
x1 = self.winfo_width()-2
y0 = max(int(height * first), 0)
y1 = min(int(height * last), height)
self.coords("thumb", x0, y0, x1, y1)
def on_click(self, event):
y = event.y / self.winfo_height()
self.command("moveto", y)
Using the class in a program
You would use this class exactly like you would a native scrollbar: instantiate it, and set the command to be the yview command of a scrollable widget.
This example uses a text widget so you can see the scrollbar updating as you type, but the exact same code would work with a Canvas, or any other scrollable window.
root = tk.Tk()
text = tk.Text(root)
sb = CustomScrollbar(root, width=20, command=text.yview)
text.configure(yscrollcommand=sb.set)
sb.pack(side="right", fill="y")
text.pack(side="left", fill="both", expand=True)
with open(__file__, "r") as f:
text.insert("end", f.read())
root.mainloop()

Adding a attribute to an instance

I have the below code...
import math
class Circle:
"""Class to create Circle objects"""
def __init__(self, radius=1):
"""Circle initializer"""
self.radius = radius
#property
def area(self):
"""Calculate and return the area of the Circle"""
return math.pi * self.radius ** 2
#property
def diameter(self):
"""Calculate and return the diameter of the Circle"""
return self.radius * 2
#diameter.setter
def diameter(self, diameter):
"""Set the diameter"""
self.radius = diameter / 2
def __str__(self):
return 'Circle of radius {}'.format(self.radius)
def __repr__(self):
return "Circle(radius={})".format(self.radius)
I want to add an attribute radius_log to the instance. It is a list which would contain radius values which have belonged to the circle as well as the current radius value as the last item in the list. The other properties must still work. I know I have to make the radius a property and add a setter property for the radius. Below is an example output...
circle = Circle()
circle
Circle(radius=1)
circle.radius_log
[1]
circle.radius = 2
circle.diameter = 3
circle
Circle(radius=1.5)
circle.radius_log
[1, 2, 1.5]
circle2 = Circle(radius=2)
circle2.radius_log
[2]
Any ideas on how to do this?
Change radius to property and add new property radius_log.
Inside radius property setter you will add value to _property_log list in every change. This log will be exposed through radius_log property:
import math
class Circle:
"""Class to create Circle objects"""
def __init__(self, radius=1):
"""Circle initializer"""
self.radius = radius
#property
def radius(self):
return self._radius
#radius.setter
def radius(self, value):
self._radius = getattr(self, '_radius', None)
if self._radius == value:
return
self._radius_log = getattr(self, '_radius_log', [])
self._radius_log.append(value)
self._radius = value
#property
def radius_log(self):
return self._radius_log[:]
#property
def area(self):
"""Calculate and return the area of the Circle"""
return math.pi * self.radius ** 2
#property
def diameter(self):
"""Calculate and return the diameter of the Circle"""
return self.radius * 2
#diameter.setter
def diameter(self, diameter):
"""Set the diameter"""
self.radius = diameter / 2
def __str__(self):
return 'Circle of radius {}'.format(self.radius)
def __repr__(self):
return "Circle(radius={})".format(self.radius)
circle = Circle()
print(circle)
print(circle.radius_log)
circle.radius = 2
circle.diameter = 3
print(circle)
print(circle.radius_log)
circle2 = Circle(radius=2)
print(circle2.radius_log)
This prints:
Circle of radius 1
[1]
Circle of radius 1.5
[1, 2, 1.5]
[2]

Draw n-sided regular polygon with center point, radius and coords of one vertex

Not sure if this should be posted as a programming question or a math question but I need to draw an n-sided regular polygon providing center, radius, and end coords of one edge.
Here is my code so far, but it is only able to draw the polygon with the right most edge of the polygon vertical:
from tkinter import *
import math
class App:
def __init__(self, master):
self.w = Canvas(width=800, height=600, bg='black')
self.w.draw_regular_polygon((400,400), 100, 3, outline='green')
self.w.grid(row=0, column=0)
def _draw_regular_polygon(self, center, radius, n, **kwargs):
coord_list = []
for i in range(n):
coord_x = center[0] + radius * math.cos((math.pi/n) * (1 + 2 * i))
coord_y = center[1] + radius * math.sin((math.pi/n) * (1 + 2 * i))
coord_list.append(coord_x)
coord_list.append(coord_y)
return self.create_polygon(coord_list, **kwargs)
Canvas.draw_regular_polygon = _draw_regular_polygon
root = Tk()
app = App(root)
root.mainloop()
I need to be able either provide the end points of the vertical line or be able to spin the polygon so that each point in oriented in a specified direction.
My end goal with this project is to draw an lattice of n-sided regular polygons. I am using tkinter because it is the package I am most familiar with but I would be willing to learn a different one if there is one that can handle it better, but not a package that will draw the lattice for me. I would like to be able to understand the composition of the lattice rather than just have it drawn for me.
Add an additional rotation angle to your function; add that constant value to the rotation around the circle that creates the coordinate list.
I've slightly re-ordered your coordinate system, and added a fix value so the bottom line is always drawn straight at an angle of 0. To rotate to a next half-interval between two points, add math.pi/n as an angle.
from tkinter import *
import math
class App:
def __init__(self, master):
self.w = Canvas(width=800, height=600, bg='black')
self.w.draw_regular_polygon((400,400), 100, 5, 0, outline='green')
self.w.draw_regular_polygon((400,400), 100, 5, math.pi/5, outline='red')
self.w.grid(row=0, column=0)
def _draw_regular_polygon(self, center, radius, n, angle, **kwargs):
angle -= (math.pi/n)
coord_list = [[center[0] + radius * math.sin((2*math.pi/n) * i - angle),
center[1] + radius * math.cos((2*math.pi/n) * i - angle)] for i in range(n)]
return self.create_polygon(coord_list, **kwargs)
Canvas.draw_regular_polygon = _draw_regular_polygon
root = Tk()
app = App(root)
root.mainloop()
Result:
(That said: the only repeating n-side polygon lattices are for n = [3,4,6] where the only problematic one is 3, which you could have hard-coded.)

Beginner Pygame, Scores not updating/Variables not being found

So to preface this, I am a Education student whos minor is computer science. My main focus is not coding and I may have made some big mistakes in here that I have not seen yet. My current issue is that I will receive the error
"Traceback (most recent call last):
File "/home/user/Downloads/PongV1.py", line 158, in <module>
main()
File "/home/user/Downloads/PongV1.py", line 13, in <module>
game.play()
File "/home/user/Downloads/PongV1.py", line 42, in <module>
self.update()
File "/home/user/Downloads/PongV1.py", line 77, in <module>
self.ball.move()
File "/home/user/Downloads/PongV1.py", line 136, in <module>
game.score2 = game.score2 + 1
builtins.NameError: name 'game' is not defined
Whenever I try to run this game. I know it is currently in downloads, but I'm running this off of a hastily put together VM machine.As far as I know, I called my score 1/score 2 Variable decently well.
The goal of what I am trying to do is get the scores in the corners to update when the ball hits the wall. Currently, that is located in the def move section
This is what my screen looks like when I try to run this program
Thank you all for looking!
# pygame v2
import pygame
import uaio
import math
import time
from pygame.locals import *
# User-defined functions
def main():
surface = create_window()
game = Game(surface)
game.play()
pygame.quit()
# Create window
def create_window():
pygame.init()
surface_size = (700,600)
title = 'Pong'
surface = pygame.display.set_mode(surface_size)
pygame.display.set_caption(title)
return surface
# define class games
class Game:
def __init__ (self, surface):
self.surface = surface #locations and surface colors of games
self.bg_color = pygame.Color('black')
self.pause_time = 0.01
self.close_clicked = False
self.continue_game = True
self.ball = Ball(pygame.Color('white'),[350,300],5,[6,2], surface)
self.paddle= Paddle(pygame.Color('white'),(100,300),100,100, surface)
self.score1 = 0
self.score2 = 0
def play(self): #playing the game while the game is not closed
self.draw()
while not self.close_clicked:
self.handle_event()
if self.continue_game:
self.update()
self.decide_continue
self.draw()
time.sleep(self.pause_time)
def handle_event(self): #continuing the game
event = pygame.event.poll()
if event.type == QUIT:
self.close_clicked = True
def draw(self): #drawing the balls and paddles
self.surface.fill(self.bg_color)
self.ball.draw()
self.paddle.draw()
self.draw_score()
pygame.display.update()
def draw_score(self):
string = str(self.score1)
location = 0,0
size = 80
#fg_color = pygame.Color('white')
uaio.draw_string(string, self.surface,location,size)
string = str(self.score2)
location = 650,0
size = 80
#fg_color = pygame.Color('white')
uaio.draw_string(string, self.surface,location,size)
def paddlecollide(self):
self.paddle.collide_right(x, y)
self.paddle.collidge_left(x, y)
def update(self): #updating the movement of the ball
self.ball.move()
self.ball.collide(self.paddle)
def decide_continue(self): # deciding to continue teh game
pass
class Paddle: #defining paddle
def __init__(self, color, left, width, height, surface):
#location of paddle etc
self.color = color
self.left = left
self.surface = surface
self.width = width
self.height = height
self.paddle1 = pygame.Rect(140,270,20,80)
self.paddle2 = pygame.Rect(540,270,20,80)
#return self.paddle1, self.paddle2
def draw(self):
#drawing paddle
pygame.draw.rect(self.surface, self.color, self.paddle1)
pygame.draw.rect(self.surface, self.color, self.paddle2)
def collide_left(self, x, y):
return self.paddle1.collidepoint(x, y)
def collide_right(self, x, y):
return self.paddle2.collidepoint(x, y)
class Ball: #defining ball
def __init__(self, color, center, radius, velocity, surface):
#charactersitics of said ball
self.color = color
self.center = center
self.radius = radius
self.velocity = velocity
self.surface = surface
def draw(self):
#drawing the ball
pygame.draw.circle(self.surface, self.color, self.center, self.radius)
def move(self):
# how the ball moves as well as ist velocity
size = self.surface.get_size()
for coord in range(0, 2):
self.center[coord] = (self.center[coord] + self.velocity[coord])
if self.center[coord] < self.radius:
self.velocity[coord] = -self.velocity[coord]
Game.score1 = Game.score1 + 1
if self.center[coord] + self.radius > size[coord]:
self.velocity[coord] = -self.velocity[coord]
Game.score2 = Game.score2 + 1
def collide(self, paddles):
xcoord =0
if paddles.collide_left(self.center[0], self.center[1]):
self.velocity[xcoord] = -self.velocity[xcoord]
if paddles.collide_right(self.center[0], self.center[1]):
self.velocity[xcoord] = -self.velocity[xcoord]
#if x_velocity <= 0:
# collide = False
#
#else: collide = True
main()
The problematic line is this one (in your given code):
Game.score2 = Game.score2 + 1
There are two things wrong with this line:
Firstly, you are trying to use a variable that doesn't exist. Game is the name of a class that you have defined, you must create a new Game object and assign it to a variable before it can be used. I see that you have, which leads me onto problem 2...
Scope. You have defined the variable game in the function main. However, this variable will have been created locally. It cannot be accessed anywhere but the function it was defined in (with some exceptions). I recommend reading this stackoverflow answer to understand scope a little better.
score1 and score2 are both defined within the Games class. In the main function (line 12), a new Games object is created, and assigned to the variable games. This variable is local, and can only be accessed within the function main.
Now, you have 2 options. The first option would be to remove the variables score1 and score2 from the Games class altogether, and have them as separate variables defined in the main body of the program. This would allow them to be accessed anywhere (obviously you would have to change any references to game.score1 or game.score2.
The second, and in my opinion preferable option, would be to make the variable game a global variable. In your main function, the code would look like this:
def main():
surface = create_window()
global game
game = Game(surface)
game.play()
pygame.quit()
Then, remember to de-capitalise any references to the Game class outside of your main function, so that your using the variable game, lie so:
Game.score1 = Game.score1 + 1
becomes
game.score1 = game.score1 + 1
I hope I explained this clearly enough. I would really recommend reading up on how scope and classes work in python before delving too far into pygame.

Resources