icon 情報整理

PythonでGUI

textbox1の内容をbutton1を押すことでlabel1に反映
import tkinter as tk

root = tk.Tk()
root.geometry("800x500")
root.title("test")

textbox1 = tk.Entry()
textbox1.insert(0, "textbox1_string")
textbox1.place(x=10, y=10)

def button1_click():
label1["text"] = textbox1.get()

button1 = tk.Button(root, text="button1", command=button1_click)
button1.place(x=10, y=50)

label1 = tk.Label(text="label1_text")
label1.place(x=10, y=90)

root.mainloop()
image-1 image-2

Pythonでアナログ時計

import math
import datetime
import time
import tkinter
import threading

WIDTH = 400
HEIGHT = 400
RADIUS = 180
NEEDLE_H = 120
NEEDLE_M = 160
NEEDLE_S = 150
MARK = 10
BASE_AGL = 90
W_TAG = "needle"
CENTER = int(WIDTH/2),int(HEIGHT/2)

def get_time():
while True:
now = datetime.datetime.now()

angle_h = float(BASE_AGL -30 * now.hour - 0.5 * now.minute)
angle_m = int(BASE_AGL - 6 * now.minute)
angle_s = int(BASE_AGL - 6 * now.second)

pos_hx = round(math.cos(math.radians(angle_h))*NEEDLE_H)
pos_hy = round(math.sin(math.radians(angle_h))*NEEDLE_H)
pos_mx = round(math.cos(math.radians(angle_m))*NEEDLE_M)
pos_my = round(math.sin(math.radians(angle_m))*NEEDLE_M)
pos_sx = round(math.cos(math.radians(angle_s))*NEEDLE_S)
pos_sy = round(math.sin(math.radians(angle_s))*NEEDLE_S)

canvas.create_line(CENTER, CENTER[0]+pos_hx, CENTER[1]-pos_hy, width=8, tags=W_TAG)
canvas.create_line(CENTER, CENTER[0]+pos_mx, CENTER[1]-pos_my, width=5, tags=W_TAG)
canvas.create_line(CENTER, CENTER[0]+pos_sx, CENTER[1]-pos_sy, width=2, tags=W_TAG)

time.sleep(0.2)

canvas.delete("needle")

canvas = tkinter.Canvas(master=None, width=WIDTH, height=HEIGHT)

canvas.create_oval(10, 10, 390, 390, outline="lightgray", fill="lightgray")

for mark in range(0, 360, 30):
mark_i_x = round(math.cos(math.radians(mark))*(RADIUS-MARK))
mark_i_y = round(math.sin(math.radians(mark))*(RADIUS-MARK))
mark_o_x = round(math.cos(math.radians(mark))*RADIUS)
mark_o_y = round(math.sin(math.radians(mark))*RADIUS)
canvas.create_line((CENTER[0]+mark_i_x,CENTER[1]+mark_i_y), (CENTER[0]+mark_o_x,CENTER[1]+mark_o_y), width=3, fill="gray")

canvas.pack()

thread = threading.Thread(target=get_time, daemon=True)

thread.start()

canvas.mainloop()
image-6

Pythonでペイント

import tkinter

paint_app = tkinter.Tk();

paint_app.geometry(
"500x500"
)

paint_app.title(
"Paintアプリ"
)

canvas = tkinter.Canvas(
paint_app,
width = 500,
height = 500,
bg = "white"
)

press = False

def mouse_move_func(event):
global canvas

x = event.x
y = event.y

if press:
canvas.create_oval(x - 20, y - 20, x + 20, y + 20, fill = "blue", width = 0)

def mouse_click_func(event):
global press

press = True

def mouse_release_func(event):
global press

press = False

canvas.grid()

paint_app.bind(
"",
mouse_move_func
)

paint_app.bind(
"",
mouse_click_func
)

paint_app.bind(
"",
mouse_release_func
)

paint_app.mainloop()
image-5

Pythonでメモ帳

# coding: Shift_JIS

import tkinter as tk
import tkinter.font as font

root = tk.Tk()

#フォント
my_font = font.Font(root,family = "MS Gothic")

#エディタの作成
text_widget = tk.Text(root, wrap = tk.NONE, font = my_font)
text_widget.grid(column=0, row=0, sticky = (tk.N, tk.S, tk.E, tk.W))
root.columnconfigure(0, weight = 1)
root.rowconfigure(0, weight = 1)

