1. Инструмент для обновления PIP в Windows
Разберем простой инструмент для обновления PIP.
Обратите внимание, что вам нужно добавить Python к Windows PATH для использования данного инструмента.
Далее дан полный код Python для инструмента обновления PIP используя Tkinter:
# Импортируем модули import os import tkinter as tk # создание экземпляра класса Tk(), для отображенния окна приложения root= tk.Tk() # создаем холст с размерами, цветом canvas1 = tk.Canvas(root, width = 300, height = 350, bg = 'lightsteelblue2', relief = 'raised') canvas1.pack() # создаем текстовую метку label1 = tk.Label(root, text='Upgrade PIP', bg = 'lightsteelblue2') label1.config(font=('helvetica', 20)) canvas1.create_window(150, 80, window=label1) # создаем функцию с вызовом командной строки и командой обновления def upgradePIP (): os.system('start cmd /k python.exe -m pip install --upgrade pip') # создаем кнопку с текстом и размерами button1 = tk.Button(text=' Upgrade PIP ', command=upgradePIP, bg='green', fg='white', font=('helvetica', 12, 'bold')) canvas1.create_window(150, 180, window=button1) # запуск цикла программы root.mainloop()
Просто запустите код и затем нажмите на кнопку Upgrade PIP, после чего команда выполнится.
2. Электронные часы
В сегодняшней статье мы рассмотрим, как создать цифровые часы при помощи Python и Tkinter. Также нам понадобится модуль time. Мы создадим окно, затем добавим к нему метку Lable, в которой будут отображаться цифровые знаки, обновляющиеся по логике часов. Так мы будем имитировать изменение времени. И так, приступим.
# Для начала импортируем все элементы из модуля from tkinter import * from tkinter.ttk import * # импорт модуля для преобразования кортежей через format from time import strftime # создание экземпляра класса Tk(), для отображенния окна приложения root = Tk() # добавление заголовка к окну root.title('Часы') # создание текстовой метки в окне прилржения, для отображения цифровых знаков. Цифры будут белыми на черном фоне lable = Label(root, font=('aerial', 30), background='black', foreground='white') # функция отображения времени def time(): string = strftime('%H:%M:%S %p') lable.config(text=string) lable.after(1000, time) # азмещение метки времени по центру lable.pack(anchor='center') time() # запуск цикла программы mainloop()
3. Ну что дружок, погоняем кружок
Зеленый кружок можно двигать клавишами стрелок
# Импортируем модуль from tkinter import * # создаем окно root = Tk() c = Canvas(width=300, height=300, bg='white') c.focus_set() c.pack() # создаем круг ball = c.create_oval(140, 140, 160, 160, fill='green') # реагируем на клавиши c.bind('<Up>', lambda event: c.move(ball, 0, -2)) c.bind('<Down>', lambda event: c.move(ball, 0, 2)) c.bind('<Left>', lambda event: c.move(ball, -2, 0)) c.bind('<Right>', lambda event: c.move(ball, 2, 0)) # создаем цикл root.mainloop()
В данном примере круг двигается по холсту с помощью стрелок на клавиатуре. Когда создавался круг, его идентификатор был присвоен переменной ball. Метод move
объекта Canvas принимает идентификатор и смещение по осям.
4. AwesomeTkinter предлагает несколько симпатичных виджетов tkinter.
Эти виджеты представляют собой всего лишь виджеты tkinter с пользовательскими стилями и изображениями.
Не забываем pip install awesometkinter
import tkinter as tk from tkinter import ttk import awesometkinter as atk # our root root = tk.Tk() root.config(background=atk.DEFAULT_COLOR) # select tkinter theme required for things to be right on windows, # only 'alt', 'default', or 'classic' can work fine on windows 10 s = ttk.Style() s.theme_use('default') # 3d frame f1 = atk.Frame3d(root) f1.pack(side='left', expand=True, fill='both', padx=3, pady=3) # 3d progressbar bar = atk.RadialProgressbar3d(f1, fg='cyan', size=120) bar.pack(padx=20, pady=20) bar.start() # 3d button atk.Button3d(f1, text='3D Button').pack(pady=10) f2 = atk.Frame3d(root) f2.pack(side='left', expand=True, fill='both', padx=3, pady=3) # flat radial progressbar bar = atk.RadialProgressbar(f2, fg='green') bar.pack(padx=30, pady=30) bar.start() atk.Button3d(f2, text='Pressed Button').pack(pady=10) f3 = atk.Frame3d(root) f3.pack(side='left', expand=True, fill='both', padx=3, pady=3) atk.Radiobutton(f3, text="Radiobutton 1").pack(padx=20, pady=(20, 5)) atk.Radiobutton(f3, text="Radiobutton 2", ind_outline_color='white', ind_bg='yellow', ind_mark_color='red').pack(padx=20, pady=5) atk.Checkbutton(f3, text=" Checkbutton 1", check_mark_color='red', size=12).pack(padx=20, pady=(20, 5)) atk.Checkbutton(f3, text=" Checkbutton 2").pack(padx=20, pady=5) root.mainloop() )
Радиокнопки
import tkinter as tk from tkinter import ttk import awesometkinter as atk root = tk.Tk() root.title('AwesomeTkinter') # select tkinter theme required for things to be right on windows, # only 'alt', 'default', or 'classic' can work fine on windows 10 s = ttk.Style() s.theme_use('default') f = tk.Frame(root, bg='white') f.pack(expand=True, fill='both') # radio buttons' variable var = tk.StringVar() var.set('test') # lets print selection value var.trace_add('write', lambda *args: print(var.get())) # atk radiobutton, you can control indicator ring, fill, and mark color atk.Radiobutton(f, text='AwesomeTkinter Radiobutton', variable=var).pack(padx=17, pady=10, anchor='w') atk.Radiobutton(f, text='AwesomeTkinter Radiobutton, selected', value='test', variable=var).pack(padx=17, pady=10, anchor='w') ttk.Separator(f).pack(expand=True, fill='x') # standard tk button tk.Radiobutton(f, text='standard tk Radiobutton', variable=var, value='standard tk Radiobutton', fg='black', bg='white').pack(padx=10, pady=10, anchor='w') tk.Radiobutton(f, text='standard tk Radiobutton, selected', variable=var, value='test', bg='white', fg='black').pack(padx=10, pady=10, anchor='w') ttk.Separator(f).pack(expand=True, fill='x') # standard ttk Radiobutton ttk.Radiobutton(f, text='standard ttk Radiobutton', variable=var).pack(padx=15, pady=10, anchor='w') ttk.Radiobutton(f, text='standard ttk Radiobutton, selected', variable=var, value='test').pack(padx=15, pady=10, anchor='w') ttk.Separator(f).pack(expand=True, fill='x') # atk with custom colors atk.Radiobutton(f, text='AwesomeTkinter Radiobutton, with custom colors', ind_bg='yellow', ind_outline_color='red', ind_mark_color='blue', variable=var, value='test').pack(padx=17, pady=10, anchor='w') root.mainloop() )
5. Переводчик (используем translate)
не забываем про: pip install tranlate
from tkinter import * from translate import Translator #Функция перевода def translate(): translator= Translator(from_lang=lan1.get(),to_lang=lan2.get()) translation = translator.translate(var.get()) var1.set(translation) #Корневое окно Tkinter с заголовком root = Tk() root.title("Переводчик") #Создание рамки и сетки для размещения содержимого mainframe = Frame(root) mainframe.grid(column=0,row=0, sticky=(N,W,E,S) ) mainframe.columnconfigure(0, weight = 1) mainframe.rowconfigure(0, weight = 1) mainframe.pack(pady = 100, padx = 100) #переменные для выпадающего списка lan1 = StringVar(root) lan2 = StringVar(root) #варианты для отображения в выпадающем меню choices = { 'English','Hindi','Gujarati','Spanish','German', 'Russian'} #default selection for dropdownlists lan1.set('English') lan2.set('Russian') #создание выпадающего списка и упорядочивание в сетке lan1menu = OptionMenu( mainframe, lan1, *choices) Label(mainframe,text="Выбор языка").grid(row = 0, column = 1) lan1menu.grid(row = 1, column =1) lan2menu = OptionMenu( mainframe, lan2, *choices) Label(mainframe,text="Выбор языка").grid(row = 0, column = 2) lan2menu.grid(row = 1, column =2) #Текстовое поле для ввода пользователем Label(mainframe, text = "Введите текст").grid(row=2,column=0) var = StringVar() textbox = Entry(mainframe, textvariable=var).grid(row=2,column=1) #текстовое поле для отображения выходных данных #также можно использовать этикетку Label(mainframe, text = "Выход").grid(row=2,column=2) var1 = StringVar() textbox = Entry(mainframe, textvariable=var1).grid(row=2,column=3) #создание кнопки для вызова функции переводчика b=Button(mainframe,text='Перевод',command=translate).grid(row=3,column=1,columnspan=3) root.mainloop()
6. Аккуратный калькулятор
Стандартный калькулятор с графическим интерфейсом, использующий полный графический калькулятор на основе Tkinter (python)
from tkinter import * import parser root = Tk() root.title('Calculator') i = 0 def get_variables(num): global i display.insert(i,num) i += 1 def clear_all(): display.delete(0, END) def undo(): entire_string = display.get() if len(entire_string): new_string = entire_string[:-1] clear_all() display.insert(0,new_string) else: clear_all() display.insert(0, "Error") def get_operation(operator): global i length = len(operator) display.insert(i,operator) i += length def calculate(): entire_string = display.get() try: a = parser.expr(entire_string).compile() result = eval(a) clear_all() display.insert(0,result) except Exception: clear_all() display.insert(0,"Error") def calcFact(): try: number = int(display.get()) res = 1 for i in xrange(1,number + 1): res *= i clear_all() display.insert(0,res) except Exception: clear_all() display.insert(0,"Error") display = Entry(root) display.grid(row = 1, columnspan=6, sticky = W + E) #adding buttons to the calculator Button(root,text = "1", command = lambda : get_variables(1)).grid(row = 2 ,column = 0) Button(root,text = "2", command = lambda : get_variables(2)).grid(row = 2 ,column = 1) Button(root,text = "3", command = lambda : get_variables(3)).grid(row = 2 ,column = 2) Button(root,text = "4", command = lambda : get_variables(4)).grid(row = 3 ,column = 0) Button(root,text = "5", command = lambda : get_variables(5)).grid(row = 3 ,column = 1) Button(root,text = "6", command = lambda : get_variables(6)).grid(row = 3 ,column = 2) Button(root,text = "7", command = lambda : get_variables(7)).grid(row = 4 ,column = 0) Button(root,text = "8", command = lambda : get_variables(8)).grid(row = 4 ,column = 1) Button(root,text = "9", command = lambda : get_variables(9)).grid(row = 4 ,column = 2) Button(root, text = "AC", command = lambda: clear_all()).grid(row=5, column =0) Button(root, text = "0", command = lambda : get_variables(0)).grid(row=5, column =1) Button(root, text = "=", command = lambda: calculate()).grid(row=5, column =2) Button(root, text = "+", command = lambda: get_operation("+")).grid(row=2, column =3) Button(root, text = "-", command = lambda: get_operation("-")).grid(row=3, column =3) Button(root, text = "x", command = lambda: get_operation("*")).grid(row=4, column =3) Button(root, text = "pi", command = lambda:get_operation("*3.14")).grid(row=2, column =4) Button(root, text = "%", command = lambda:get_operation("%")).grid(row=3, column =4) Button(root, text = "(", command = lambda:get_operation("(")).grid(row=4, column =4) Button(root, text = "exp", command = lambda:get_operation("**")).grid(row=5, column =4) Button(root, text = "<-", command = lambda : undo()).grid(row=2, column =5) Button(root, text = "x!", command = lambda: calcFact()).grid(row=3, column =5) Button(root, text = ")", command = lambda: get_operation(")")).grid(row=4, column =5) Button(root, text = "^2", command = lambda: get_operation("**2")).grid(row=5, column =5) root.mainloop()
7. tkinter-подсказка (всплывающее окно)
Это простая, но полностью настраиваемая реализация всплывающей подсказки/всплывающего окна для tkinter
виджетов. Он способен полностью интегрироваться с пользовательскими tkinter
темами, как светлыми, так и темными.
Функции
- обычные всплывающие подсказки
- показать всплывающую подсказку с
s
секундамиdelay
- всплывающая подсказка отслеживает курсор мыши
- всплывающая подсказка отображает строки и функции, возвращающие строки
- полностью настраиваемый, всплывающая подсказка наследует основной стиль темы
Установить
pip install tkinter-tooltip
Примеры
Обычные всплывающие подсказки
По умолчанию всплывающая подсказка активируется при входе и/или перемещении внутри виджета и деактивируется при выходе и/или нажатии любой кнопки.
import tkinter as tk import tkinter.ttk as ttk from tktooltip import ToolTip app = tk.Tk() b = ttk.Button(app, text="Button") b.pack() ToolTip(b, msg="Hover info") app.mainloop()
Отложенная подсказка
import tkinter as tk import tkinter.ttk as ttk from tktooltip import ToolTip app = tk.Tk() b = ttk.Button(app, text="Button") b.pack() ToolTip(b, msg="Hover info", delay=2.0) # True by default app.mainloop()
Подсказка отслеживания
Пусть всплывающая подсказка следует за курсором мусса при движении.
import tkinter as tk import tkinter.ttk as ttk from tktooltip import ToolTip app = tk.Tk() b = ttk.Button(app, text="Button") b.pack() ToolTip(b, msg="Hover info", follow=True) # True by default app.mainloop()
Функция как всплывающая подсказка
Здесь всплывающая подсказка возвращает значение, которое time.asctime()
обновляется при каждом движении. Вы можете управлять частотой обновления сквозного ToolTip
аргумента refresh
, по умолчанию для него установлено значение 1s
.
import time import tkinter as tk import tkinter.ttk as ttk from tktooltip import ToolTip app = tk.Tk() b = ttk.Button(app, text="Button") b.pack() # NOTE: pass the function itself not the return value ToolTip(b, msg=time.asctime, delay=0) app.mainloop()
Тематическая подсказка
tkinter-tooltip
полностью осведомлен о базовой теме (в данном случае темной теме) и даже может быть дополнительно настроен путем передачи tk
аргументов стиля во всплывающую подсказку.
Стиль всплывающей подсказки и основы кнопки. Если использовалась полная тема, то ToolTip
по умолчанию будут унаследованы настройки темы.
import tkinter as tk import tkinter.ttk as ttk from tktooltip import ToolTip app = tk.Tk() s = ttk.Style() s.configure("custom.TButton", foreground="#ffffff", background="#1c1c1c") b = ttk.Button(app, text="Button", style="custom.TButton") b.pack() ToolTip(b, msg="Hover info", delay=0, parent_kwargs={"bg": "black", "padx": 5, "pady": 5}, fg="#ffffff", bg="#1c1c1c", padx=10, pady=10) app.mainloop()
8. ttkScrollableNotebook
Горизонтальные прокручиваемые вкладки для виджета ноутбука Tkinter Ссылка
9. TkDial
Это библиотека, содержащая некоторые виджеты с круговыми вращающимися ручками для Tkinter. Его можно использовать вместо обычных ползунков и шкалы. Ссылка
10. Таблица стилей Tkinter — Tkss
Эта библиотека поможет установить стиль для виджета по умолчанию tkinter с использованием таблицы стилей безнадежной безопасности. Ссылка
11. TkFontAwesome
Библиотека, которая позволяет вам использовать значки FontAwesome в вашем приложении tkinter. Ссылка
pip install tkfontawesome
Вы можете использовать любую из 1000+ бесплатных иконок FontAwesome 5.0 . Цвет и размер заливки настраиваются в соответствии с вашими требованиями, а затем преобразуются в объект с помощью tksvg , который можно использовать везде, где вы будете использовать tkinter.PhotoImage
объект.
12. Notepad-Tk
Блокнот, созданный с помощью Tkinter. Ссылка
13. Графический интерфейс на Python с использованием Pandas и Tkinter
14. Создание QR кода
#pip install qrcode pillow import qrcode, PIL from PIL import Image,ImageTk import tkinter as tk from tkinter import ttk,messagebox,filedialog def createQR(*args): data = text_entry.get() if data: img = qrcode.make(data) #generate QRcode res_img = img.resize((280,250)) # reszie QR Code Size #Convert To photoimage tkimage= ImageTk.PhotoImage(res_img) qr_canvas.create_image(0,0,anchor=tk.NW, image=tkimage) qr_canvas.image = tkimage else: messagebox.showwarning("Warning",'Enter Data in Entry First') def saveQR(): data = text_entry.get() if data: img = qrcode.make(data) #generate QRcode res_img = img.resize((280,250)) # reszie QR Code Size path = filedialog.asksaveasfilename(defaultextension=".png",) if path: res_img.save(path) messagebox.showinfo("Sucess","QR Code is Saved ") else: messagebox.showwarning("Warning",'Enter Data in Entry First') root = tk.Tk() root.title("QR Code Generator") root.geometry("300x380") root.config(bg='white') root.resizable(0,0) frame1 = tk.Frame(root,bd=2,relief=tk.RAISED) frame1.place(x=10,y=5,width=280,height=250) frame2 = tk.Frame(root,bd=2,relief=tk.SUNKEN) frame2.place(x=10,y=260,width=280,height=100) qr_canvas = tk.Canvas(frame1) qr_canvas.pack(fill=tk.BOTH) text_entry = ttk.Entry(frame2,width=26,font=("Sitka Small",11),justify=tk.CENTER) text_entry.bind("<Return>",createQR) text_entry.place(x=5,y=5) btn_1 = ttk.Button(frame2,text="Create",width=10,command=createQR) btn_1.place(x=25,y=50) btn_2 = ttk.Button(frame2,text="Save",width=10,command=saveQR) btn_2.place(x=100,y=50) btn_3 = ttk.Button(frame2,text="Exit",width=10,command=root.quit) btn_3.place(x=175,y=50) root.mainloop()
15. Выбор цвета
Создаем приложение для выбора цвета в фомате Hex и RGB .
# >> @dynamic.coding << """ Python Tkinter Color Picker to choose color in Hex and RGB Format ... """ import tkinter as tk from tkinter import Entry, Frame, Label from tkinter.constants import HORIZONTAL, RAISED, SUNKEN class Colorpicker: def __init__(self,root): self.root = root self.root.title("Color Picker") self.root.geometry("300x420") self.root.resizable(0,0) self.R = tk.IntVar() self.G = tk.IntVar() self.B = tk.IntVar() self.hex = tk.IntVar() self.color_canvas = Label(self.root,bg="#8400ff",width=40,height=10,bd=2,relief=RAISED) self.color_canvas.place(x=7,y=2) self.color_canvas.bind("<Double-1>",self.copy_color) frame = Frame(self.root,bd=2,relief=SUNKEN) frame.place(x=7,y=170,height=180,width=285) r_label = Label(frame,text="R",width=5,fg="#ff0000",font=('arial',10,'bold')) r_label.place(x=5,y=24) self.R_Scale = tk.Scale(frame,from_=0,to=255,length=210,fg="#ff0000" ,orient=HORIZONTAL,command=self.scaleMove) self.R_Scale.set(132) self.R_Scale.place(x=40,y=6) g_label = Label(frame,text="G",width=5,fg="#00a200",font=('arial',10,'bold')) g_label.place(x=5,y=68) self.G_Scale = tk.Scale(frame,from_=0,to=255,length=210,fg="#00a200" ,orient=HORIZONTAL,command=self.scaleMove) self.G_Scale.place(x=40,y=50) b_label = Label(frame,text="B",width=5,fg="#0000ff",font=('arial',10,'bold')) b_label.place(x=5,y=122) self.B_Scale = tk.Scale(frame,from_=0,to=255,length=210,fg="#0000ff" ,orient=HORIZONTAL,command=self.scaleMove) self.B_Scale.set(255) self.B_Scale.place(x=40,y=105) hex_label = Label(self.root,text="Hex Code :",font=('arial',10,'bold')) hex_label.place(x=7,y=360) self.hex_entry = Entry(self.root,width=12,font=('arial',10)) self.hex_entry.insert(tk.END,'##8400ff') self.hex_entry.place(x=90,y=360) rbg_label = Label(self.root,text="RGB Code :",font=('arial',10,'bold')) rbg_label.place(x=7,y=390) self.rgb_entry = Entry(self.root,width=12,font=('arial',10)) self.rgb_entry.place(x=90,y=390) def scaleMove(self,*args): self.R = int(self.R_Scale.get()) self.G = int(self.G_Scale.get()) self.B = int(self.B_Scale.get()) rgb = f"{self.R},{self.G},{self.B}" #print(r,g,b) self.hex = "#%02x%02X%02x"%(self.R,self.G,self.B) self.color_canvas.config(bg=self.hex) # Hex to RGB #h = color_hex.lstrip('#') #print('RGB =', tuple(int(h[i:i+2], 16) for i in (0, 2, 4))) self.hex_entry.delete(0,tk.END) self.hex_entry.insert(0,self.hex) self.rgb_entry.delete(0,tk.END) self.rgb_entry.insert(0,rgb) def copy_color(self,*args): root.clipboard_clear() # clear clipboard contents root.clipboard_append(self.hex) # append new value to clipbaord root = tk.Tk() Colorpicker(root) root.mainloop()
16. Крестики-Нолики
# Instagram : @dynamic.coding # >> FOLLOW ME << from tkinter import * from tkinter import messagebox import random as r def button(frame): #Function to define a button b=Button(frame,padx=1,bg="#D4D4D4",width=3,text=" ", font=('arial',60,'bold'),relief=RAISED,bd=5) return b def change_a(): #Function to change the operand for the next player global a for i in ['O','X']: if not(i==a): a=i break def reset(): #Resets the game global a for i in range(3): for j in range(3): b[i][j]["text"]=" " b[i][j]["state"]=NORMAL a=r.choice(['O','X']) def check(): #Checks for victory or Draw for i in range(3): if(b[i][0]["text"]==b[i][1]["text"]==b[i][2]["text"]==a or b[0][i]["text"]==b[1][i]["text"]==b[2][i]["text"]==a): messagebox.showinfo("Congrats!!","'"+a+"' Победил") reset() if(b[0][0]["text"]==b[1][1]["text"]==b[2][2]["text"]==a or b[0][2]["text"]==b[1][1]["text"]==b[2][0]["text"]==a): messagebox.showinfo("Congrats!!","'"+a+"' победил") reset() elif(b[0][0]["state"]==b[0][1]["state"]==b[0][2]["state"]==b[1][0]["state"]==b[1][1]["state"]==b[1][2]["state"]==b[2][0]["state"]==b[2][1]["state"]==b[2][2]["state"]==DISABLED): messagebox.showinfo("Tied!!","The match ended in a draw") reset() def click(row,col): b[row][col].config(text=a,state=DISABLED,disabledforeground=colour[a]) check() change_a() ############### Main Program ################# root=Tk() #Window defined root.title("Крестики-Нолики") #Title given a=r.choice(['O','X']) #Two operators defined colour={'O':"deep sky blue",'X':"lawn green"} b=[[],[],[]] for i in range(3): for j in range(3): b[i].append(button(root)) b[i][j].config(command= lambda row=i,col=j:click(row,col)) b[i][j].grid(row=i,column=j) reset_btn = Button(text="Играть сначало",font=('arial',15,'bold'),command=reset) reset_btn.grid(row=3,column=0,columnspan=3) root.mainloop()
17. Еще один калькулятор
from tkinter import * from math import * root = Tk() root.title("Calculator") root.resizable(width=False, height=False) screen = StringVar() screen.set("0") current = "" power = "" firstnum = "" secondnum = "" mathsign = "" exponentiation = False percent_active = False def math_button_pressed(): if mathsign == '+': button_plus.config(relief=SUNKEN) elif mathsign == '-': button_minus.config(relief=SUNKEN) elif mathsign == '*': button_multiply.config(relief=SUNKEN) elif mathsign == '/': button_division.config(relief=SUNKEN) def math_button_raised(): button_plus.config(relief=RAISED) button_minus.config(relief=RAISED) button_multiply.config(relief=RAISED) button_division.config(relief=RAISED) def is_int(num): if int(num) == float(num): return int(num) else: return float(num) def set_screen(num): screen.set(is_int(num)) def number_pressed(butt): global current, power, firstnum, secondnum if mathsign == "" and not exponentiation: current = current + str(butt) firstnum = float(current) elif mathsign != "" and not exponentiation: math_button_raised() current = current + str(butt) secondnum = float(current) elif mathsign == "" and exponentiation: power = power + str(butt) current = current + str(butt) elif mathsign != "" and exponentiation: power = power + str(butt) current = current + str(butt) print(power) screen.set(current) def math_pressed(math): global current, power, mathsign, firstnum, secondnum, exponentiation, percent_active if mathsign == "" and not exponentiation and not percent_active and firstnum != "": mathsign = str(math) math_button_pressed() current = "" elif mathsign != "" and not exponentiation and not percent_active: if mathsign == '+': firstnum = float(firstnum + secondnum) elif mathsign == '-': firstnum = float(firstnum - secondnum) elif mathsign == '*': firstnum = float(firstnum * secondnum) elif mathsign == '/': firstnum = float(firstnum / secondnum) firstnum = round(firstnum, 6) set_screen(firstnum) elif mathsign != "" and exponentiation and not percent_active: if mathsign == '+': firstnum = firstnum + secondnum ** int(power) elif mathsign == '-': firstnum = firstnum - secondnum ** int(power) elif mathsign == '*': firstnum = firstnum * secondnum ** int(power) elif mathsign == '/': firstnum = firstnum / secondnum ** int(power) firstnum = round(firstnum, 6) exponentiation = False set_screen(firstnum) exponentiation = False power = "" elif exponentiation and not percent_active: firstnum = round(firstnum ** int(power), 6) exponentiation = False set_screen(firstnum) power = "" elif percent_active: if mathsign == '+': firstnum = float(firstnum + firstnum / 100 * secondnum) elif mathsign == '-': firstnum = float(firstnum - firstnum / 100 * secondnum) firstnum = round(firstnum, 6) set_screen(firstnum) percent_active = False mathsign = str(math) math_button_pressed() current = "" def squareroot(): global firstnum, secondnum, mathsign, current if mathsign == "": firstnum = round(sqrt(firstnum), 6) set_screen(firstnum) elif mathsign != "": if mathsign == '+': firstnum = sqrt(firstnum + float(secondnum)) elif mathsign == '-': firstnum = sqrt(firstnum - float(secondnum)) elif mathsign == '*': firstnum = sqrt(firstnum * float(secondnum)) elif mathsign == '/': firstnum = sqrt(firstnum / float(secondnum)) firstnum = round(firstnum, 6) set_screen(firstnum) secondnum = "" mathsign = "" current = "" def x(): global firstnum, secondnum, mathsign, current, exponentiation if mathsign == "": current = str(is_int(firstnum)) + '^' elif mathsign != "": current = str(is_int(secondnum)) + '^' screen.set(current) exponentiation = True def result(): global firstnum, secondnum, mathsign, current, power, exponentiation, percent_active if not exponentiation and not percent_active: if mathsign == '+': firstnum = float(firstnum + secondnum) elif mathsign == '-': firstnum = float(firstnum - secondnum) elif mathsign == '*': firstnum = float(firstnum * secondnum) elif mathsign == '/': firstnum = float(firstnum / secondnum) firstnum = round(firstnum, 6) set_screen(firstnum) elif mathsign == "" and exponentiation and not percent_active: firstnum = round(firstnum ** int(power), 6) exponentiation = False set_screen(firstnum) elif mathsign != "" and exponentiation and not percent_active: if mathsign == '+': firstnum = firstnum + secondnum ** int(power) elif mathsign == '-': firstnum = firstnum - secondnum ** int(power) elif mathsign == '*': firstnum = firstnum * secondnum ** int(power) elif mathsign == '/': firstnum = firstnum / secondnum ** int(power) firstnum = round(firstnum, 6) exponentiation = False set_screen(firstnum) elif not exponentiation and percent_active: if mathsign == '+': firstnum = float(firstnum + firstnum / 100 * secondnum) elif mathsign == '-': firstnum = float(firstnum - firstnum / 100 * secondnum) firstnum = round(firstnum, 6) set_screen(firstnum) percent_active = False elif not exponentiation and mathsign == '*' or '/' and percent_active: clear() mathsign = "" current = "" power = "" def clear(): global current, firstnum, secondnum, mathsign, power, exponentiation, percent_active screen.set(0) current = "" power = "" firstnum = "" secondnum = "" mathsign = "" exponentiation = False math_button_raised() percent_active = False def percent(): global firstnum, secondnum, current, percent_active current = str(is_int(secondnum)) + '%' screen.set(current) percent_active = True # Widgets calculation = Entry(root, textvariable=screen, font=("Verdana", 15,), bd=12, insertwidth=4, width=14, justify=RIGHT) calculation.grid(columnspan=4) # Numbers button1 = Button(root, text='1', command=lambda: number_pressed(1), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button1.grid(row=2, column=0, sticky=W) button2 = Button(root, text='2', command=lambda: number_pressed(2), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button2.grid(row=2, column=1, sticky=W) button3 = Button(root, text='3', command=lambda: number_pressed(3), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button3.grid(row=2, column=2, sticky=W) button4 = Button(root, text='4', command=lambda: number_pressed(4), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button4.grid(row=3, column=0, sticky=W) button5 = Button(root, text='5', command=lambda: number_pressed(5), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button5.grid(row=3, column=1, sticky=W) button6 = Button(root, text='6', command=lambda: number_pressed(6), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button6.grid(row=3, column=2, sticky=W) button7 = Button(root, text='7', command=lambda: number_pressed(7), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button7.grid(row=4, column=0, sticky=W) button8 = Button(root, text='8', command=lambda: number_pressed(8), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button8.grid(row=4, column=1, sticky=W) button9 = Button(root, text='9', command=lambda: number_pressed(9), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button9.grid(row=4, column=2, sticky=W) button0 = Button(root, text='0', command=lambda: number_pressed(0), bg="gainsboro", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button0.grid(row=5, column=0, sticky=W) button_float = Button(root, text='.', command=lambda: number_pressed('.'), bg="gainsboro", bd=3, padx=15, pady=5, font=("Helvetica", 14, "bold")) button_float.grid(row=5, column=1) # Math signs button_plus = Button(root, text='+', command=lambda: math_pressed('+'), bg="gray70", bd=3, padx=11, pady=5, font=("Helvetica", 14, "bold")) button_plus.grid(row=2, column=3, sticky=W) button_minus = Button(root, text='-', command=lambda: math_pressed('-'), bg="gray70", bd=3, padx=11, pady=4, font=("Verdana", 14, "bold")) button_minus.grid(row=3, column=3, sticky=W) button_multiply = Button(root, text='*', command=lambda: math_pressed('*'), bg="gray70", bd=3, padx=13, pady=5, font=("Helvetica", 14, "bold")) button_multiply.grid(row=4, column=3, ) button_division = Button(root, text='/', command=lambda: math_pressed('/'), bg="gray70", bd=3, padx=14, pady=5, font=("Helvetica", 14, "bold")) button_division.grid(row=5, column=3, ) button_equal = Button(root, text='=', command=lambda: result(), bg='orange', bd=3, padx=12, pady=5, font=("Arial", 14)) button_equal.grid(row=5, column=2, ) button_percent = Button(root, text='%', command=lambda: percent(), bg="gray70", bd=3, padx=8, pady=5, font=("Helvetica", 14, "bold")) button_percent.grid(row=1, column=3, ) button_clear = Button(root, text='C', command=lambda: clear(), bg='gray70', bd=3, padx=11, pady=5, font=("Helvetica", 14)) button_clear.grid(row=1, column=0) button_sqrt = Button(root, text='√', command=lambda: squareroot(), bg="gray70", bd=3, padx=12, pady=5, font=("Helvetica", 14, "bold")) button_sqrt.grid(row=1, column=1, sticky=W) button_x = Button(root, text='x^y', command=lambda: x(), bg="gray70", bd=3, padx=6, pady=5, font=("Helvetica", 14)) button_x.grid(row=1, column=2, sticky=W) root.mainloop()
18. Интересная шкала
from tkinter import * import ttkbootstrap as tb root = tb.Window(themename="superhero") #root = Tk() root.title("TTK Bootstrap! Meter!") #root.iconbitmap('images/codemy.ico') root.geometry('500x650') def up(): my_meter.step(10) def down(): my_meter.step(-10) global counter counter=20 def clicker(): global counter if counter <= 100: my_meter.configure(amountused=counter) counter += 5 my_button.configure(text=f'Нажми меня {my_meter.amountusedvar.get()}') my_meter = tb.Meter(root, bootstyle="danger", subtext="Умный Tkinter", interactive=True, textright="%", #textleft="$" metertype="full", # Can be semi stripethickness=10, metersize=200, padding=50, amountused=0, amounttotal=100, subtextstyle="light" ) my_meter.pack(pady=50) my_button = tb.Button(root, text="Нажми меня 5", command=clicker) my_button.pack(pady=20) my_button2 = tb.Button(root, text="Шаг вверх", command=up) my_button2.pack(pady=20) my_button3 = tb.Button(root, text="Шаг вниз", command=down) my_button3.pack(pady=20) root.mainloop()
19. Интересный календарь
Модуль ttkbootstrap. Расширение темы для tkinter, которое позволяет создавать по запросу темы в современном плоском стиле, вдохновленные Bootstrap.
from tkinter import * import ttkbootstrap as tb from datetime import date from ttkbootstrap.dialogs import Querybox root = tb.Window(themename="superhero") #root = Tk() root.title("TTK Bootstrap! Ввод даты") #root.iconbitmap('images/codemy.ico') root.geometry('500x350') def datey(): # Grab The Date my_label.config(text=f"Ты выбрал: {my_date.entry.get()}") def thing(): cal = Querybox() my_label.config(text=f"Ты выбрал: {cal.get_date()}") my_date = tb.DateEntry(root, bootstyle="danger", firstweekday=0, startdate=date(2023, 2, 14)) my_date.pack(pady=50) my_button = tb.Button(root, text='Получить дату', bootstyle="danger outline", command=datey) my_button.pack(pady=20) my_button2 = tb.Button(root, text='Получить календарь', bootstyle="success outline", command=thing) my_button2.pack(pady=20) my_label = tb.Label(root, text="Ты выбрал: ") my_label.pack(pady=20) root.mainloop()
20. Слайдер
Сами выставляем размер окна
from tkinter import * main = Tk() main.geometry('720x360') vertical = Scale(main, from_=180, to=360) vertical.pack() horizontal = Scale(main, from_=360, to=720, orient=HORIZONTAL) horizontal.pack() def clicked(): # one use! main.geometry(f'{horizontal.get()}x{vertical.get()}') Button(main, text='Изменить размер окна', command=clicked).pack() main.mainloop()
21. Цифровые часы
import sys from tkinter import * import time def times(): current_time=time.strftime("%H:%M:%S") clock.config(text=current_time) clock.after(200,times) root=Tk() root.geometry("450x250") clock=Label(root,font=("times",50,"bold"),bg="white") clock.grid(row=2,column=2,pady=25,padx=100) times() digi=Label(root,text="Цифровые часы",font="times 24 bold") digi.grid(row=0,column=2) nota=Label(root,text="часы минуты секунды ",font="times 15 bold") nota.grid(row=3,column=2) root.mainloop()
22. Система управления библиотекой
Проект GUI системы управления библиотеками на Python с использованием Tkinter и SQL Ссылка
Перед использованием установите следующие пакеты в cmd.
pip install python-tk
pip install pillow
- запустить trinity .py
- имя пользователя = Prakarsha, пароль = root
23. Симпатичный блокнот
Симпатичный блокнот с очисткой, удалением и сохранением.
Создает текстовый файл checklist (там же и сохраняет), в том же месте где и файл питон. Ссылка
Папка: 5_simple_checklist
#Simple Checklist import tkinter from tkinter import END, ANCHOR #Define window root = tkinter.Tk() root.title('Простой список') root.iconbitmap('check.ico') root.geometry('400x400') root.resizable(0,0) #Define fonts and colors my_font = ('Times New Roman', 12) root_color = '#6c1cbc' button_color = '#e2cff4' root.config(bg=root_color) #Define functions def add_item(): """Add an individual item to the listbox""" my_listbox.insert(END, list_entry.get()) list_entry.delete(0, END) def remove_item(): """Remove the selected (ANCHOR) item from the listbox""" my_listbox.delete(ANCHOR) def clear_list(): """Delete all items from the listbox""" my_listbox.delete(0, END) def save_list(): """Save the list to a simple txt file""" with open('checklist.txt', 'w') as f: #listbox.get() returns a tuple.... list_tuple = my_listbox.get(0, END) for item in list_tuple: #Take proper precautions to include only one \n for formatting purposes if item.endswith('\n'): f.write(item) else: f.write(item + "\n") def open_list(): """Open the list upon starting the program if there is one""" try: with open('checklist.txt', 'r') as f: for line in f: my_listbox.insert(END, line) except: return #Define layout #Create frames input_frame = tkinter.Frame(root, bg=root_color) output_frame = tkinter.Frame(root, bg=root_color) button_frame = tkinter.Frame(root, bg=root_color) input_frame.pack() output_frame.pack() button_frame.pack() #Input frame layout list_entry = tkinter.Entry(input_frame, width=35, borderwidth=3, font=my_font) list_add_button = tkinter.Button(input_frame, text="Добавить", borderwidth=2, font=my_font, bg=button_color, command=add_item) list_entry.grid(row=0, column=0, padx=5, pady=5) list_add_button.grid(row=0, column=1, padx=5, pady=5, ipadx=5) #Output frame layout my_scrollbar = tkinter.Scrollbar(output_frame) my_listbox = tkinter.Listbox(output_frame, height=15, width=45, borderwidth=3, font=my_font, yscrollcommand=my_scrollbar.set) #Link scrollbar to listbox my_scrollbar.config(command=my_listbox.yview) my_listbox.grid(row=0, column=0) my_scrollbar.grid(row=0, column=1, sticky="NS") #Button Frame layout list_remove_button = tkinter.Button(button_frame, text="Удалить", borderwidth=2, font=my_font, bg=button_color, command=remove_item) list_clear_button = tkinter.Button(button_frame, text='Очистить', borderwidth=2, font=my_font, bg=button_color, command=clear_list) save_button = tkinter.Button(button_frame, text='Сохранить', borderwidth=2, font=my_font, bg=button_color, command=save_list) quit_button = tkinter.Button(button_frame, text='Выйти', borderwidth=2, font=my_font, bg=button_color, command=root.destroy) list_remove_button.grid(row=0, column=0, padx=2, pady=10) list_clear_button.grid(row=0, column=1, padx=2, pady=10, ipadx=10) save_button.grid(row=0, column=2, padx=2, pady=10, ipadx=10) quit_button.grid(row=0, column=3, padx=2, pady=10, ipadx=25) #Open the previous list if available open_list() #Run the root window's main loop root.mainloop()
24. Приложение в Tkinter и Pyserial для управления 4 контактами Arduino Ссылка
25. Управление светодиодом
Tkinter и Pyserial (Ардуино)
26. Сценарий ком порта
Резюме проекта
Этот проект включает в себя разработку сценария Python для создания терминала последовательного порта на основе графического интерфейса пользователя в Windows. Основной вариант использования — преобразование USB в TTL. Ссылка
27. Изменение шрифта
#tkinter for Python 3.x #Tkinter for Python 2.x import tkinter def quit(): global tkTop tkTop.destroy() def setTextSize(ev=None): global tkLabel global tkScale tkLabel.config(font="Helvetica -%d bold" %tkScale.get()) tkTop = tkinter.Tk() tkTop.geometry('300x200') tkButtonQuit = tkinter.Button(tkTop, text="Quit", command=quit) tkButtonQuit.pack() tkLabel = tkinter.Label(text="Hello Python") tkLabel.pack() tkScale = tkinter.Scale(tkTop, from_=1, to=40, orient=tkinter.HORIZONTAL, command=setTextSize) tkScale.set(18) tkScale.pack(anchor=tkinter.CENTER) tkinter.mainloop()
28. Выпадающий список
Если вы хотите создать раскрывающийся список элементов и разрешить пользователю выбирать элементы списка, вы можете использовать виджет Combobox. Виджет Combobox позволяет создать выпадающий список, в котором можно мгновенно выбрать список элементов. Однако, если вы хотите получить индекс выбранных элементов в виджете со списком, вы можете использовать метод get(). Метод get() возвращает целое число выбранного элемента, известное как индекс элемента.
Пример
Давайте возьмем пример, чтобы увидеть, как это работает. В этом примере мы создали список дней недели в раскрывающемся списке, и всякий раз, когда пользователь выбирает день из раскрывающегося списка, он будет печатать и отображать индекс выбранного элемента в виджете «Label». Чтобы напечатать индекс, мы можем объединить строку, приведя данный индекс к строке.
from tkinter import * from tkinter import ttk # Создайте экземпляр фрейма или окна tkinter window = Tk() # Установить размер окна window.geometry("700x350") # Создайте функцию для очистки поля со списком def clear_combobox(): combobox.set('') # Определить кортеж дней days= ('Понедельник','Вторник','Среда','Четверг','Пятница','Суббота','Воскресенье') # Функция для печати индекса выбранной опции в Combobox def callback(*arg): Label(window, text = 'Индекс равен' + str(combobox.current()) + ' для ' + ' ' + str(var.get()), font = ('Helvetica 12') ).pack() # Создайте виджет со списком var = StringVar() combobox = ttk.Combobox(window, textvariable = var) combobox['values'] = days combobox['state'] = 'readonly' combobox.pack(fill='x',padx= 5, pady=5) # Установите трассировку для данной переменной var.trace('w', callback) # Создайте кнопку, чтобы очистить выбранное текстовое значение поля со списком button = Button(window, text = 'очистить', command = clear_combobox) button.pack() window.mainloop()
Выполнение приведенного выше кода отобразит виджет со списком дней. Всякий раз, когда вы выбираете день из списка, он будет печатать индекс и соответствующий элемент в виджете метки.
29. Форма для ввода пароля (без логики)
# импортируем библиотеку tkinter всю сразу from tkinter import * from tkinter import messagebox # главное окно приложения window = Tk() # заголовок окна window.title('Авторизация') # размер окна window.geometry('450x230') # можно ли изменять размер окна - нет window.resizable(False, False) # кортежи и словари, содержащие настройки шрифтов и отступов font_header = ('Arial', 15) font_entry = ('Arial', 12) label_font = ('Arial', 11) base_padding = {'padx': 10, 'pady': 8} header_padding = {'padx': 10, 'pady': 12} # обработчик нажатия на клавишу 'Войти' def clicked(): # получаем имя пользователя и пароль username = username_entry.get() password = password_entry.get() # выводим в диалоговое окно введенные пользователем данные messagebox.showinfo('Заголовок', '{username}, {password}'.format(username=username, password=password)) # заголовок формы: настроены шрифт (font), отцентрирован (justify), добавлены отступы для заголовка # для всех остальных виджетов настройки делаются также main_label = Label(window, text='Авторизация', font=font_header, justify=CENTER, **header_padding) # помещаем виджет в окно по принципу один виджет под другим main_label.pack() # метка для поля ввода имени username_label = Label(window, text='Имя пользователя', font=label_font , **base_padding) username_label.pack() # поле ввода имени username_entry = Entry(window, bg='#fff', fg='#444', font=font_entry) username_entry.pack() # метка для поля ввода пароля password_label = Label(window, text='Пароль', font=label_font , **base_padding) password_label.pack() # поле ввода пароля password_entry = Entry(window, bg='#fff', fg='#444', font=font_entry) password_entry.pack() # кнопка отправки формы send_btn = Button(window, text='Войти', command=clicked) send_btn.pack(**base_padding) # запускаем главный цикл окна window.mainloop()
30. Проект реализован на PyQt5
Игра . Тетрис.
Эту игру знают все! Главная задача игрока не дать разным, геометрическим фигурам достигнуть “ФИНИША”.
import sys, random
from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication
from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal
from PyQt5.QtGui import QPainter, QColor
Вы видите библиотеки, которые будут использоваться при создании данной игры, всех их нужно загрузить через командную строку вашего компьютера.
После того как установили нужные нам библиотеки, создаём класс с нашими переменными. класс назовём Tetris и будем использовать свойства отцовского класса, чтобы каждый раз не прописывать все переменные заново для каждого последующего класса.
class Tetris(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tboard = Board(self)
self.setCentralWidget(self.tboard)
self.statusbar = self.statusBar()
self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
self.tboard.start()
self.resize(180, 380)
self.center()
self.setWindowTitle('Tetris')
self.show()
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2,
(screen.height()-size.height())/2)
После создания отцовского класса Tetris, создаём все остальные классы и переменные для уже других функций.
class Board(QFrame):
msg2Statusbar = pyqtSignal(str)
BoardWidth = 10
BoardHeight = 22
Speed = 300
def __init__(self, parent):
super().__init__(parent)
self.initBoard()
def initBoard(self):
self.timer = QBasicTimer()
self.isWaitingAfterLine = False
self.curX = 0
self.curY = 0
self.numLinesRemoved = 0
self.board = []
self.setFocusPolicy(Qt.StrongFocus)
self.isStarted = False
self.isPaused = False
self.clearBoard()
def shapeAt(self, x, y):
return self.board[(y * Board.BoardWidth) + x]
def setShapeAt(self, x, y, shape):
self.board[(y * Board.BoardWidth) + x] = shape
def squareWidth(self):
return self.contentsRect().width() // Board.BoardWidth
def squareHeight(self):
return self.contentsRect().height() // Board.BoardHeight
def start(self):
if self.isPaused:
return
self.isStarted = True
self.isWaitingAfterLine = False
self.numLinesRemoved = 0
self.clearBoard()
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.newPiece()
self.timer.start(Board.Speed, self)
def pause(self):
if not self.isStarted:
return
self.isPaused = not self.isPaused
if self.isPaused:
self.timer.stop()
self.msg2Statusbar.emit("paused")
else:
self.timer.start(Board.Speed, self)
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.update()
def paintEvent(self, event):
painter = QPainter(self)
rect = self.contentsRect()
boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight()
for i in range(Board.BoardHeight):
for j in range(Board.BoardWidth):
shape = self.shapeAt(j, Board.BoardHeight - i - 1)
if shape != Tetrominoe.NoShape:
self.drawSquare(painter,
rect.left() + j * self.squareWidth(),
boardTop + i * self.squareHeight(), shape)
if self.curPiece.shape() != Tetrominoe.NoShape:
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.drawSquare(painter, rect.left() + x * self.squareWidth(),
boardTop + (Board.BoardHeight - y - 1) * self.squareHeight(),
self.curPiece.shape())
def keyPressEvent(self, event):
if not self.isStarted or self.curPiece.shape() == Tetrominoe.NoShape:
super(Board, self).keyPressEvent(event)
return
key = event.key()
if key == Qt.Key_P:
self.pause()
return
if self.isPaused:
return
elif key == Qt.Key_Left:
self.tryMove(self.curPiece, self.curX - 1, self.curY)
elif key == Qt.Key_Right:
self.tryMove(self.curPiece, self.curX + 1, self.curY)
elif key == Qt.Key_Down:
self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY)
elif key == Qt.Key_Up:
self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY)
elif key == Qt.Key_Space:
self.dropDown()
elif key == Qt.Key_D:
self.oneLineDown()
else:
super(Board, self).keyPressEvent(event)
def timerEvent(self, event):
if event.timerId() == self.timer.timerId():
if self.isWaitingAfterLine:
self.isWaitingAfterLine = False
self.newPiece()
else:
self.oneLineDown()
else:
super(Board, self).timerEvent(event)
def clearBoard(self):
for i in range(Board.BoardHeight * Board.BoardWidth):
self.board.append(Tetrominoe.NoShape)
def dropDown(self):
newY = self.curY
while newY > 0:
if not self.tryMove(self.curPiece, self.curX, newY - 1):
break
newY -= 1
self.pieceDropped()
def oneLineDown(self):
if not self.tryMove(self.curPiece, self.curX, self.curY - 1):
self.pieceDropped()
def pieceDropped(self):
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.setShapeAt(x, y, self.curPiece.shape())
self.removeFullLines()
if not self.isWaitingAfterLine:
self.newPiece()
def removeFullLines(self):
numFullLines = 0
rowsToRemove = []
for i in range(Board.BoardHeight):
n = 0
for j in range(Board.BoardWidth):
if not self.shapeAt(j, i) == Tetrominoe.NoShape:
n = n + 1
if n == 10:
rowsToRemove.append(i)
rowsToRemove.reverse()
for m in rowsToRemove:
for k in range(m, Board.BoardHeight):
for l in range(Board.BoardWidth):
self.setShapeAt(l, k, self.shapeAt(l, k + 1))
numFullLines = numFullLines + len(rowsToRemove)
if numFullLines > 0:
self.numLinesRemoved = self.numLinesRemoved + numFullLines
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.isWaitingAfterLine = True
self.curPiece.setShape(Tetrominoe.NoShape)
self.update()
def newPiece(self):
self.curPiece = Shape()
self.curPiece.setRandomShape()
self.curX = Board.BoardWidth // 2 + 1
self.curY = Board.BoardHeight - 1 + self.curPiece.minY()
if not self.tryMove(self.curPiece, self.curX, self.curY):
self.curPiece.setShape(Tetrominoe.NoShape)
self.timer.stop()
self.isStarted = False
self.msg2Statusbar.emit("Game over")
def tryMove(self, newPiece, newX, newY):
for i in range(4):
x = newX + newPiece.x(i)
y = newY - newPiece.y(i)
if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight:
return False
if self.shapeAt(x, y) != Tetrominoe.NoShape:
return False
self.curPiece = newPiece
self.curX = newX
self.curY = newY
self.update()
return True
def drawSquare(self, painter, x, y, shape):
colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]
color = QColor(colorTable[shape])
painter.fillRect(x + 1, y + 1, self.squareWidth() - 2,
self.squareHeight() - 2, color)
painter.setPen(color.lighter())
painter.drawLine(x, y + self.squareHeight() - 1, x, y)
painter.drawLine(x, y, x + self.squareWidth() - 1, y)
painter.setPen(color.darker())
painter.drawLine(x + 1, y + self.squareHeight() - 1,
x + self.squareWidth() - 1, y + self.squareHeight() - 1)
painter.drawLine(x + self.squareWidth() - 1,
y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1)
После создаём класс уже для самих объектов( фигур), назовём его Tetrominoe.
class Tetrominoe(object):
NoShape = 0
ZShape = 1
SShape = 2
LineShape = 3
TShape = 4
SquareShape = 5
LShape = 6
MirroredLShape = 7
И ещё один класс, но уже будем задавать координаты фигурам.
class Shape(object):
coordsTable = (
((0, 0), (0, 0), (0, 0), (0, 0)),
((0, -1), (0, 0), (-1, 0), (-1, 1)),
((0, -1), (0, 0), (1, 0), (1, 1)),
((0, -1), (0, 0), (0, 1), (0, 2)),
((-1, 0), (0, 0), (1, 0), (0, 1)),
((0, 0), (1, 0), (0, 1), (1, 1)),
((-1, -1), (0, -1), (0, 0), (0, 1)),
((1, -1), (0, -1), (0, 0), (0, 1))
)
def __init__(self):
self.coords = [[0,0] for i in range(4)]
self.pieceShape = Tetrominoe.NoShape
self.setShape(Tetrominoe.NoShape)
def shape(self):
return self.pieceShape
def setShape(self, shape):
table = Shape.coordsTable[shape]
for i in range(4):
for j in range(2):
self.coords[i][j] = table[i][j]
self.pieceShape = shape
def setRandomShape(self):
self.setShape(random.randint(1, 7))
def x(self, index):
return self.coords[index][0]
def y(self, index):
return self.coords[index][1]
def setX(self, index, x):
self.coords[index][0] = x
def setY(self, index, y):
self.coords[index][1] = y
def minX(self):
m = self.coords[0][0]
for i in range(4):
m = min(m, self.coords[i][0])
return m
И завершаем наш код
def maxX(self):
m = self.coords[0][0]
for i in range(4):
m = max(m, self.coords[i][0])
return m
def minY(self):
m = self.coords[0][1]
for i in range(4):
m = min(m, self.coords[i][1])
return m
def maxY(self):
m = self.coords[0][1]
for i in range(4):
m = max(m, self.coords[i][1])
return m
def rotateLeft(self):
if self.pieceShape == Tetrominoe.SquareShape:
return self
result = Shape()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, self.y(i))
result.setY(i, -self.x(i))
return result
def rotateRight(self):
if self.pieceShape == Tetrominoe.SquareShape:
return self
result = Shape()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, -self.y(i))
result.setY(i, self.x(i))
return result
if __name__ == '__main__':
app = QApplication([])
tetris = Tetris()
sys.exit(app.exec_())
Полный код:
import sys, random
from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication
from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal
from PyQt5.QtGui import QPainter, QColor
class Tetris(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tboard = Board(self)
self.setCentralWidget(self.tboard)
self.statusbar = self.statusBar()
self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
self.tboard.start()
self.resize(180, 380)
self.center()
self.setWindowTitle('Tetris')
self.show()
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2,
(screen.height()-size.height())/2)
class Board(QFrame):
msg2Statusbar = pyqtSignal(str)
BoardWidth = 10
BoardHeight = 22
Speed = 300
def __init__(self, parent):
super().__init__(parent)
self.initBoard()
def initBoard(self):
self.timer = QBasicTimer()
self.isWaitingAfterLine = False
self.curX = 0
self.curY = 0
self.numLinesRemoved = 0
self.board = []
self.setFocusPolicy(Qt.StrongFocus)
self.isStarted = False
self.isPaused = False
self.clearBoard()
def shapeAt(self, x, y):
return self.board[(y * Board.BoardWidth) + x]
def setShapeAt(self, x, y, shape):
self.board[(y * Board.BoardWidth) + x] = shape
def squareWidth(self):
return self.contentsRect().width() // Board.BoardWidth
def squareHeight(self):
return self.contentsRect().height() // Board.BoardHeight
def start(self):
if self.isPaused:
return
self.isStarted = True
self.isWaitingAfterLine = False
self.numLinesRemoved = 0
self.clearBoard()
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.newPiece()
self.timer.start(Board.Speed, self)
def pause(self):
if not self.isStarted:
return
self.isPaused = not self.isPaused
if self.isPaused:
self.timer.stop()
self.msg2Statusbar.emit("paused")
else:
self.timer.start(Board.Speed, self)
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.update()
def paintEvent(self, event):
painter = QPainter(self)
rect = self.contentsRect()
boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight()
for i in range(Board.BoardHeight):
for j in range(Board.BoardWidth):
shape = self.shapeAt(j, Board.BoardHeight - i - 1)
if shape != Tetrominoe.NoShape:
self.drawSquare(painter,
rect.left() + j * self.squareWidth(),
boardTop + i * self.squareHeight(), shape)
if self.curPiece.shape() != Tetrominoe.NoShape:
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.drawSquare(painter, rect.left() + x * self.squareWidth(),
boardTop + (Board.BoardHeight - y - 1) * self.squareHeight(),
self.curPiece.shape())
def keyPressEvent(self, event):
if not self.isStarted or self.curPiece.shape() == Tetrominoe.NoShape:
super(Board, self).keyPressEvent(event)
return
key = event.key()
if key == Qt.Key_P:
self.pause()
return
if self.isPaused:
return
elif key == Qt.Key_Left:
self.tryMove(self.curPiece, self.curX - 1, self.curY)
elif key == Qt.Key_Right:
self.tryMove(self.curPiece, self.curX + 1, self.curY)
elif key == Qt.Key_Down:
self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY)
elif key == Qt.Key_Up:
self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY)
elif key == Qt.Key_Space:
self.dropDown()
elif key == Qt.Key_D:
self.oneLineDown()
else:
super(Board, self).keyPressEvent(event)
def timerEvent(self, event):
if event.timerId() == self.timer.timerId():
if self.isWaitingAfterLine:
self.isWaitingAfterLine = False
self.newPiece()
else:
self.oneLineDown()
else:
super(Board, self).timerEvent(event)
def clearBoard(self):
for i in range(Board.BoardHeight * Board.BoardWidth):
self.board.append(Tetrominoe.NoShape)
def dropDown(self):
newY = self.curY
while newY > 0:
if not self.tryMove(self.curPiece, self.curX, newY - 1):
break
newY -= 1
self.pieceDropped()
def oneLineDown(self):
if not self.tryMove(self.curPiece, self.curX, self.curY - 1):
self.pieceDropped()
def pieceDropped(self):
for i in range(4):
x = self.curX + self.curPiece.x(i)
y = self.curY - self.curPiece.y(i)
self.setShapeAt(x, y, self.curPiece.shape())
self.removeFullLines()
if not self.isWaitingAfterLine:
self.newPiece()
def removeFullLines(self):
numFullLines = 0
rowsToRemove = []
for i in range(Board.BoardHeight):
n = 0
for j in range(Board.BoardWidth):
if not self.shapeAt(j, i) == Tetrominoe.NoShape:
n = n + 1
if n == 10:
rowsToRemove.append(i)
rowsToRemove.reverse()
for m in rowsToRemove:
for k in range(m, Board.BoardHeight):
for l in range(Board.BoardWidth):
self.setShapeAt(l, k, self.shapeAt(l, k + 1))
numFullLines = numFullLines + len(rowsToRemove)
if numFullLines > 0:
self.numLinesRemoved = self.numLinesRemoved + numFullLines
self.msg2Statusbar.emit(str(self.numLinesRemoved))
self.isWaitingAfterLine = True
self.curPiece.setShape(Tetrominoe.NoShape)
self.update()
def newPiece(self):
self.curPiece = Shape()
self.curPiece.setRandomShape()
self.curX = Board.BoardWidth // 2 + 1
self.curY = Board.BoardHeight - 1 + self.curPiece.minY()
if not self.tryMove(self.curPiece, self.curX, self.curY):
self.curPiece.setShape(Tetrominoe.NoShape)
self.timer.stop()
self.isStarted = False
self.msg2Statusbar.emit("Game over")
def tryMove(self, newPiece, newX, newY):
for i in range(4):
x = newX + newPiece.x(i)
y = newY - newPiece.y(i)
if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight:
return False
if self.shapeAt(x, y) != Tetrominoe.NoShape:
return False
self.curPiece = newPiece
self.curX = newX
self.curY = newY
self.update()
return True
def drawSquare(self, painter, x, y, shape):
colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC,
0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]
color = QColor(colorTable[shape])
painter.fillRect(x + 1, y + 1, self.squareWidth() - 2,
self.squareHeight() - 2, color)
painter.setPen(color.lighter())
painter.drawLine(x, y + self.squareHeight() - 1, x, y)
painter.drawLine(x, y, x + self.squareWidth() - 1, y)
painter.setPen(color.darker())
painter.drawLine(x + 1, y + self.squareHeight() - 1,
x + self.squareWidth() - 1, y + self.squareHeight() - 1)
painter.drawLine(x + self.squareWidth() - 1,
y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1)
class Tetrominoe(object):
NoShape = 0
ZShape = 1
SShape = 2
LineShape = 3
TShape = 4
SquareShape = 5
LShape = 6
MirroredLShape = 7
class Shape(object):
coordsTable = (
((0, 0), (0, 0), (0, 0), (0, 0)),
((0, -1), (0, 0), (-1, 0), (-1, 1)),
((0, -1), (0, 0), (1, 0), (1, 1)),
((0, -1), (0, 0), (0, 1), (0, 2)),
((-1, 0), (0, 0), (1, 0), (0, 1)),
((0, 0), (1, 0), (0, 1), (1, 1)),
((-1, -1), (0, -1), (0, 0), (0, 1)),
((1, -1), (0, -1), (0, 0), (0, 1))
)
def __init__(self):
self.coords = [[0,0] for i in range(4)]
self.pieceShape = Tetrominoe.NoShape
self.setShape(Tetrominoe.NoShape)
def shape(self):
return self.pieceShape
def setShape(self, shape):
table = Shape.coordsTable[shape]
for i in range(4):
for j in range(2):
self.coords[i][j] = table[i][j]
self.pieceShape = shape
def setRandomShape(self):
self.setShape(random.randint(1, 7))
def x(self, index):
return self.coords[index][0]
def y(self, index):
return self.coords[index][1]
def setX(self, index, x):
self.coords[index][0] = x
def setY(self, index, y):
self.coords[index][1] = y
def minX(self):
m = self.coords[0][0]
for i in range(4):
m = min(m, self.coords[i][0])
return m
def maxX(self):
m = self.coords[0][0]
for i in range(4):
m = max(m, self.coords[i][0])
return m
def minY(self):
m = self.coords[0][1]
for i in range(4):
m = min(m, self.coords[i][1])
return m
def maxY(self):
m = self.coords[0][1]
for i in range(4):
m = max(m, self.coords[i][1])
return m
def rotateLeft(self):
if self.pieceShape == Tetrominoe.SquareShape:
return self
result = Shape()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, self.y(i))
result.setY(i, -self.x(i))
return result
def rotateRight(self):
if self.pieceShape == Tetrominoe.SquareShape:
return self
result = Shape()
result.pieceShape = self.pieceShape
for i in range(4):
result.setX(i, -self.y(i))
result.setY(i, self.x(i))
return result
if __name__ == '__main__':
app = QApplication([])
tetris = Tetris()
sys.exit(app.exec_())
Что такое Tkinter