I decided to make a image editing program using only the array given to me by the matplotlib.pyplot.imread method, but when I try to assign the contents of one pixel to another, it tells me that it: can't assign to function call.
import matplotlib.pyplot as plt
f = plt.imread("GreenScreen.png")
x1 = 250
y1 = 350
x2 = 750
xCount = x2
xCount2 = xCount
xCountStart = x2
xSet = 0
for xCount in range(xCountStart, x1):
xCount2 = (x1 + xCount) / 2
xSet = xCount2
for y1 in range(350, 360):
for xCount2 in range(xSet, xCount):
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
xCount2 = xSet
y1 = 350
plt.imshow(f)
plt.show()
Change your parentheses () to square brackets [], which are used for indices. Something like this should work:
for xCount in range(xCountStart, x1):
xCount2 = (x1 + xCount) / 2
xSet = xCount2
for y1 in range(350, 360):
for xCount2 in range(xSet, xCount):
f[xCount2, y1] = f[xSet, y1]
f[xCount2, y1] = f[xSet, y1]
f[xCount2, y1] = f[xSet, y1]
f[xCount2, y1] = f[xSet, y1]
xCount2 = xSet
y1 = 350
...
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
f(xCount2, y1) = f(xSet, y1)
To set a field in f, use f[xCount2, y1]. Parentheses are used to call a function, square brackets are for indexes.
Related
I managed to find in someone who made a class for rounded buttons in tkinter that works great. However the issue I have is there is always a white border.
I've tried reading through all of the code and changing all of the colour values but to no avail.
Here is an excerpt of the code working, I've tried to format it as nicely as I could:
from tkinter import Tk, Canvas
class RoundedButton(Canvas):
def __init__(self, master=None, text: str = "", radius=25, btnforeground="#007CEE", btnbackground="#ffffff",
clicked=None, font=("Righteous", 25), *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.btnforeground = btnforeground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=font,
justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2] - text_rect[0]:
self["width"] = (text_rect[2] - text_rect[0]) + 10
if int(self["height"]) < text_rect[3] - text_rect[1]:
self["height"] = (text_rect[3] - text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False,
**kwargs): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
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]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2] - text_bbox[0]:
width = text_bbox[2] - text_bbox[0] + 30
if event.height < text_bbox[3] - text_bbox[1]:
height = text_bbox[3] - text_bbox[1] + 30
self.round_rectangle(5, 5, width - 5, height - 5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2] - bbox[0]) / 2) - ((text_bbox[2] - text_bbox[0]) / 2)
y = ((bbox[3] - bbox[1]) / 2) - ((text_bbox[3] - text_bbox[1]) / 2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#DE8500")
self.itemconfig(self.text, fill='#ffffff')
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
self.itemconfig(self.text, fill=self.btnforeground)
window = Tk()
window.geometry("1440x872")
window.configure(bg="#007CEE")
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=0)
download_button_1.place(
x=409,
y=383,
width=621.0,
height=105.0
)
window.mainloop()
EDIT: Furas' answer works perfect, for anyone interested in using this rounded button class I would reccommend changing the splinesteps to a higher value at self.create_polygon to help with smoothing
return self.create_polygon(points, **kwargs, smooth=True, splinesteps=10000)
On Linux works for me
highlightthickness=0
or set color of background
highlightbackground="#007CEE"
eventually
borderwidth=-1
Doc for Canvas (page effbot.org on archive.org) shows all config options.
Before:
After:
2023.01.28:
Using: Pop!_OS 22.04 LTS //Python 3.10.6// Tcl/Tk V.8.6
"borderwidth=-1" did not seem to work, but "highlightthickness=0" appeared to do exactly what I expected.
Resulting button with rounded corners
And I used an exact copy of the code posted in the original question (by: Cai Allin,Mar 10, 2022 at 21:21)
My only changes were in the block for the "Rounded button".
First I tested to change the "borderwidth"
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=-1,
)
But this did not result in any visible change.
I then tested to just below the "borderwidth" add:
highlightthickness=0
And this change succeeded in removing the "white border", and it worked regardless whether the settings for the "borderwidth" was "-1" or "0"
I have made this algorithm myself based on how to rotate an image.
import cv2
import math
import numpy as np
class rotation:
angle = 60.0
x = 100
y = 100
img = cv2.imread('FNAF.png',0)
width,height = img.shape
def showImage(name, self):
cv2.imshow(name, self.img)
def printWidthHeight(self):
print(self.width)
print(self.height)
def rotateImage(self):
ForwardMap = np.zeros((self.width,self.height),dtype="uint8")
BackwardMap = np.zeros((self.width,self.height),dtype="uint8")
for i in range(self.width):
for j in range(self.height):
# forward mapping
for_x = (i - self.x) * math.cos(self.angle*(math.pi/180)) - (j - self.y) * math.sin(self.angle*(math.pi/180)) + self.x
for_y = (i - self.x) * math.sin(self.angle*(math.pi/180)) + (j - self.y) * math.cos(self.angle*(math.pi/180)) + self.x
for_x = int(for_x)
for_y = int(for_y)
# backward mapping should change the forward mapping to the original image
back_x = (i - self.x) * math.cos(self.angle*(math.pi/180)) + (j - self.y) * math.sin(self.angle*(math.pi/180)) + self.x
back_y = -(i - self.x) * math.sin(self.angle*(math.pi/180)) + (j - self.y) * math.cos(self.angle*(math.pi/180)) + self.x
back_x = int(back_x)
back_y = int(back_y)
if for_x in range(self.width) and for_y in range(self.height):
ForwardMap[i, j] = self.img[for_x, for_y]
else:
pass
if back_x in range(self.width) and back_y in range(self.height):
BackwardMap[i, j] = self.img[back_x, back_y]
else:
pass
cv2.imshow('Forward Mapping', ForwardMap)
cv2.imshow('Backward Mapping', BackwardMap)
def demo():
rotation.showImage('normal', rotation)
rotation.printWidthHeight(rotation)
rotation.rotateImage(rotation)
cv2.waitKey(0)
cv2.destroyAllWindows
if __name__ == '__main__':
demo()
My problem is now that I want to make the rotated pictures (both for forward and backwards mapping) fit JUST right so there is no unnecessary use of space. Can anybody help me with this? Much appreciated.
If you have any suggestions to optimize my code, feel free to comment on that as well.
Your original image has 4 corners, coordinates: (0,0), (w-1, 0), (0,h-1) and (w-1, h-1). Since your transformation is affine, why not transform these coordinates into destination coordinates?
(0,0) → (x1, y1)
(w-1, 0) → (x2, y2)
(0, h-1) → (x3, y3)
(w-1, h-1) → (x4, y4)
Your destination image size is then:
width = max(x1, x2, x3, x4) - min(x1, x2, x3, x4)
height = max(y1, y2, y3, y4) - min(y1, y2, y3, y4)
from tkinter import *
import random
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
for x in range(0, 40):
x1 = random.randint(0,400)
y1 = random.randint(0,400)
x2 = random.randint(0,400)
y2 = random.randint(0,400)
x3 = random.randint(0,400)
y3 = random.randint(0,400)
my_triangle = canvas.create_polygon(x1, y1, x2, y2, x3, y3,\
fill =("blue"), outline="red")
Hi! I am playing with tkinter and generating random triangles. The problem is:
I want to use random on fill = " " to generate random colors
random.randint(start, end) returns numbers, but fill accepts only strings like
fill ="red" or hexadecimal = "#RGB"
if I enter a numeric valuer like fill = (1,1,0) it doesn't work. How could I generate random string values in fill?
Thank you
Simply use random.sample() from a known list of colors. And you can find the python tkinter color chart enumerated here. You can then randomize for both fill and outline values:
COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace' ...]
for x in range(0, 40):
x1 = random.randint(0,400)
y1 = random.randint(0,400)
x2 = random.randint(0,400)
y2 = random.randint(0,400)
x3 = random.randint(0,400)
y3 = random.randint(0,400)
my_triangle = canvas.create_polygon(x1, y1, x2, y2, x3, y3,\
fill = (random.sample(COLORS, 1)[0]),
outline = random.sample(COLORS, 1)[0])
Of course, always seed if you want to reproduce same exact random generated numbers:
random.seed(444) # WHERE 444 IS ANY INTEGER
In alternative just generate your random color and format it:
from tkinter import *
import random
def random_color():
return random.randint(0,0x1000000)
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
for x in range(0, 40):
color = '{:06x}'.format(random_color())
x1 = random.randint(0,400)
y1 = random.randint(0,400)
x2 = random.randint(0,400)
y2 = random.randint(0,400)
x3 = random.randint(0,400)
y3 = random.randint(0,400)
my_triangle = canvas.create_polygon(x1, y1, x2, y2, x3, y3,\
fill =('#'+ color), outline="red")
tk.mainloop()
so there are a lot of problems going on with this. I attempted to make a snake game in python but It was just a mess so now I'm trying to make it where the only direction they can go after the initial right movement is down and they have to get to the coordinates of the food otherwise it starts over. if they 'eat' the food/square then it will make another level with ought starting new game so I can keep score, however the grow definition doesn't seem to be working at all no matter what I put under the if's. Im using python tkinter.
import Tkinter
import random
import math
from Tkinter import *
import time
# Create root window
####
root = Tkinter.Tk()
#####
# Create Model
######
speed_intvar = Tkinter.IntVar()
speed_intvar.set(1) # Initialize y coordinate
# radius and x-coordinate of circle
new_dir = 0
leng = 40
var = 1
x1 = 10
y1 = 10
x2 = 50
y2 = 10
x3 = x2
y3 = 10
direction = 3
foodx1 = 1
foodx2 = 8
foody1 = 1
foody2 = 8
food_present = 0
length = 8
food = 0# radians of angle in standard position, ccw from positive x axis
######
# Create Controller
#######
# Instantiate and place slider
# Create and place directions for the user
#canvas = Tkinter.Canvas(root, width=900, height=900, background='#FFFFFF')
#canvas.grid(row=0, rowspan=2, column=2)
#text = Tkinter.Button(root, text='Use WASD to move', command = new_game)
#text.grid(row=0, column =2)
#text = Tkinter.Label(root, text='Use WASD to move')
#text.grid(row=0, column =2)
######
# Create View
#######
# Create and place a canvas
def new_game():
c.delete("all")
canvas = Tkinter.Canvas(root, width=900, height=900, background='#FFFFFF')
canvas.grid(row=0, rowspan=2, column=1)
# Create a circle on the canvas to match the initial model
circle_item = canvas.create_line(x1, y1, x2, y2, x2, y3, fill='black', width = "8")
#circle_item2 = canvas.create_rectangle(8, 1, 9, 8,
# outline='#000000', fill='black')
#def move(event):
# if event.char=='w'
def food():
global foodx1, foodx2, foody1, foody2, food_present, food, var
food_present = 0
if food_present==0:
foodx1 = random.randint(1, 900)
foody1 = random.randint(1,900)
foodx2 = foodx1 + 8
foody2 = foody1 + 8
food = canvas.create_rectangle(foodx1, foody1, foodx2, foody2, fill = 'black')
food_present += 1
food()
#def make_longer():
# global food_present, food_list, x1, y1, x2, y2, circle_item
# #x1 = canvas.coords(circle_item)
# #y1 = canvas.coords(circle_item)
# #x2 = canvas.coords(circle_item)
# #y2 = canvas.coords(circle_item)
# xx1, yy1, xx2, yy2 = canvas.coords(circle_item)
# xx1 -= 10
# xx2 -= 50
# for i in range(len(food_list)):
# circle_item2=canvas.create_rectangle(xx1, yy1, xx2, yy2, fill ="black")
#make_longer()
def animate():
global x1, y1, x2, y2, x3, y3, var
x1, y1, x2, y2, x3, y3 = canvas.coords(circle_item)
#for i in range(food_present):
if var == 1:
x1 += 1
x2 += 1
#x3+= 1
if var == 4:
y1+=1
y2+=1
y3+=1
if var == 5:
x1-=1
x2-=1
x3-=1
if var == 6:
y1 -= 1
y2 -= 1
y3 -= 1
canvas.coords(circle_item, x1, y1, x2, y2, x2, y3)
#canvas.itemconfig(circle_item, x1, y1, x2, y2, x3, y3, fill="blue")
canvas.update()
#
#while
# Get the slider data and create x- and y-components of velocity
#velocity_x = speed_intvar.get() * math.cos(direction) # adj = hyp*cos()
#velocity_y = speed_intvar.get() * math.sin(direction) # opp = hyp*sin()
## Change the canvas item's coordinates
#canvas.move(circle_item, velocity_x, velocity_y)
#canvas.move(circle_item2, velocity_x, velocity_y)
# Get the new coordinates and act accordingly if ball is at an edge
#global location
## If crossing left or right of canvas
#if x2>canvas.winfo_width():
#
#if x1<0:
# canvas.move(circle_item, x+400, y)
#global direction
canvas.after(1, animate)
# Call function directly to start the recursion
animate()
#
def move(event):
global direction, var, x1, x2, x3, y1, y2, y3, new_dir
direction = 3
if event.char=='s' and direction == 3:
if direction == 1:
return
else:
new_dir = 1
var = 3
for i in range(10):
x1, y1, x2, y2, x3, y3 = canvas.coords(circle_item)
#for i in range(food_present):
if var == 3:
x1 += 1
x2 += 0
x3 +=0
y1 +=0
y2= y1
#x2 += 1
#x3 += 1
y3 += 1
canvas.coords(circle_item, x1, y1, x2, y2, x3, y3)
canvas.update()
if x1 == x3:
var = 4
direction = 1
canvas.update()
# if event.char=='s' and direction == 2:
# if direction == 1:
# return
# else:
# new_dir = 1
# var = 3
# for i in range(10):
# x1, y1, x2, y2, x3, y3 = canvas.coords(circle_item)
##for i in range(food_present):
# if var == 3:
# x1 -= 0
# x2 -= 1
# x3 -=1
# y1 -=0
# y2 -=1
# #x2 += 1
# #x3 += 1
#
# y3 -= 1
# canvas.coords(circle_item, x1, y1, x2, y2, x3, y3)
# canvas.update()
# if x1 == x3:
# var = 4
# direction = 1
# canvas.update()
root.bind("<Key>", move)
def x():
i = Tkinter.Canvas(root, width=900, height=900, background='#FFFFFF')
x = Tkinter.Button(root, text='Use S to move down. Try and eat the food.', command = new_game)
x.grid(row=0, column =1)
def grow():
global x1, y1, x2, y2, x3, y3, var, food_present, foodx1, foody1, foodx2, foody2
x1, y1, x2, y2, x3, y3 = canvas.coords(circle_item)
if x2>canvas.winfo_width() or x1<0:
x()
if y2>canvas.winfo_height() or y3>canvas.winfo_height():
food_present = 0
x()
canvas.update()
grow()
c = Tkinter.Canvas(root, width=900, height=900, background='#FFFFFF')
c.grid(row=0, rowspan=2, column=1)
text = Tkinter.Button(root, text='Use S to move down. Try and eat the food.', command = new_game)
text.grid(row=0, column =1)
root.mainloop()
If you want to check if two objects are overlapping on a Tkinter canvas, you may get their positions by the method of object Canvas .coords(objectname). You use the .coords method to check on a drawn object.
Example:
circle = canvas.create_oval(0, 0, 50, 50)
canvas.move(circle, 5, 0) # moves the circle by 5 pixels to the right
coords = canvas.coords(circle) # Returns an array (5, 0, 55, 0).
What you don't do is specify a coordinate to return what object is on it(what I think you are doing).
I have written the following code which defines a few functions that I will use later:
def dy1_dt(t, y1, y2, y3, y5, y6, i):
S=pi*y5**2
return -G*m_range[i]/y2**2+(1.0/(2.0*y3)*C_D*rho_range[i]*(y1**2+y2**2*y6**2)*cos(phi)*S
def dy2_dt(t, y1, i):
return y1
def dy3_dt(t, y1, y2, y5, y6, i):
S=pi*y5**2
return -0.5*C_H*rho_range[i]*(y1**2+y2**2*y6**2)**(1.50)*S/Q_abl
def dy4_dt(t, y1, y2, y5, y6, i):
return C_D*rho_range[i]/(2*iron_den)*(y1**2+y2**2*y6**2)/y5
def dy5_dt(t, y1, y2, y3, y5, y6, i):
S=pi*y5**2
return -y5/(6.0*y3)*C_H*rho_range[i]*(y1**2+y2**2*y6**2)**(1.50)*S/Q_abl
def dy6_dt(t, y1, y2, y3, y6, i):
return -C_D*rho_range[i]/(2*y3*y2)*(y1**2+y2**2*y6**2)*sin(phi)*S-((y1*y6)/y2)
def dy7_dt(t, y6, i):
return y6
I am receiving an error message at the line of 'dy2_dt(t, y1, i)' which says 'invalid syntax'. I am at loss as to what invalid syntax is actually included therein--it seems all well.
Your code is indeed invalid, you forgot to close parenthesis.
If you expand your first function, it gives:
def dy1_dt(t, y1, y2, y3, y5, y6, i):
S=pi*y5**2
return (
-G *
m_range[i] /
y2 **
2 +
(
1.0 /
(2.0 *y3 ) *
C_D *
rho_range[i] *
(
y1 **
2 +
y2 **
2 *
y6 **
2
) *
cos(phi) *
S