root.title("無題 - メモ帳")
#root.iconbitmap(default = "XXXX.ico")
root.geometry("500x250")

# スクロールバー
yscroll = tk.Scrollbar(text_widget, command=text_widget.yview)
xscroll = tk.Scrollbar(text_widget, command=text_widget.xview, orient=tk.HORIZONTAL)
yscroll.pack(side=tk.RIGHT, fill = "y")
xscroll.pack(side=tk.BOTTOM, fill = "x")
text_widget['yscrollcommand'] = yscroll.set
text_widget['xscrollcommand'] = xscroll.set

#メニューバー
menubar = tk.Menu(root, font = my_font)

filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label = "新規(N)")
filemenu.add_command(label = "開く(O)")
filemenu.add_command(label = "上書き保存(S)")
filemenu.add_command(label = "名前を付けて保存(A)...")
filemenu.add_separator()
filemenu.add_command(label = "ページ設定(U)...")
filemenu.add_command(label = "印刷(P)...")
filemenu.add_separator()
filemenu.add_command(label = "メモ帳の終了(X)", comman = root.quit)
menubar.add_cascade(label = "ファイル(F)", menu = filemenu)

editmenu = tk.Menu(menubar, tearoff=0)
editmenu.add_command(label = "About...")
menubar.add_cascade(label = "編集(E)", menu = editmenu)

formatmenu = tk.Menu(menubar, tearoff = 0)
formatmenu.add_command(label = "About...")
menubar.add_cascade(label = "書式(O)", menu = formatmenu)

viewmenu = tk.Menu(menubar, tearoff = 0)
viewmenu.add_command(label = "About...")
menubar.add_cascade(label = "表示(V)", menu = viewmenu)

helpmenu = tk.Menu(menubar, tearoff = 0)
helpmenu.add_command(label = "About...")
menubar.add_cascade(label = "ヘルプ(H)", menu = helpmenu)

root.config(menu = menubar)

root.mainloop()
image-8

Pythonでファイルアクセス

ファイル読み込み(全体)

f = open('test.txt', 'r')

data = f.read()

print(data)

f.close()
abc
def
ghij

ファイル読み込み(行単位)

f = open('test.txt', 'r', encoding='UTF-8')

for data in f:
print(data.rstrip('\n'))

f.close()
abc
def
ghij

ファイル書き込み(上書き)

### coding: Shift_JIS

f = open('test2.txt', 'w', encoding='UTF-8')

f.write('こんにちは\n')

f.close()
こんにちは

ファイル書き込み(追加)

### coding: Shift_JIS

f = open('test2.txt', 'a', encoding='UTF-8')

f.write('こんにちは\n')

f.close()
こんにちは
こんにちは

ファイル書き込み(複数行)

### coding: Shift_JIS

f = open('test2.txt', 'w', encoding='UTF-8')

datalist = ['こんにちは\n', 'お元気ですか?\n', 'それではまた\n']
f.writelines(datalist)

f.close()
こんにちは
お元気ですか?
それではまた

Pythonで画像表示

IMGを表示
### coding: Shift_JIS

import tkinter as tk

### ウィンドウ作成
root = tk.Tk()
root.geometry('700x560')

### 画像
test_img = tk.PhotoImage(file="test_img.png")

###キャンバス
canvas = tk.Canvas(width=700, height=500)

### 描画
canvas.create_image(0, 0, anchor="nw", image=test_img)

canvas.pack()

### メインループ
root.mainloop()
image-9

Pythonでドラッグアンドドロップ

ドラッグアンドドロップしたファイルを表示する
import tkinter
from tkinterdnd2 import *

def drop_event(event):
label1['text'] = event.data

root = TkinterDnD.Tk()
root.geometry('400x300')
label1 = tkinter.Label()
root.drop_target_register(DND_FILES)
root.dnd_bind('<>', drop_event)

label1.pack()

root.mainloop()
image-11

Pythonでグリッド表示

グリッドで表示する
import tkinter as tk

root = tk.Tk()
root.geometry("300x180")

label1 = tk.Label(text="label1", bg="cyan1")
label2 = tk.Label(text="label2", bg="green1")
label3 = tk.Label(text="label3", bg="yellow1")

label1.grid(row=0, column=0)
label2.grid(row=1, column=0)
label3.grid(row=2, column=0)

root.mainloop()
image-12

Pythonでグラフ表示

グラフを表示する
import matplotlib.pyplot as plt

data = [100, 200, 300, 400, 500, 600]

plt.plot(data)
plt.show()
image-13

Pythonで外部プログラム起動

import os

os.system('a.txt')
os.startfile('aa')

Pythonのフレーム

import tkinter as tk

root = tk.Tk()
root.geometry('500x100')

frame1 = tk.Frame(root)
frame2 = tk.Frame(root)

label1 = tk.Label(frame1,text="label1")
label1.pack()
label2 = tk.Label(frame2,text="label2")
label2.pack()

frame1.pack()
frame1.destroy()
frame2.pack()

root.mainloop()

Pythonでファイルドラッグ

import tkinter
from tkinterdnd2 import *

def drop_event(event):
label1['text'] = event.data

root = TkinterDnD.Tk()
root.geometry('400x300')
label1 = tkinter.Label()
root.drop_target_register(DND_FILES)
root.dnd_bind('<>', drop_event)

label1.pack()

root.mainloop()

Pythonで数値グラフ比較

数値をグラフ化して比較する

from tkinter import *
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

def plot_wave(y):
fig = plt.Figure()
ax1 = fig.add_subplot()
plt.ylim(0,)
ax1.bar(["a","b"],y)
return fig

def button1():
y = [0,0]
y[0] = int(txt1.get())
y[1] = int(txt2.get())
fig = plot_wave(y)
canvas = FigureCanvasTkAgg(fig, frame_2)
canvas.draw()
canvas.get_tk_widget().grid(row=0, column=0)

root = Tk()

frame_1 = Frame(root)
frame_2 = Frame(root)

txt1 = Entry(frame_1)
txt2 = Entry(frame_1)

btn1 = Button(frame_1, text='Update', command=button1)
fig = plot_wave(0)
canvas = FigureCanvasTkAgg(fig, frame_2)

frame_1.grid(row=0, column=0, sticky=W + E)
frame_2.grid(row=1, column=0)
txt1.pack(fill=X)
txt2.pack(fill=X)
btn1.pack(fill=X)
canvas.get_tk_widget().grid(row=0, column=0)

root.mainloop()
image-14

Pythonで画面上プログラムを実行

画面上に書かれたPythonプログラムを実行する

import tkinter as tk
from tkinter import scrolledtext as sc
from datetime import datetime
import os

path = 'temp.py'
root = tk.Tk()
frame1 = tk.Frame(root)
frame1_1 = tk.Frame(frame1)
button1 = tk.Button(frame1_1, text='python')
frame1_2 = tk.Frame(frame1)
text_box1 = sc.ScrolledText(frame1_2)

def main():
button1["command"] = button1_click

frame1.grid(row=0, column=0)
frame1_1.pack()
button1.pack()
frame1_2.pack()
text_box1.pack()

frame1.tkraise()

root.mainloop()

# memo
def button1_click():
f=open(path, 'w', encoding="utf-8")
f.write(text_box1.get("1.0", 'end -1c'))
f.close()

os.system('python '+ path)

main()
image-15

Pythonで計算してグラフ表示

掛け算をグラフ表示

from tkinter import *
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

def plot_wave(y):
fig = plt.Figure()
ax1 = fig.add_subplot()
plt.ylim(0,)
ax1.bar(["a","b","c"],y)
return fig

def button1():
y = [0,0,0]
y[0] = int(txt1.get())
y[1] = int(txt2.get())
y[2] = y[0] * y[1]
fig = plot_wave(y)
canvas = FigureCanvasTkAgg(fig, frame_2)
canvas.draw()
canvas.get_tk_widget().grid(row=0, column=0)

root = Tk()

frame_1 = Frame(root)
frame_2 = Frame(root)

txt1 = Entry(frame_1)
txt2 = Entry(frame_1)

btn1 = Button(frame_1, text='Update', command=button1)
fig = plot_wave(0)
canvas = FigureCanvasTkAgg(fig, frame_2)

frame_1.grid(row=0, column=0, sticky=W + E)
frame_2.grid(row=1, column=0)
txt1.pack(fill=X)
txt2.pack(fill=X)
btn1.pack(fill=X)
canvas.get_tk_widget().grid(row=0, column=0)

root.mainloop()
image-16

Pythonで視覚カウンター

+1、-1などを視覚的に表示

import tkinter as tk

num=0
root = tk.Tk()
frame = tk.Frame(root)

def main():

button1=tk.Button(text="+1", command=on_click1)
button1.pack()
button2=tk.Button(text="-1", command=on_click2)
button2.pack()
button3=tk.Button(text="*10", command=on_click3)
button3.pack()
disp()
frame.pack()

root.mainloop()

def on_click1():
global num
num+=1
disp()

def on_click2():
global num
num-=1
disp()

def on_click3():
global num
num*=10
disp()

def disp():
global num, frame
tmp_num = num
keta = 10

for i in range(keta):
for j in range(9):
if(j < tmp_num%10):
label1 = tk.Label(frame, text="■")
else:
label1 = tk.Label(frame, text=" ")
label1.grid(row=9-j, column=keta-i)
tmp_num //= 10;
main()
image-17

Pythonで簡易メモ帳

memo.txtを読み込んで表示 メモの内容に日付を入れてmemo.txtに書き込み

import tkinter as tk
from tkinter import scrolledtext as sc
from datetime import datetime

path = 'memo.txt'
root = tk.Tk()
frame1 = tk.Frame(root)
frame1_1 = tk.Frame(frame1)
button1 = tk.Button(frame1_1, text='memo')
frame1_2 = tk.Frame(frame1)
text_box1 = sc.ScrolledText(frame1_2)
frame2 = tk.Frame(root)
frame2_1 = tk.Frame(frame2)
button2_1 = tk.Button(frame2_1, text='cancel')
button2_2 = tk.Button(frame2_1, text='  ok  ')
frame2_2 = tk.Frame(frame2)
text_box2 = sc.ScrolledText(frame2_2)

def main():
button1["command"] = button1_click
button2_1["command"] = button2_1_click
button2_2["command"] = button2_2_click

frame1.grid(row=0, column=0)
frame1_1.pack()
button1.pack()
frame1_2.pack()
text_box1.pack()

frame2.grid(row=0, column=0)
frame2_1.pack()
button2_1.pack(side='left')
button2_2.pack(side='left')
frame2_2.pack()
text_box2.pack()

frame1.tkraise()
read_file()

root.mainloop()

def read_file():
text_box1.configure(state="normal")
try:
f=open(path, 'r', encoding="utf-8")
text_box1.delete("1.0", "end")
text_box1.insert("1.0", f.read())
f.close()
except:
pass
text_box1.configure(state="disabled")

def write_file():
try:
f=open(path, 'r', encoding="utf-8")
data = f.read()
f.close()
except:
data = ""	

f=open(path, 'w', encoding="utf-8")
f.write('--- ' + datetime.now().strftime('%Y/%m/%d %H:%M') + ' ---\n')
f.write(text_box2.get("1.0", 'end -1c'))
f.write("\n\n")
f.write(data)
f.close()

# memo
def button1_click():
text_box2.delete("1.0", "end")
frame2.tkraise()

# cancel
def button2_1_click():
frame1.tkraise()
read_file()

# ok
def button2_2_click():
frame1.tkraise()
if text_box2.get("1.0", 'end -1c') != "":
write_file()
read_file()

main()
image-18 image-19

Pythonでスタックファイラ

スタックファイラにドラッグアンドドロップで日付順に表示 データは保存先に日付フォルダを作成し移動 「OUT」ボタンで保存データをデスクトップに移動

# coding: utf-8
import tkinter
from tkinterdnd2 import *
import os
import shutil
from datetime import datetime
import glob

root=None
frame=None
stack_filer_data_path = "C:/stack_filer_data/"
out_path = "C:/Users/XXXX/Desktop/"

def main():
global root
global frame

root = TkinterDnD.Tk()
root.geometry('400x300')

root.drop_target_register(DND_FILES)
root.dnd_bind('<>', drop_event)

frame = tkinter.Frame(root)

disp()

root.mainloop()

def disp():
global frame
i=0

frame.destroy()
frame = tkinter.Frame(root)
frame.grid(row=0, column=0, sticky=tkinter.W)    

dirs=sorted(glob.glob(stack_filer_data_path + "*"), reverse=False)
for dir_name in dirs:
dir_name = dir_name.replace("\\","/")
label1 = tkinter.Label(frame)
print(dir_name)
file_name = glob.glob(dir_name + "/*")[0]
print(file_name)
print("---")
label1['text'] = os.path.basename(file_name)
label1.grid(row=i, column=0, sticky=tkinter.W)
button1 = tkinter.Button(frame, text="OK", command=button1_click(file_name))
button1.grid(row=i, column=1, sticky=tkinter.W)
button2 = tkinter.Button(frame, text="OUT", command=button2_click(file_name))
button2.grid(row=i, column=2, sticky=tkinter.W)
i+=1

def drop_event(event):
global i
path = event.data.replace("{","").replace("}","")
new_dir = datetime.now().strftime('%Y%m%d%H%M%S')
os.makedirs(stack_filer_data_path + "/" + new_dir)
new_path = stack_filer_data_path + "/" + new_dir + "/" + os.path.basename(path)
shutil.move(path, new_path)
disp()

def button1_click(path):
def temp():
os.startfile(path)
return temp

def button2_click(path):
def temp():
new_path = out_path + os.path.basename(path)
shutil.move(path, new_path)
os.rmdir(os.path.dirname(path))
disp()
return temp

main()
image
【保存データ】
stack_filer_data
20220306100745
test1.txt
20220306100801
test2.txt

【出力先】
デスクトップ

Pythonでメモ2

メモを単に日付を入れてmemo.txtに追記していく

import tkinter as tk
from tkinter import scrolledtext as sc
from datetime import datetime

path = 'memo.txt'
root = tk.Tk()
frame1 = tk.Frame(root)
frame1_1 = tk.Frame(frame1)
button1_1 = tk.Button(frame1_1, text='cancel')
button1_2 = tk.Button(frame1_1, text='  ok  ')
frame1_2 = tk.Frame(frame1)
text_box1 = sc.ScrolledText(frame1_2)

def main():
button1_1["command"] = button1_1_click
button1_2["command"] = button1_2_click

frame1.grid(row=0, column=0)
frame1_1.pack()
button1_1.pack(side='left')
button1_2.pack(side='left')
frame1_2.pack()
text_box1.pack()

frame1.pack()

root.mainloop()

def write_file():
try:
f=open(path, 'r', encoding="utf-8")
except OSError as e:
data = ""
else:
data = f.read()
f.close()

f=open(path, 'w', encoding="utf-8")
f.write('--- ' + datetime.now().strftime('%Y/%m/%d %H:%M') + ' ---\n')
f.write(text_box1.get("1.0", 'end -1c'))
f.write("\n\n")
f.write(data)
f.close()

# cancel
def button1_1_click():
root.destroy()

# ok
def button1_2_click():
if text_box1.get("1.0", 'end -1c') != "":
write_file()
root.destroy()

main()
image2
出力ファイル
memo.txt

Pythonでファイルスタック

ファイルをバッチファイルにドラッグアンドドロップすることで
指定フォルダに日付+ファイル名のフォルダを作成し、その下に移動する
【バッチファイル】
if not "%~0"=="%~dp0.\%~nx0" (
start /min cmd /c,"%~dp0.\%~nx0" %*
exit
)

python file_stack.py %*
【Pythonプログラム】
# coding: utf-8
import os
import shutil
from datetime import datetime
import sys

file_stack_data_path = "C:/file_stack_data/"
w_list = ['月', '火', '水', '木', '金', '土', '日']

def main():
for arg in sys.argv[1:]:
file_stack(arg)

def file_stack(arg):
arg = arg.replace("\\\\","/")
print(arg)
dt = datetime.now()
new_dir = "【" + dt.strftime('%Y年%m月%d日')
new_dir += "(" + w_list[dt.weekday()] + ") "
new_dir += dt.strftime('%H時%M分%S秒') + "】 " + os.path.basename(arg)
os.makedirs(file_stack_data_path + "/" + new_dir)
new_path = file_stack_data_path + "/" + new_dir + "/" + os.path.basename(arg)
shutil.move(arg, new_path)

main()
【移動先ファイル】
file_stack_data
【2022年03月04日(金) 00時36分03秒】 test1.txt
test1.txt
【2022年03月04日(金) 00時36分03秒】 test2.txt
test2.txt
【2022年03月06日(日) 11時33分39秒】 test3.txt
test3.txt

Pyhonでバックアップ・削除

バックアップ

ファイルをバッチファイルにドラッグアンドドロップすることで
指定フォルダに日付+ファイル名のフォルダを作成し、その下にバックアップ(コピー)する
【バッチファイル】
if not "%~0"=="%~dp0.\%~nx0" (
start /min cmd /c,"%~dp0.\%~nx0" %*
exit
)

python backup.py %*
【Pythonプログラム】
# coding: utf-8
import os
import shutil
from datetime import datetime
import sys

file_stack_data_path = "C:/backup_data/"
w_list = ['月', '火', '水', '木', '金', '土', '日']

def main():
for arg in sys.argv[1:]:
file_stack(arg)

def file_stack(arg):
arg = arg.replace("\\\\","/")
print(arg)
dt = datetime.now()
new_dir = "【" + dt.strftime('%Y年%m月%d日')
new_dir += "(" + w_list[dt.weekday()] + ") "
new_dir += dt.strftime('%H時%M分%S秒') + "】 " + os.path.basename(arg)
os.makedirs(file_stack_data_path + "/" + new_dir)
new_path = file_stack_data_path + "/" + new_dir + "/" + os.path.basename(arg)
shutil.copy(arg, new_path)

main()
【バックアップデータ】
backup_data
【2022年03月04日(金) 00時36分03秒】 test1.txt
test1.txt
【2022年03月04日(金) 00時36分03秒】 test2.txt
test2.txt
【2022年03月06日(日) 11時33分39秒】 test3.txt
test3.txt

削除(データを削除データへ移動)

ファイルをバッチファイルにドラッグアンドドロップすることで
指定フォルダに日付+ファイル名のフォルダを作成し、その下に削除(移動)する
【バッチファイル】
if not "%~0"=="%~dp0.\%~nx0" (
start /min cmd /c,"%~dp0.\%~nx0" %*
exit
)

python remove.py %*
【Pythonプログラム】
# coding: utf-8
import os
import shutil
from datetime import datetime
import sys

file_stack_data_path = "C:/remove_data/"
w_list = ['月', '火', '水', '木', '金', '土', '日']

def main():
for arg in sys.argv[1:]:
file_stack(arg)

def file_stack(arg):
arg = arg.replace("\\\\","/")
print(arg)
dt = datetime.now()
new_dir = "【" + dt.strftime('%Y年%m月%d日')
new_dir += "(" + w_list[dt.weekday()] + ") "
new_dir += dt.strftime('%H時%M分%S秒') + "】 " + os.path.basename(arg)
os.makedirs(file_stack_data_path + "/" + new_dir)
new_path = file_stack_data_path + "/" + new_dir + "/" + os.path.basename(arg)
shutil.move(arg, new_path)

main()
【削除データ】
remove_data
【2022年03月04日(金) 00時36分03秒】 test1.txt
test1.txt
【2022年03月04日(金) 00時36分03秒】 test2.txt
test2.txt
【2022年03月06日(日) 11時33分39秒】 test3.txt
test3.txt

Pythonでファイル操作2

import shutil
shutil.copy(コピー元ファイル, コピー先ファイル)

ファイル移動

import shutil
shutil.move(移動元ファイル, 移動先ファイル)

ファイル名変更

import os
os.rename(変更前ファイル, 変更後ファイル)

Pythonで放物シュミレーション

import pgzrun
import math

WIDTH = 900
HEIGHT = 500

class Projectile:
def __init__(self, v0, angle):
self.vx = v0 * math.cos(math.radians(angle))
self.vy = v0 * math.sin(math.radians(angle))
self.x = 0
self.y = 0
self.t = 0

def change_pos(self):
self.t += 1/60
scale_x = 10 + 100 * self.vx * self.t
scale_y = 400 - (100 * (self.vy * self.t + 1/2 * - 1.62 * self.t * self.t))
scale_position = (scale_x, scale_y)
screen.draw.filled_circle(scale_position, 10, 'RED')

ball = Projectile(4, 60)

def update():
screen.clear()
ball.change_pos()

pgzrun.go()
image-7