class paint: def __init__(self,root): self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.configure(background = 'white') self.root.resizable(0,0) self.pen_color="black" self.eraser_color = "white" #adding widgets to tkinter window self.color_frame = LabelFrame(self.root,text="Color",font=('arial',15),bd=4,relief=RIDGE,bg="white") self.color_frame.place(x = 0,y = 0, width =98, height = 195) colors = ['#ff0000', '#00ff00', '#0000ff' , '#ffff00', '#00ffff', '#ff00ff','#ffffff', '#000000', '#99ffcc', '#ff99cc'] i = j = 0 for color in colors: Button(self.color_frame,bg = color,bd =2, relief=RIDGE,width=2,command = lambda col=color:self.select_color(col)).grid(row = i, column = j) i += 1 if i==5: i = 0 j+=1 self.eraser_button = Button(self.root, text = "Eraser",bd = 4,bg="white",command = self.eraser,width = 8,relief=RIDGE) self.eraser_button.place(x = 0,y = 207) self.clear_button = Button(self.root, text = "Clear",bd = 4,bg="white",command = lambda:self.canvas.delete("all"),width = 8,relief=RIDGE) self.clear_button.place(x = 0,y = 247) self.canvas_color = Button(self.root, text = "Canvas",bd = 4,bg="white",command = self.canvas,width = 8,relief=RIDGE) self.canvas_color.place(x = 0,y = 287) #creating a scale for pen and eraser size.. self.pen_size_scale_frame = LabelFrame(self.root, text="Size", bd=5,bg='white',font=('arial', 15,'bold'),relief=RIDGE) self.pen_size = Scale(self.pen_size_scale_frame,orient=VERTICAL,from_=50,to=0,length=170) self.pen_size.set(1) self.pen_size.grid(row=0,column=1,padx=15) #creating canvas self.canvas = Canvas(self.root,bg='white',bd=5,relief=GROOVE, height=488,width=680) self.canvas.place(x=105,y=7) self.pen_size_scale_frame.place(x=0,y=325,height=190,width=98) #bind canvas with mouse drag self.canvas.bind("<B1-Motion>",self.paint) #function creation def paint(self,event): x1,y1 = (event.x-2),(event.y-2) x2,y2 = (event.x+2),(event.y+2) self.canvas.create_oval(x1,y1,x2,y2,fill=self.pen_color,outline=self.pen_color,width=self.pen_size.get()) def select_color(self,col): self.pen_color =col def eraser(self): self.pen_color = self.eraser_color def canvas(self): color = colorchooser.askcolor() self.canvas.configure(background = color[1]) self.eraser_color = color[1]
def __build_lightness_slider(self): """ Builds a slider that allows the user to adjust light intensity on the scene """ can = self.canvas self.add_title('Light Brightness',4) def adjust(event=None): d = 1 s = int(light_meter.get()) pos = can.config('lighting').get_lighting_parameters()[2][0] can.config('lighting').clear() can.create_light([s,s,s,s],Lighting.Point,position=pos,sharpness=4) can.create_light([s,s,s,s],Lighting.Ambient) textvar.set("Brightness: "+str(s)) can.update_idletasks() light_meter = Scale( self, to = 255, from_ = 1, length = 200 ) light_meter.grid(row=5,column=0) textvar = tk.StringVar() textvar.set("Brightness: 178") tk.Label(self,textvariable=textvar).grid(row=5,column=1) light_meter.set(178) light_meter.configure(command=adjust)
def __build_fog_slider(self): """ Builds a slider that allows the user to adjust light intensity on the scene """ can = self.canvas self.add_title('Fog Scalar',6) def adjust(event=None): d = 1 s = int(fog_meter.get()) can.config('lighting').set_fog_scale(s) if s > 0 and s != 70: textvar.set("Fog Magnitude: "+str(s)) elif s == 70: textvar.set("Fog Magnitude: :)") else: textvar.set("Fog Magnitude: OFF") can.update_idletasks() fog_meter = Scale( self, to = 120, from_ = 0, length = 200 ) fog_meter.grid(row=7,column=0) textvar = tk.StringVar() textvar.set("Darkness: 0") tk.Label(self,textvariable=textvar).grid(row=7,column=1) fog_meter.set(0) fog_meter.configure(command=adjust)
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint Application") self.root.geometry("900x750") self.root.configure(background='white') self.stack = [] self.item = None self.old_x = None self.old_y = None self.old_x_arrow = None self.old_y_arrow = None self.width_val = self.root.winfo_screenwidth() self.height_val = self.root.winfo_screenheight() self.pen_color = 'black' self.eraser_color = 'white' self.save_color = self.pen_color self.choice = 'Pencil' # Adding widgets to tkinter window self.color_frame = LabelFrame(self.root, bd=4, relief=RIDGE, bg="white") self.color_frame.grid(row=0, column=0, pady=(5, 0)) self.color_frame_tooltip = CreateToolTip(self.color_frame, 'Select Brush Color') self.color_frame.config(cursor="hand2") colors = [ '#800000', '#FF0000', '#FFA500', '#FFFF00', '#808000', '#800080', '#FF00FF', '#808080', '#00FF00', '#008000', '#000080', '#0000FF', '#00FFFF', '#008080', '#000000', '#C0C0C0' ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=3, command=lambda col=color: self.select_color(col)).grid( row=i, column=j) i += 1 if i == 8: i = 0 j += 1 self.clear_image = PhotoImage(file='signs.png') self.clear_button = Button(self.root, image=self.clear_image, command=self.clear, width=64) self.clear_button.grid(row=1, column=0, pady=(5, 0)) self.clear_button.config(cursor="hand2") self.clear_button_tooltip = CreateToolTip(self.clear_button, 'Clear the Canvas') self.eraser_image = PhotoImage(file='eraser.png') self.eraser_button = Button(self.root, image=self.eraser_image, command=self.eraser, width=64) self.eraser_button.grid(row=2, column=0) self.eraser_button.config(cursor="hand2") self.eraser_button_tooltip = CreateToolTip(self.eraser_button, 'Eraser') self.line_image = PhotoImage(file='line.png') self.line_button = Button(self.root, image=self.line_image, command=self._createLine, width=64) self.line_button.grid(row=3, column=0) self.line_button.config(cursor="hand2") self.line_button_tooltip = CreateToolTip(self.line_button, 'Straight Line') self.line_arrow_image = PhotoImage(file='arrows.png') self.line_arrow_button = Button(self.root, image=self.line_arrow_image, command=self._createArrowLine, width=64) self.line_arrow_button.grid(row=4, column=0) self.line_arrow_button.config(cursor="hand2") self.line_arrow_button_tooltip = CreateToolTip( self.line_arrow_button, 'Straight Line with Arrow') self.rectangle_image = PhotoImage(file='rectangle.png') self.rectangle_button = Button(self.root, image=self.rectangle_image, command=self._createRectangle, width=64) self.rectangle_button.grid(row=5, column=0) self.rectangle_button.config(cursor="hand2") self.rectangle_button_tooltip = CreateToolTip(self.rectangle_button, 'Rectangle and Square') self.oval_image = PhotoImage(file='oval.png') self.oval_button = Button(self.root, image=self.oval_image, command=self._createOval, width=64) self.oval_button.grid(row=6, column=0) self.oval_button.config(cursor="hand2") self.oval_button_tooltip = CreateToolTip(self.oval_button, 'Oval and Circle') self.pencil_image = PhotoImage(file='pencil.png') self.pencil_button = Button(self.root, image=self.pencil_image, command=self._pencil, width=64) self.pencil_button.grid(row=7, column=0) self.pencil_button.config(cursor="hand2") self.pencil_button_tooltip = CreateToolTip(self.pencil_button, 'Pencil') self.undo_image = PhotoImage(file='undo.png') self.undo_button = Button(self.root, image=self.undo_image, command=self.undo, width=64) self.undo_button.grid(row=9, column=0) self.undo_button.config(cursor="hand2") self.undo_button_tooltip = CreateToolTip(self.undo_button, 'Undo') # self.redo_image = PhotoImage(file='redo.png') # self.redo_button = Button(self.root, image=self.redo_image, command=self.redo, width=64) # self.redo_button.grid(row=8, column=0) # self.redo_button.config(cursor="hand2") # Creating a Scale for pen and eraser size... self.pen_size_scale_frame = Frame(self.root, bd=5, bg='lightblue', relief=RIDGE) self.pen_size_scale_frame.grid(row=10, column=0, pady=5) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=30, to=2, length=170) self.pen_size_tooltip = CreateToolTip( self.pen_size, 'Adjust the size of pen and eraser using this slider.') self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15, pady=5) self.pen_size.config(cursor="hand2") # Creating Canvas self.canvas = Canvas(self.root, bg='white', relief=GROOVE, height=self.height_val, width=self.width_val, cursor="crosshair") self.canvas.place(x=70, y=0) # Binding the canvas with the mouse drag self.canvas.bind("<B1-Motion>", self.paint) self.canvas.bind("<ButtonRelease-1>", self.reset) self.msg = tk.Message(self.root, text=self.choice) self.msg.grid(row=11, column=0, pady=(20, 0)) menu = Menu(self.root) self.root.config(menu=menu) filemenu = Menu(menu) colormenu = Menu(menu) menu.add_cascade(label='Colors', menu=colormenu) colormenu.add_command(label='Brush Color', command=self.brush_color) colormenu.add_command(label='Background Color', command=self.canvas_color) optionmenu = Menu(menu) menu.add_cascade(label='Options', menu=optionmenu) optionmenu.add_command(label='Clear Canvas', command=self.clear) optionmenu.add_command(label='Exit', command=self.root.destroy) menu.add_cascade(label='File', menu=filemenu) filemenu.add_command(label='Save', command=self.save_it) filemenu.add_command(label='Save and Exit', command=self.save_it_destroy) # Function definitions def choice_disp(self): self.msg.config(text=self.choice) def _createRectangle(self): self.choice = 'Rectangle/\nSquare' self.choice_disp() self.rectx0 = 0 self.recty0 = 0 self.rectx1 = 0 self.recty1 = 0 self.rectid = None self.pen_color = self.save_color self.canvas.config(cursor="fleur") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startRect) self.canvas.bind("<ButtonRelease-1>", self.stopRect) self.canvas.bind("<B1-Motion>", self.movingRect) def startRect(self, event): #Translate mouse screen x0,y0 coordinates to canvas coordinates self.rectx0 = self.canvas.canvasx(event.x) self.recty0 = self.canvas.canvasy(event.y) #Create rectangle self.rectid = self.canvas.create_rectangle(self.rectx0, self.recty0, self.rectx0, self.recty0, outline=self.pen_color, width=self.pen_size.get()) def movingRect(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.rectx1 = self.canvas.canvasx(event.x) self.recty1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.rectid, self.rectx0, self.recty0, self.rectx1, self.recty1) def stopRect(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.rectx1 = self.canvas.canvasx(event.x) self.recty1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.rectid, self.rectx0, self.recty0, self.rectx1, self.recty1) self.stack.append(self.rectid) self.stack.append('$') # Delimeter def _createOval(self): self.choice = 'Oval and\nCircle' self.choice_disp() self.ovalx0 = 0 self.ovaly0 = 0 self.ovalx1 = 0 self.ovaly1 = 0 self.ovalid = None self.pen_color = self.save_color self.canvas.config(cursor="fleur") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startOval) self.canvas.bind("<ButtonRelease-1>", self.stopOval) self.canvas.bind("<B1-Motion>", self.movingOval) def startOval(self, event): #Translate mouse screen x0,y0 coordinates to canvas coordinates self.ovalx0 = self.canvas.canvasx(event.x) self.ovaly0 = self.canvas.canvasy(event.y) #Create rectangle self.ovalid = self.canvas.create_oval(self.ovalx0, self.ovaly0, self.ovalx0, self.ovaly0, outline=self.pen_color, width=self.pen_size.get()) def movingOval(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.ovalx1 = self.canvas.canvasx(event.x) self.ovaly1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.ovalid, self.ovalx0, self.ovaly0, self.ovalx1, self.ovaly1) def stopOval(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.ovalx1 = self.canvas.canvasx(event.x) self.ovaly1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.ovalid, self.ovalx0, self.ovaly0, self.ovalx1, self.ovaly1) self.stack.append(self.ovalid) self.stack.append('$') # Delimeter def _createLine(self): self.choice = 'Line' self.choice_disp() self.linex0 = 0 self.liney0 = 0 self.linex1 = 0 self.liney1 = 0 self.lineid = None self.pen_color = self.save_color self.canvas.config(cursor="tcross") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startLine) self.canvas.bind("<ButtonRelease-1>", self.stopLine) self.canvas.bind("<B1-Motion>", self.movingLine) def startLine(self, event): #Translate mouse screen x0,y0 coordinates to canvas coordinates self.linex0 = self.canvas.canvasx(event.x) self.liney0 = self.canvas.canvasy(event.y) #Create rectangle self.lineid = self.canvas.create_line(self.linex0, self.liney0, self.linex0, self.liney0, fill=self.pen_color, width=self.pen_size.get(), smooth=True, capstyle=ROUND) def movingLine(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) def stopLine(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) self.stack.append(self.lineid) self.stack.append('$') # Delimeter def _createArrowLine(self): self.choice = 'Arrow Line' self.choice_disp() self.linex0 = 0 self.liney0 = 0 self.linex1 = 0 self.liney1 = 0 self.lineid = None self.pen_color = self.save_color self.canvas.config(cursor="tcross") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startArrowLine) self.canvas.bind("<ButtonRelease-1>", self.stopArrowLine) self.canvas.bind("<B1-Motion>", self.movingArrowLine) def startArrowLine(self, event): #Translate mouse screen x0,y0 coordinates to canvas coordinates self.linex0 = self.canvas.canvasx(event.x) self.liney0 = self.canvas.canvasy(event.y) #Create rectangle self.lineid = self.canvas.create_line(self.linex0, self.liney0, self.linex0, self.liney0, fill=self.pen_color, arrow="last", arrowshape=(10, 10, 5), width=self.pen_size.get(), smooth=True, capstyle=ROUND) def movingArrowLine(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) def stopArrowLine(self, event): #Translate mouse screen x1,y1 coordinates to canvas coordinates self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) #Modify rectangle x1, y1 coordinates self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) self.stack.append(self.lineid) self.stack.append('$') # Delimeter def _pencil(self): self.choice = 'Pencil' self.choice_disp() self.pen_color = self.save_color self.canvas.config(cursor="crosshair") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<B1-Motion>", self.paint) self.canvas.bind("<ButtonRelease-1>", self.reset) def _pencilArrow(self): self.choice = 'Pencil with\nArrow' self.choice_disp() self.pen_color = self.save_color self.canvas.config(cursor="crosshair") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<B1-Motion>", self.paint_arrow) self.canvas.bind("<ButtonRelease-1>", self.reset_arrow) def undo(self): self.item = self.stack.pop() if ( self.item == '$' ): # For undoing figures like rectangle, oval, circle, square, straight lines. self.item = self.stack.pop() self.canvas.delete(self.item) elif (self.item == '#'): self.item = self.stack.pop() while (self.item != '#' and self.item != '$'): self.canvas.delete(self.item) if len(self.stack) == 0: break self.item = self.stack.pop() if self.item == '#' or self.item == '$': self.stack.append(self.item) # def redo(self): # self.item = self.stack.pop() # self.canvas.delete(self.x) def clear(self): self.canvas.delete(ALL) self.canvas.configure(background='white') def paint(self, event): if self.old_x and self.old_y: self.stack.append( self.canvas.create_line(self.old_x, self.old_y, event.x, event.y, width=self.pen_size.get(), fill=self.pen_color, capstyle=ROUND, smooth=True)) self.old_x = event.x self.old_y = event.y def reset(self, e): # Resetting self.old_x = None self.old_y = None self.stack.append('#') def select_color(self, col): self.pen_color = col self.save_color = col def eraser(self): self.choice = 'Eraser' self.choice_disp() self.canvas.config(cursor="dotbox") self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<B1-Motion>", self.paint) self.canvas.bind("<ButtonRelease-1>", self.reset) self.pen_color = self.eraser_color def brush_color(self): #changing the pen color self.pen_color = colorchooser.askcolor(color=self.pen_color)[1] self.save_color = self.pen_color def canvas_color(self): color = colorchooser.askcolor() self.canvas.configure(background=color[1]) self.eraser_color = color[1] def save_it(self): try: filename = filedialog.asksaveasfilename(defaultextension='.jpg') ImageGrab.grab().save(filename) messagebox.showinfo('Paint says', 'image is saved as ' + str(filename)) except: messagebox.showerror( 'Paint says', 'unable to save image, \n something went wrong') def save_it_destroy(self): try: filename = filedialog.asksaveasfilename(defaultextension='.jpg') ImageGrab.grab().save(filename) messagebox.showinfo('Paint says', 'image is saved as ' + str(filename)) self.root.destroy() except: messagebox.showerror( 'Paint says', 'unable to save image, \n something went wrong')
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.config(background='purple') self.root.resizable(0, 0) self.pen_color = "black" #adding frame self.color_frame = LabelFrame(self.root, text="Color", font=('arial', 15), bd=5, relief=RIDGE, bg='white') self.color_frame.place(x=0, y=0, width=70, height=205) colors = [ '#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#F1510B', '#CD9C10', '#513D53', '#4A7570' ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=3, command=None).grid(row=i, column=j) i += 1 if i == 6: i = 0 j += 1 self.eraser_button = Button(self.root, text="ERASER", bd=4, bg='white', command=None, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=205) self.eraser_button = Button(self.root, text="Clear", bd=4, bg='white', command=None, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=235) self.eraser_button = Button(self.root, text="Save", bd=4, bg='white', command=None, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=265) self.eraser_button = Button(self.root, text="Canvas", bd=4, bg='white', command=None, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=295) self.pen_size_scale_frame = LabelFrame(self.root, text="Size", bd=5, bg='white', font=('arial', 15, 'bold'), relief=RIDGE) self.pen_size_scale_frame.place(x=0, y=325, width=70, height=195) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length=150) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) self.canvas = Canvas(self.root, bg='white', bd=5, relief=GROOVE, height=505, width=715) self.canvas.place(x=70, y=0) self.canvas.bind("<B1-Motion>", self.paint) def paint(self, event): x1, y1 = (event.x - 2), (event.y - 2) x2, y2 = (event.x + 2), (event.y + 2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get())
class GUI: x0 = y0 = x1 = y1 = x_start = y_start = rect_x0 = rect_y0 = rect_x2 = rect_y2 = -1 polygone = [] # polygonesPointsCollection = [] polygone_id_collection = {} polygoneCollection = {} colorCollection = [ 'black', 'red', 'green', 'blue', 'cyan', 'yellow', 'magenta' ] randomColor = random.choice(colorCollection) # fontText = tkFont.Font(family='Helvetica') textHeight = 30 line_tmp = None # format de text in the text-area text_format = "txt" check_mark = u"\u2713" rect = None canvasLigneCollection = [] the_last_draw = None def __init__(self, master): self.master = master self.master.title("Points indicator") # Mode de draw self.draw_mode = "point" # Image self.origin_image = None self.scale = 1.0 self.img = None self.img_id = None # Menu self.menu_bar = Menu(self.master) self.create_menus() # main frame self.frame = Frame(self.master, relief=SUNKEN, bg="red", width=self.master.winfo_width()) self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.frame.pack(fill=None, expand=False) # scroll bars self.xscrollbar = Scrollbar(self.frame, orient=HORIZONTAL) self.xscrollbar.grid(row=2, column=0, columnspan=2, sticky=EW) self.yscrollbar = Scrollbar(self.frame) self.yscrollbar.grid(row=1, column=1, sticky=NS) # canvas to put image self.canvas = Canvas(self.frame, bg="black", bd=0, height=(self.master.winfo_height() - 250), width=(self.master.winfo_width() - 100), xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set) self.canvas.grid(row=1, column=0, sticky=NSEW) self.canvas.config(state=DISABLED) self.xscrollbar.config(command=self.canvas.xview) self.yscrollbar.config(command=self.canvas.yview) # zoom utility buttons self.zoom_in_button = Button(self.frame, text="+", command=lambda: self.zoom(self.scale * 2), width=3) self.zoom_out_button = Button( self.frame, text="-", command=lambda: self.zoom(self.scale * 0.5), width=3) self.zoom_scale = Scale(self.frame, from_=1, to=3, length=80, command=self.on_scale, orient=VERTICAL) self.zoom_in_button.place(relx=0.93, rely=0.03) self.zoom_scale.place(relx=0.93, rely=0.07) self.zoom_out_button.place(relx=0.93, rely=0.18) self.change_zoom_state(0) # Frame to put text self.textFrame = Frame(self.frame, relief=SUNKEN, bg=self.master.cget('bg'), width=(self.master.winfo_width()), height=(self.master.winfo_height() - int(self.canvas['height']) - 50)) self.textFrame.grid_rowconfigure(0, weight=1) self.textFrame.grid_columnconfigure(0, weight=1) self.textFrame.grid(row=3, column=0, columnspan=2, sticky=NSEW) self.textFrame.grid_propagate(False) # text area widget self.textContent = Text(self.textFrame, font='Arial') self.textContent.grid(row=4, column=0, padx=25, pady=25, sticky=NSEW) self.set_text_color_tags() # popup entry value self.roomLabel = StringVar() self.open_file() # bind mouse-click event self.go_to_point_mode() # point mode by default self.canvas.bind("<MouseWheel>", self.on_mouse_wheel) def create_menus(self): """ create pull-down menus, and add it to the menu bar """ # menu File file_menu = Menu(self.menu_bar, tearoff=0) file_menu.add_command(label="New Image", command=self.open_file) file_menu.add_command(label="Save Data", command=self.save_to) file_menu.add_command(label="Load From File", command=self.load_work_from_file) file_menu.add_separator() file_menu.add_command(label="Exit", command=self.master.quit) self.menu_bar.add_cascade(label="File", menu=file_menu) self.master.config(menu=self.menu_bar) # menu Format convert_menu = Menu(self.menu_bar, tearoff=0) convert_menu.add_command(label="Json", command=lambda: self.generate_text("json")) convert_menu.add_command(label="Html", command=lambda: self.generate_text("html")) convert_menu.add_command(label="Text", command=lambda: self.generate_text("txt")) self.menu_bar.add_cascade(label="Format", menu=convert_menu) self.master.config(menu=self.menu_bar) # menu Tools tools_menu = Menu(self.menu_bar, tearoff=0) tools_menu.add_command(label="Copy text to clipboard", command=self.copy_text_to_clipboard) self.menu_bar.add_cascade(label="Tools", menu=tools_menu) self.master.config(menu=self.menu_bar) """ menu Mode (draw mode): [Point mode]: dessiner des polygones par des points [Drag mode]: dessiner des polygones par le tire d'une aire de polygone sur l'interface """ draw_mode_menu = Menu(self.menu_bar, tearoff=0) draw_mode_menu.add_command( label=self.check_mark + " Point", command=lambda: self.change_draw_mode(draw_mode_menu, 'point')) draw_mode_menu.add_command( label=" Drag", command=lambda: self.change_draw_mode(draw_mode_menu, 'drag')) self.menu_bar.add_cascade(label="Mode", menu=draw_mode_menu) self.master.config(menu=self.menu_bar) # menu Undo menu_undo = Menu(self.menu_bar, tearoff=0) menu_undo.add_command(label="Remove the last polygone", command=self.undo_last_polygone) self.menu_bar.add_cascade(label="Undo", menu=menu_undo) self.master.config(menu=self.menu_bar) def end_draw_cycle(self, popup): if self.roomLabel.get() in self.polygoneCollection: self.popup("Id already exist and they are unique.", "#ff3838") self.roomLabel.set('') elif self.roomLabel.get() == '': self.popup("The id can't be empty.", "#ff3838") else: popup.destroy() polygone_str = self.get_formatted_coordinates(self.polygone) # self.textContent.insert('end', self.roomLabel.get() + ': ' + polygone_str+'\n', self.randomColor) self.polygoneCollection[self.roomLabel.get()] = polygone_str self.roomLabel.set('') self.polygone = [] self.remove_polygone_lignes() self.randomColor = self.get_no_repeat_color() self.generate_text(self.text_format) print('restart!') print(self.polygoneCollection) def popup_entry(self): popup = Toplevel() popup.wm_title("Entry an id") popup.wm_geometry("%dx%d%+d%+d" % (220, 80, 450, 300)) popup_label = Label(popup, text="Id : ") popup_label.grid(row=0, padx=10, pady=10) entry = Entry(popup, textvariable=self.roomLabel) entry.grid(row=0, column=1, padx=10, pady=10) entry.focus_set() entry.bind("<Return>", (lambda event: self.end_draw_cycle(popup))) button = Button(popup, text="Ok", command=lambda: self.end_draw_cycle(popup)) button.grid(row=1, columnspan=2, padx=10, pady=10) popup.protocol("WM_DELETE_WINDOW", lambda: self.close_entry_popup_window(popup)) def get_formatted_coordinates(self, the_polygone): """ Retourne un String de coordonées de polygone sous forme: "x0, y0 x1, y1 ... " """ formatted_coordinates = '' for i in range(len(self.polygone)): if i % 2 == 0: # indice paire (x) formatted_coordinates += (str(the_polygone[i]) + ',') else: # impaire (y) formatted_coordinates += (str(the_polygone[i]) + ' ') return formatted_coordinates def get_no_repeat_color(self): """ Retourne une couleur dans la colorCollection autre que la variable 'randomColor' Pour éviter d'avoir 2 fois la suite la meme couleur """ color_collection_copie = self.colorCollection.copy() color_collection_copie.remove(self.randomColor) return random.choice(color_collection_copie) def add_line(self, event): """ MouseClick event pour tracer les polygones """ if self.x0 == -1 and self.y0 == -1: # start drawing (start point: x0, y0) self.change_zoom_state(0) self.x0 = event.x self.y0 = event.y self.x_start = self.x0 self.y_start = self.y0 """ self.x_start = self.mutate_point(self.x0) if self.x_start != self.x0: self.y_start = self.mutate_point(self.y0) else: self.y_start = self.y0 print("after: " + str(self.x_start) + ", " + str(self.y_start)) """ self.polygone.append( self.canvas.canvasx(self.x_start) / self.scale) self.polygone.append( self.canvas.canvasy(self.y_start) / self.scale) else: # in drawing self.x1 = event.x self.y1 = event.y canvas_ligne = self.canvas.create_line( self.canvas.canvasx(self.x0), self.canvas.canvasy(self.y0), self.canvas.canvasx(self.x1), self.canvas.canvasy(self.y1), fill=self.randomColor) self.canvasLigneCollection.append(canvas_ligne) if ((self.x_start - 5) <= self.x1 <= (self.x_start + 5)) and ((self.y_start - 5) <= self.y1 <= (self.y_start + 5)): # endPoint ~ start point (in a range of 5 pixels ): end 1 cycle draw self.x0 = -1 self.y0 = -1 self.the_last_draw = self.canvas.create_polygon( ' '.join( str(points * self.scale) for points in self.polygone), fill=self.randomColor) self.polygone_id_collection[ self.the_last_draw] = self.randomColor # self.polygonesPointsCollection.append(self.polygone) self.popup_entry() self.change_zoom_state(1) else: self.x0 = self.x1 self.y0 = self.y1 """ print(str(self.x1) + ', ' + str(self.y1)) self.x0 = self.mutate_point(self.x1) self.y0 = self.mutate_point(self.y1) print("after: " + str(self.x0) + ", " + str(self.y0)) """ self.polygone.append( self.canvas.canvasx(self.x0, 0.5) / self.scale) self.polygone.append( self.canvas.canvasy(self.y0, 0.5) / self.scale) """ [TODO]: draw with a polygone near by def mutate_point(self, point): if self.polygonesPointsCollection: for polygonPoints in self.polygonesPointsCollection: for pt in polygonPoints: if (pt-10) <= point <= (pt+10): return pt return point """ def cancel_draw(self, e): self.x0 = self.y0 = self.x_start = self.y_start = -1 self.polygone = [] self.popup("Draw cancelled.") self.remove_polygone_lignes() self.change_zoom_state(1) def popup(self, msg, text_color=None): popup = Toplevel(self.master) # popup window par rapport a l'écran TODO: center to root window popup.wm_title("Info") popup.wm_geometry("%dx%d%+d%+d" % (220, 80, 450, 300)) if text_color: popup_label = Label(popup, text=msg, fg=text_color) else: popup_label = Label(popup, text=msg) popup_label.grid(row=0, padx=10, pady=10) button = Button(popup, text="Ok", command=popup.destroy) button.grid(row=1, padx=65, pady=10) def on_mouse_wheel(self, event): self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units") def generate_text(self, text_format): formatted_text = '' if text_format == "json": formatted_text = '{\n\t"value": "", "label": "", \n\t"zones": [\n\t' for key, value in self.polygoneCollection.items(): formatted_text += '\t{"id": "' + key + '", "points": "' + value + '"},\n\t' formatted_text = self.r_replace(formatted_text, ',', '', 1) formatted_text += ']\n}' self.text_format = "json" elif text_format == 'html': for key, value in self.polygoneCollection.items(): formatted_text += '<polygon id="' + key + '" class="st0" points="' + value + '"/>\n' self.text_format = "html" else: for key, value in self.polygoneCollection.items(): formatted_text += (key + ': ' + value + '\n') self.text_format = "txt" self.reload_text_content(formatted_text) def reload_text_content(self, text): self.textContent.delete('1.0', END) self.textContent.insert('1.0', text) def copy_text_to_clipboard(self): text_area_values = self.textContent.get('1.0', END) self.master.clipboard_clear() self.master.clipboard_append(text_area_values) self.popup("Text copied to clipboard, [Ctrl]+[V] to paste.") def set_text_color_tags(self): """ Créer un textTag pour chaque couleur dans 'colorCollection' """ for color in self.colorCollection: self.textContent.tag_config(color, foreground=color) def r_replace(self, s, old, new, occurrence): """ Inversement remplacer le 'old' character 'occurrence' fois par 'new' caracter dans le string 's' """ li = s.rsplit(old, occurrence) return new.join(li) def preview_line(self, event): if self.line_tmp: self.canvas.delete(self.line_tmp) self.line_tmp = None if self.x0 != -1 and self.y0 != -1: x_start = self.x0 y_start = self.y0 self.line_tmp = self.canvas.create_line( self.canvas.canvasx(x_start), self.canvas.canvasy(y_start), self.canvas.canvasx(event.x), self.canvas.canvasy(event.y), fill=self.randomColor) def zoom(self, zoom_scale): if 1 <= zoom_scale <= 4: self.scale = zoom_scale self.zoom_scale.set(self.scale) self.load_image() self.redraw_all_polygone() def load_image(self): self.canvas.delete("all") image_width, image_height = self.origin_image.size size = int(image_width * self.scale), int(image_height * self.scale) self.img = ImageTk.PhotoImage(self.origin_image.resize(size)) self.img_id = self.canvas.create_image(0, 0, image=self.img, anchor=NW) # tell the canvas to scale up/down the vector objects self.canvas.scale(ALL, 0, 0, self.scale, self.scale) self.canvas.configure(scrollregion=self.canvas.bbox("all")) def open_file(self): """ [menu][File][Open] changer l'image sur la quelle qu'on travail """ """ # [DEV] Chemin seulement pour faciliter le développement: à changer en prod file = Image.open("C:/Users/gs63vr/Documents/Grener/app/src/assets/img/confort/N4.png") """ file = askopenfilename(parent=self.master, initialdir="C:/", title='Choose a file to open', filetypes=FileHandler.IMAGE_FILE_TYPES) if file: try: self.origin_image = Image.open(file) self.polygoneCollection = {} self.reload_text_content('') self.load_image() self.change_zoom_state(1) except IOError: self.popup("Can't open the image file!", "#ff3838") def on_button_press(self, event): """ Set x0, y0 du rectangle :param event: on click event """ self.rect = None self.rect_x0 = self.canvas.canvasx(event.x) / self.scale self.rect_y0 = self.canvas.canvasy(event.y) / self.scale def on_move_press(self, event): if self.rect: self.canvas.delete(self.rect) self.rect_x2 = self.canvas.canvasx(event.x) self.rect_y2 = self.canvas.canvasy(event.y) # expand rectangle as you drag the mouse self.rect = self.canvas.create_rectangle(self.rect_x0 * self.scale, self.rect_y0 * self.scale, self.rect_x2, self.rect_y2, fill=self.randomColor) def on_button_release(self, event): self.polygone.extend([ self.rect_x0, self.rect_y0, self.rect_x2 / self.scale, self.rect_y0, self.rect_x2 / self.scale, self.rect_y2 / self.scale, self.rect_x0, self.rect_y2 / self.scale ]) self.the_last_draw = self.rect self.polygone_id_collection[self.the_last_draw] = self.randomColor self.popup_entry() def save_to(self): """ [menu][File][Save] export de fichier """ my_file_handler = FileHandler(self.master) my_file_handler.export_file(self.textContent.get(1.0, END), self.text_format) def load_work_from_file(self): """ [menu][File][Load_from_file] export de fichier """ my_file_handler = FileHandler(self.master) content = my_file_handler.load_file() if my_file_handler.file_extension: self.reinit_variables_from_content(content, my_file_handler.file_extension) self.text_format = my_file_handler.file_extension.replace('.', '') self.reload_text_content(content) def reinit_variables_from_content(self, content_text, extension): # clean global variables self.clean_global_variables() self.polygone_id_collection = {} self.polygoneCollection = {} # Initialisation datas quand reload if extension == '.json': json_obj = json.loads(content_text) for zone in json_obj['zones']: points = zone['points'].replace(',', ' ') polygone = self.canvas.create_polygon(points, fill=self.randomColor) self.polygone_id_collection[polygone] = '' self.polygoneCollection[zone['id']] = zone['points'] elif extension == '.html': my_html_parser = MyHTMLParser() my_html_parser.feed(content_text) for polygone in my_html_parser.polygone_collection: points = polygone[2][1].replace(',', ' ') polygone = self.canvas.create_polygon(points, fill=self.randomColor) self.polygone_id_collection[polygone] = '' self.polygoneCollection[polygone[0][1]] = polygone[2][1] elif extension == '.txt': structured_data = content_text.rstrip('\n') structured_data = [ s.split(': ') for s in structured_data.splitlines() ] for polygon in structured_data: points = polygon[1].replace(',', ' ') polygone = self.canvas.create_polygon(points, fill=self.randomColor) self.polygone_id_collection[polygone] = '' self.polygoneCollection[polygon[0]] = polygon[1] self.randomColor = self.get_no_repeat_color() def on_scale(self, event): value = self.zoom_scale.get() if int(value) != value: self.zoom_scale.set(round(value)) self.scale = round(value) self.zoom(round(value)) def undo_last_polygone(self): """ clean the last drawn """ if self.polygone_id_collection: self.canvas.delete( list(self.polygone_id_collection.items())[-1][0]) self.polygone_id_collection.popitem() # self.canvas.delete(self.the_last_draw) self.clean_global_variables() self.polygoneCollection.popitem() self.generate_text(self.text_format) def change_draw_mode(self, menu, mode_to_change): """ Fonction qui change le mode de draw entre "point mode" et "drag mode" """ if mode_to_change != self.draw_mode: # TODO: [clean] separer le switch de menu dans 2 fonction differents if mode_to_change == 'point': self.go_to_point_mode() menu.entryconfig(0, label=self.check_mark + ' Point') menu.entryconfig(2, label=' Drag') elif mode_to_change == 'drag': self.go_to_drag_mode() menu.entryconfig(0, label=' Point') menu.entryconfig(2, label=self.check_mark + ' Drag') self.draw_mode = mode_to_change def go_to_point_mode(self): self.clean_global_variables() self.canvas.unbind("<ButtonRelease 1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button 1>", self.add_line) self.canvas.bind("<Motion>", self.preview_line) self.canvas.bind("<Button 3>", self.cancel_draw) def go_to_drag_mode(self): """ [Drag Mode] """ self.clean_global_variables() self.canvas.unbind("<Button 3>") self.canvas.bind("<Button 1>", self.on_button_press) self.canvas.bind("<B1-Motion>", self.on_move_press) self.canvas.bind("<ButtonRelease 1>", self.on_button_release) def clean_global_variables(self): """ Réinitialiser les variables globales sauf la collection de polygone :polygoneCollection """ self.x0 = self.y0 = self.x1 = self.y1 = self.x_start = self.y_start = self.rect_x0 = self.rect_y0 = self.rect_x2 = self.rect_y2 = -1 self.polygone = [] self.randomColor = self.get_no_repeat_color() self.line_tmp = None self.rect = None def close_entry_popup_window(self, popup, event=None): popup.destroy() self.canvas.delete(self.the_last_draw) self.remove_polygone_lignes() self.clean_global_variables() def remove_polygone_lignes(self): for canvasLigne in self.canvasLigneCollection: self.canvas.delete(canvasLigne) self.canvasLigneCollection = [] def redraw_all_polygone(self): for polygone_coordinates in self.polygoneCollection.values(): points = polygone_coordinates.replace(',', ' ').rstrip().split(' ') points = [float(point) * self.scale for point in points] canvas_coord = ' '.join(str(s) for s in points) polygone = self.canvas.create_polygon(canvas_coord, fill=self.randomColor) self.polygone_id_collection[polygone] = '' def change_zoom_state(self, state): if state == 0: self.zoom_in_button.state(['disabled']) self.zoom_out_button.state(['disabled']) self.zoom_scale.state(['disabled']) else: self.zoom_in_button.state(['!disabled']) self.zoom_out_button.state(['!disabled']) self.zoom_scale.state(['!disabled'])
class Paint(): def __init__(self, root): self.root = root self.root.title("MyPaint") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0, 0) self.pen_color = "black" self.eraser_color = "white" self.color_frame = LabelFrame(self.root, text="Color", font=( "arial,15"), bd=5, relief=RIDGE, bg="white") self.color_frame.place(x=0, y=0, width=76, height=185) # self.canvas_shapes_frame = LabelFrame(self.root, text="Shapes", font=( # "arial", 15), bd=5, relief=RIDGE, bg="white") # self.canvas_shapes_frame.place(x=0, y=105, width=76, height=80) colors = ["#000000", "#FFFFFF", "#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#00FFFF", "#FF00FF", "#FFFACD", "#F5DEB3", "#C0C0C0", "#DEB887"] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=1, height=2, command=lambda col=color: self.select_color(col)).grid(row=i, column=j) i += 1 if i == 3 or i == 6: i = 0 j += 1 self.color_other_button = Button( self.color_frame, text="Others", bd=4, bg="white", command=self.color_other, width=8, relief=RIDGE) self.color_other_button.place(x=0, y=130, width=68) self.eraser_button = Button( self.root, text="Eraser", bd=4, bg="white", command=self.eraser, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=187, width=76) self.clear_button = Button( self.root, text="Clear", bd=4, bg="white", command=lambda: self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=217, width=76) self.save_button = Button( self.root, text="Save", bd=4, bg="white", command=self.save_image, width=8, relief=RIDGE) self.save_button.place(x=0, y=247, width=76) self.canvas_color_button = Button( self.root, text="Canvas", bd=4, bg="white", command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=277, width=76) # creating a scale for pen and eraser self.pen_size_scale_frame = LabelFrame( self.root, text="Size", bd=5, bg="white", font=("arial", 15, "bold"), relief=RIDGE) self.pen_size_scale_frame.place(x=0, y=310, height=200, width=76) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length=170) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) # creating the canvas self.canvas = Canvas(self.root, bg="white", bd=5, relief=GROOVE, height=500, width=680) self.canvas.place(x=100, y=0) # binding the canvas self.canvas.bind("<B1-Motion>", self.paint) def paint(self, event): x1, y1 = (event.x-2), (event.y-2) x2, y2 = (event.x+2), (event.y+2) self.canvas.create_oval( x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): self.pen_color = col def eraser(self): self.pen_color = self.eraser_color def color_other(self): color = colorchooser.askcolor() self.pen_color = color[1] def canvas_color(self): color = colorchooser.askcolor() self.canvas.configure(background=color[1]) self.eraser_color = color[1] def save_image(self): try: filename = filedialog.asksaveasfilename(defaultextension=".jpg") x = self.root.winfo_rootx()+self.canvas.winfo_x() y = self.root.winfo_rooty()+self.canvas.winfo_y() x1 = x + self.canvas.winfo_width() y1 = y + self.canvas.winfo_height() ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo( "MyPaint says", "Image is saved as" + str(filename)) except: messagebox.showerror("MyPaint says", "Unable to save image")
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.configure(background="#353535") self.root.resizable(0, 0) self.pen_color = "black" self.eraser_color = "white" self.color_frame = LabelFrame(self.root, text="Color", font=("Arial", 15), bd=0, relief=RIDGE, bg="grey") self.color_frame.place(x=0, y=0, width=62, height=185) colors = [ "#5CFF45", "#45F7FF", "#4561FF", "#FF4545", "#000000", "#EFFF32", "#FC32FF", "#FF9C32", "#382500", "#00FFC5", "#FF00BA", "#7E0000" ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=0, relief=RIDGE, width=3, command=lambda col=color: self.select_color(col)).grid( row=i, column=j) i += 1 if i == 6: i = 0 j = 1 self.eraser_button = Button(self.root, text="Eraser", bd=0, bg="#FF6B91", command=self.eraser, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=187) self.clear_button = Button( self.root, text="Clear", bd=0, bg="Red", command=lambda: self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=217) self.canvas_color_button = Button(self.root, text="Fill", bd=0, bg="#6BFFA8", command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=247) self.save_button = Button(self.root, text="Save", bd=0, bg="#00AEFF", command=self.save_paint, width=8, relief=RIDGE) self.save_button.place(x=0, y=277) self.pen_size_scale_frame = LabelFrame(self.root, text="Size", bd="0", bg="grey", font=("Arial", 15), relief=RIDGE) self.pen_size_scale_frame.place(x=0, y=301, height=200, width=62) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length=170) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) self.canvas = Canvas(self.root, bg="white", bd=0, relief=GROOVE, height=500, width=700) self.canvas.place(x=80, y=5) self.canvas.bind("<B1-Motion>", self.paint) def paint(self, event): x1, y1 = (event.x - 2), (event.y - 2) x2, y2 = (event.x - 2), (event.y - 2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): self.pen_color = col def eraser(self): self.pen_color = "white" def canvas_color(self): color = colorchooser.askcolor() self.canvas.configure(background=color[1]) def save_paint(self): try: filename = filedialog.asksaveasfilename( defaultextension='.jpg') x = self.root.winfo_rootx() + self.canvas.winfo_x() y = self.root.winfo_rooty() + self.canvas.winfo_y() x1 = x + self.canvas.winfo_width() y1 = y + self.canvas.winfo_height() ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo("Image Saved:", str(filename)) except: messagebox.showerror("Error: \nSomething went wrong :(")
class Paint(object): def __init__(self, root): self.root = root self.root.title("Paint") self.width_value = self.root.winfo_screenwidth() self.height_value = self.root.winfo_screenheight() self.root.geometry("900x700") self.root.configure(background='white') #self.root.resizable(0, 0) self.pen_color = "black" self.eraser_color = "white" self.save_color = "black" self.old_x = None self.old_y = None self.stack = [] self.line_stack = [] self.item = None self.choice = " Pencil" self.add_widgets() def add_widgets(self): #self.controls.grid(row = 0, column = 0, sticky=NE) self.color_frame = Frame(self.root, bd=1, relief=RIDGE, bg="white") #self.color_frame.place(x = 0, y = 0, width = 185, height = 70) self.color_frame.grid(sticky=NW, row=0, column=0, padx=15, pady=10) self.color_frame.config(cursor="hand2") #self.color_frame.pack() self.palette_image = PhotoImage(file='paint.png') self.palette_button = Button(self.root, image=self.palette_image, command=self.select_palette_color) #self.canvas_button.place(x = 247, y = 0) self.palette_button.grid(sticky="W", row=0, column=1, padx=10, pady=10) self.palette_button.config(cursor="hand2") self.palette_tooltip = CreateToolTip( self.palette_button, 'Select a color from the color palette') colors = [ 'black', 'white', '#4d4d4d', 'grey', '#990033', '#993300', 'red', 'pink', 'orange', '#ffcc99', 'yellow', '#ffff99', 'lime', '#d9ffb3', 'green', '#88cc00', '#0099ff', 'turquoise', '#3333ff', '#6699cc', 'purple', '#bfbff2' ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, height=1, width=3, command=lambda col=color: self.select_color(col)).grid( row=i, column=j) i += 1 if i == 2: i = 0 j += 1 self.pencil_image = PhotoImage(file='pencil.png') self.pencil_button = Button(self.root, image=self.pencil_image, command=self.pencil) #self.pencil.place(x = 0, y = 187) self.pencil_button.grid(sticky="W", row=1, column=0, padx=16) self.pencil_button.config(cursor="hand2") self.pencil_tooltip = CreateToolTip(self.pencil_button, 'Pencil') self.bg_image = PhotoImage(file='bg.png') self.bg_button = Button(self.root, image=self.bg_image, command=self.bg_color) self.bg_button.grid(sticky="W", row=2, column=0, padx=16) self.bg_button.config(cursor="hand2") self.bg_tooltip = CreateToolTip(self.bg_button, 'Change background color') self.eraser_image = PhotoImage(file='eraser.png') self.eraser_button = Button(self.root, image=self.eraser_image, command=self.eraser) #self.eraser.place(x = 0, y = 187) self.eraser_button.grid(sticky="W", row=3, column=0, padx=16) self.eraser_button.config(cursor="hand2") self.eraser_tooltip = CreateToolTip(self.eraser_button, 'Eraser') self.clear_image = PhotoImage(file='clear.png') self.clear_button = Button(self.root, image=self.clear_image, command=self.clear) #self.clear.place(x = 0, y = 217) self.clear_button.grid(sticky="W", row=4, column=0, padx=16) self.clear_button.config(cursor="hand2") self.clear_tooltip = CreateToolTip(self.clear_button, 'Clear the canvas area') self.line_image = PhotoImage(file='line.png') self.line_button = Button(self.root, image=self.line_image, command=self.line) #self.line.place(x = 0, y = 367) self.line_button.grid(sticky="W", row=5, column=0, padx=16) self.line_button.config(cursor="hand2") self.line_tooltip = CreateToolTip(self.line_button, 'Draw a line') self.arrow_image = PhotoImage(file='arrow.png') self.arrow_button = Button(self.root, image=self.arrow_image, command=self.arrow) #self.line.place(x = 0, y = 367) self.arrow_button.grid(sticky="W", row=6, column=0, padx=16) self.arrow_button.config(cursor="hand2") self.arrow_tooltip = CreateToolTip(self.arrow_button, 'Draw an arrow') self.rectangle_image = PhotoImage(file='rectangle.png') self.rectangle_button = Button(self.root, image=self.rectangle_image, command=self.rectangle) #self.rectangle.place(x = 0, y = 307) self.rectangle_button.grid(sticky="W", row=7, column=0, padx=16) self.rectangle_button.config(cursor="hand2") self.rectangle_tooltip = CreateToolTip(self.rectangle_button, 'Draw a rectangle') self.oval_image = PhotoImage(file='oval.png') self.oval_button = Button(self.root, image=self.oval_image, command=self.oval) #self.oval.place(x = 0, y = 397) self.oval_button.grid(sticky="W", row=8, column=0, padx=16) self.oval_button.config(cursor="hand2") self.oval_tooltip = CreateToolTip(self.oval_button, 'Draw an oval/a circle') self.undo_image = PhotoImage(file='undo.png') self.undo_button = Button(self.root, image=self.undo_image, command=self.undo) #self.oval.place(x = 0, y = 397) self.undo_button.grid(sticky="W", row=9, column=0, padx=16) self.undo_button.config(cursor="hand2") self.undo_tooltip = CreateToolTip(self.undo_button, 'Undo') # creating a scale for pen and eraser size self.slider = Frame(self.root, bd=3, bg="white", relief=RIDGE) #self.slider.place(x = 0, y = 400) self.slider.grid(sticky="W", row=10, column=0, padx=16, pady=20) self.pen_size = Scale(self.slider, orient=VERTICAL, from_=50, to=0, length=170) self.pen_size.set(1) self.pen_size.grid(sticky="W", row=10, column=0, ipadx=2, padx=7, pady=7) self.slider.config(cursor="hand2") self.slider_tooltip = CreateToolTip(self.slider, 'Size') # creating canvas self.canvas = Canvas(self.root, relief=GROOVE, height=self.height_value, width=self.width_value, bg="white") self.canvas.place(x=70, y=75) # self.canvas.grid(row = 0, column = 1) # bind the canvas with mouse drag self.canvas.bind('<B1-Motion>', self.paint) self.canvas.bind('<ButtonRelease-1>', self.reset) self.msg = Message(self.root, text=self.choice, width=70, bg="white") self.msg.grid(sticky="W", row=11, column=0) menu = Menu(self.root) self.root.config(menu=menu) filemenu = Menu(menu) colormenu = Menu(menu) menu.add_cascade(label='File', menu=filemenu) filemenu.add_command(label='Save File', command=self.save_file) optionmenu = Menu(menu) menu.add_cascade(label='Options', menu=optionmenu) optionmenu.add_command(label='Exit', command=self.root.destroy) # functions def change_label(self): self.msg.config(text=self.choice) def paint(self, event): if self.old_x and self.old_y: self.line_stack.append( self.canvas.create_line(self.old_x, self.old_y, event.x, event.y, width=self.pen_size.get(), fill=self.pen_color, capstyle=ROUND, smooth=True)) self.oldx = self.old_x self.oldy = self.old_y self.old_x = event.x self.old_y = event.y self.newx = event.x self.newy = event.y def reset(self, event): # reset x and y # self.line_stack.append(self.canvas.create_line(self.oldx, self.oldy, self.newx, self.newy, arrow = 'last', width = self.pen_size.get(), fill = self.pen_color, capstyle=ROUND, smooth=True)) self.old_x = None self.old_y = None self.line_stack.append('#') # print(self.line_stack) def select_color(self, col): self.pen_color = col self.save_color = col def eraser(self): self.pen_color = self.eraser_color self.canvas.bind('<B1-Motion>', self.paint) self.canvas.bind('<ButtonRelease-1>', self.reset) self.canvas.config(cursor="dot") self.choice = " Eraser" self.change_label() def select_palette_color(self): self.choice = " Palette" self.change_label() color = colorchooser.askcolor() self.pen_color = color[1] self.save_color = color[1] #self.canvas.configure(background = color[1]) #self.eraser_color = color[1] def bg_color(self): self.canvas.configure(background=self.pen_color) self.eraser_color = self.pen_color self.choice = " Canvas\n Color" self.change_label() def clear(self): self.canvas.configure(background="white") self.canvas.delete("all") def undo(self): try: if self.line_stack[-1] == '$': self.item = self.stack.pop() self.line_stack.pop() else: if self.line_stack[-1] == '#': self.item = self.line_stack.pop() while (1): if len(self.line_stack) == 0: break elif len(self.stack) != 0 or len(self.line_stack) != 0: # print(self.line_stack) if self.line_stack[-1] != '#' and self.line_stack[ -1] != '$': self.item = self.line_stack.pop() self.canvas.delete(self.item) else: break else: break self.canvas.delete(self.item) except LookupError: print("LookupError: list index out of range") self.choice = " Undo" self.change_label() def pencil(self): self.pen_color = self.save_color self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<B1-Motion>", self.paint) self.canvas.bind("<ButtonRelease-1>", self.reset) self.canvas.config(cursor="pencil") self.choice = " Pencil" self.change_label() def rectangle(self): self.rectx0 = 0 self.recty0 = 0 self.rectx1 = 0 self.recty1 = 0 self.rectid = None self.pen_color = self.save_color self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startRect) self.canvas.bind("<ButtonRelease-1>", self.stopRect) self.canvas.bind("<B1-Motion>", self.movingRect) self.canvas.config(cursor="crosshair") self.choice = " Rectangle" self.change_label() def startRect(self, event): self.rectx0 = self.canvas.canvasx(event.x) self.recty0 = self.canvas.canvasy(event.y) self.rectid = self.canvas.create_rectangle(self.rectx0, self.recty0, self.rectx0, self.recty0, outline=self.pen_color, width=self.pen_size.get()) def movingRect(self, event): self.rectx1 = self.canvas.canvasx(event.x) self.recty1 = self.canvas.canvasy(event.y) self.canvas.coords(self.rectid, self.rectx0, self.recty0, self.rectx1, self.recty1) def stopRect(self, event): self.rectx1 = self.canvas.canvasx(event.x) self.recty1 = self.canvas.canvasy(event.y) self.canvas.coords(self.rectid, self.rectx0, self.recty0, self.rectx1, self.recty1) self.stack.append(self.rectid) self.line_stack.append('$') def line(self): self.linex0 = 0 self.liney0 = 0 self.linex1 = 0 self.liney1 = 0 self.lineid = None self.pen_color = self.save_color self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startLine) self.canvas.bind("<ButtonRelease-1>", self.stopLine) self.canvas.bind("<B1-Motion>", self.movingLine) self.canvas.config(cursor="crosshair") self.choice = " Line" self.change_label() def startLine(self, event): self.linex0 = self.canvas.canvasx(event.x) self.liney0 = self.canvas.canvasy(event.y) self.lineid = self.canvas.create_line(self.linex0, self.liney0, self.linex0, self.liney0, fill=self.pen_color, width=self.pen_size.get()) def movingLine(self, event): self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) def stopLine(self, event): self.linex1 = self.canvas.canvasx(event.x) self.liney1 = self.canvas.canvasy(event.y) self.canvas.coords(self.lineid, self.linex0, self.liney0, self.linex1, self.liney1) self.stack.append(self.lineid) self.line_stack.append('$') def arrow(self): self.arrowx0 = 0 self.arrowy0 = 0 self.arrowx1 = 0 self.arrowy1 = 0 self.arrowid = None self.pen_color = self.save_color self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startArrow) self.canvas.bind("<ButtonRelease-1>", self.stopArrow) self.canvas.bind("<B1-Motion>", self.movingArrow) self.canvas.config(cursor="crosshair") self.choice = " Arrow" self.change_label() def startArrow(self, event): self.arrowx0 = self.canvas.canvasx(event.x) self.arrowy0 = self.canvas.canvasy(event.y) self.arrowid = self.canvas.create_line(self.arrowx0, self.arrowy0, self.arrowx0, self.arrowy0, arrow='last', fill=self.pen_color, width=self.pen_size.get()) def movingArrow(self, event): self.arrowx1 = self.canvas.canvasx(event.x) self.arrowy1 = self.canvas.canvasy(event.y) self.canvas.coords(self.arrowid, self.arrowx0, self.arrowy0, self.arrowx1, self.arrowy1) def stopArrow(self, event): self.arrowx1 = self.canvas.canvasx(event.x) self.arrowy1 = self.canvas.canvasy(event.y) self.canvas.coords(self.arrowid, self.arrowx0, self.arrowy0, self.arrowx1, self.arrowy1) self.stack.append(self.arrowid) self.line_stack.append('$') def oval(self): self.ovalx0 = 0 self.ovaly0 = 0 self.ovalx1 = 0 self.ovaly1 = 0 self.ovalid = None self.pen_color = self.save_color self.canvas.unbind("<Button-1>") self.canvas.unbind("<ButtonRelease-1>") self.canvas.unbind("<B1-Motion>") self.canvas.bind("<Button-1>", self.startOval) self.canvas.bind("<ButtonRelease-1>", self.stopOval) self.canvas.bind("<B1-Motion>", self.movingOval) self.canvas.config(cursor="crosshair") self.choice = " Oval" self.change_label() def startOval(self, event): self.ovalx0 = self.canvas.canvasx(event.x) self.ovaly0 = self.canvas.canvasy(event.y) self.ovalid = self.canvas.create_oval(self.ovalx0, self.ovaly0, self.ovalx0, self.ovaly0, outline=self.pen_color, width=self.pen_size.get()) def movingOval(self, event): self.ovalx1 = self.canvas.canvasx(event.x) self.ovaly1 = self.canvas.canvasy(event.y) self.canvas.coords(self.ovalid, self.ovalx0, self.ovaly0, self.ovalx1, self.ovaly1) def stopOval(self, event): self.ovalx1 = self.canvas.canvasx(event.x) self.ovaly1 = self.canvas.canvasy(event.y) self.canvas.coords(self.ovalid, self.ovalx0, self.ovaly0, self.ovalx1, self.ovaly1) self.stack.append(self.ovalid) self.line_stack.append('$') def save_file(self): try: filename = filedialog.asksaveasfilename(defaultextension='.png') '''x = self.root.winfo_rootx() + self.canvas.winfo_x() y = self.root.winfo_rooty() + self.canvas.winfo_y() x1 = x + self.canvas.winfo_width() y1 = y + self.canvas.winfo_height()''' ImageGrab.grab().save(filename) messagebox.showinfo('Paint', 'Image is saved as ' + str(filename)) except: messagebox.showerror('Paint', 'Unable to save image!')
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0, 0) self.pen_color = "#000000" self.color_frame = LabelFrame(self.root, text="Color", font=('arial', 15, 'bold'), bd=5, relief=RIDGE, bg='white') self.color_frame.place(x=0, y=0, width=70, height=185) Colors = [ '#ff0000', '#ff4dd2', '#ffff33', '#000000', '#0066ff', '#660033', '#4dff4d', '#b300b3', '#00ffff', '#808080', '#99ffcc', '#336600', '#ff9966', '#ff99ff', '#00cc99', ] i = j = 0 for color in Colors: Button(self.color_frame, bg=color, command=lambda col=color: self.select_color(col), width=3, bd=2, relief=RIDGE).grid(row=i, column=j) i += 1 if i == 6: i = 0 j = 1 self.erase_button = Button(self.root, text="Eraser", bd=4, relief=RIDGE, width=8, command=self.eraser, bg="white") self.erase_button.place(x=0, y=187) self.clear_sreen_button = Button( self.root, text="Clear", bd=4, relief=RIDGE, width=8, command=lambda: self.canvas.delete("all"), bg="white") self.clear_sreen_button.place(x=0, y=217) self.save_button = Button(self.root, text="Save", bd=4, relief=RIDGE, width=8, command=self.save_paint, bg="white") self.save_button.place(x=0, y=247) self.canvas_color_button = Button(self.root, text="Canvas", bd=4, relief=RIDGE, width=8, command=self.canvas_color, bg="white") self.canvas_color_button.place(x=0, y=277) self.pen_size_scale_frame = LabelFrame(self.root, text="Size", bd=5, relief=RIDGE, bg="white", font=('arial', 15, 'bold')) self.pen_size_scale_frame.place(x=0, y=310, height=200, width=70) self.pen_size = Scale(self.pen_size_scale_frame, orient='vertical', from_=50, to=0, command=None, length=170) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) self.canvas = Canvas(self.root, bg='white', bd=5, relief='groove', height=500, width=700) self.canvas.place(x=80, y=0) # Blind mouse dragging event to canvas self.canvas.bind("<B1-Motion>", self.paint) def paint(self, event): global pen_color x1, y1 = (event.x - 2), (event.y - 2) x2, y2 = (event.x + 2), (event.y + 2) if (i): self.canvas.config(cursor='plus') self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): global i i = 1 self.pen_color = col def eraser(self): global color global i self.pen_color = color self.canvas.config(cursor='dot') i = 0 def canvas_color(self): global color color = colorchooser.askcolor() color = color[1] self.canvas.config(background=color) def save_paint(self): try: self.canvas.update() filename = asksaveasfilename(defaultextension='.jpg') print(filename) x = self.root.winfo_rootx() + self.canvas.winfo_x() #print(x) y = self.root.winfo_rooty() + self.canvas.winfo_y() #print(y) x1 = x + self.canvas.winfo_width() #print(x1) y1 = y + self.canvas.winfo_height() #print(y1) ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo('paint says ', 'image is saved as ' + str(filename)) except: pass
bg=bgr, image=refreshimg) refreshbut.place(x=int(ws * (235 / dw)), y=nety + int(hs * (405 / dh))) stylescale = Style(fr) #vol =tk.Scale(fr,borderwidth=0,command=controlvol,showvalue='no',highlightthickness=0,length=140,width=18,bg=bgr,from_ = 100,to = 0,orient = tk.VERTICAL ,resolution = 10) vol = Scale(fr, orient='vertical', length=int((hs * 140) / dh), from_=100, to=0, style="TScale") vol.bind('<MouseWheel>', volscroll) vol.bind('<Button-1>', middlevol) vol.place(x=int(ws * (260 / dw)), y=nety + int(hs * (185 / dh))) vol.set(100) #timeslider =tk.Scale(fr,borderwidth=0, bg=bgr,showvalue='no',width=18,highlightthickness=0,length=int(ws*(300/dw)),from_=0, to=100, resolution=1, orient=tk.HORIZONTAL) timeslider = Scale(fr, orient='horizontal', length=ws, from_=0, to=100, style="TScale") timeslider.bind('<Button-1>', middleplay) timeslider.place(x=0, y=nety + int(hs * (360 / dh))) stylescale.configure("TScale", background=bgr) tv = tk.StringVar() time_elapsed = tk.Label(fr, bg=bgr, fg='white', textvariable=tv)
class Paint(object): def __init__(self, root): #Properties of the objects self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0, 0) # Important things self.pen_color = "black" self.eraser_color = "white" #Adding widgets to tkinter window self.color_frame = LabelFrame(self.root, text="color", font = ("arial", 15), bd=5, relief=RIDGE, bg="white") self.color_frame.place(x=0, y=0, width=70, height=185) colors = ["#000000","#FFFFFF" , "#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#00FFFF", "#FF00FF", "#C0C0C0", "#808080", "#800000", "#808000", "#008000", "#800080", "#008080", "#000080"] i=j=0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=3, command=lambda col =color:self.select_color(col)).grid(row=i, column=j) i+=1 if i==6: i=0 j=1 self.eraser_button = Button(self.root, text="ERASER", bg="white", bd=4, command=self.eraser, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=187) self.clear_button = Button(self.root, text="CLEAR", bg="white", bd=4, command=lambda : self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=217) self.save_button = Button(self.root, text="SAVE", bg="white", bd=4, command=self.save_paint, width=8, relief=RIDGE) self.save_button.place(x=0, y=247) self.canvas_color_button = Button(self.root, text="CANVAS", bg="white", bd=4, command=self.canvas, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=277) #Creating a scale for pen and eraser size self.pen_size_scale_frame = LabelFrame(self.root, text="size", bd=5, bg="white", font=("arial", 15, 'bold'), relief=RIDGE) self.pen_size_scale_frame.place(x=0, y=310, height=200, width=70) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to_=0, length=170) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) #Creating Canvas self.canvas = Canvas(self.root, bg="white", bd=5, relief=GROOVE, height=500, width=700) self.canvas.place(x=80, y=0) #Bind the canvas with mouse drag self.canvas.bind("<B1-Motion>", self.paint) #Functions are defined here def paint(self, event): x1, y1 = (event.x-2, event.y-2) x2, y2 = (event.x+2, event.y+2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): #Selects the color self.pen_color = col def eraser(self): # Select the eraser self.pen_color = self.eraser_color def canvas(self): #changes canvas colour color = colorchooser.askcolor() self.canvas.configure(background=color[1]) self.eraser_color = color[1] def save_paint(self): #Save the painting try: filename = filedialog.asksaveasfilename(defaultextension=".jpg") x = self.root.winfo_rootx() + self.canvas.winfo_x() y = self.root.winfo_rooty() + self.canvas.winfo_y() x1 = x + self.canvas.winfo_width() y1 = y + self.canvas.winfo_height() ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo("paint says", "image is saved as" + str(filename)) except: #Show error dialog is something went wrong while saving messagebox.showerror("paint says", "enable to save image,\n something went wrong" )
relief=RIDGE, bd=0) shape_label.place(x=350, y=720) dots_visibility_button = Button(root, text="show/hide dots", bd=2, bg="white", width=15, height=1, command=_toggle_vis_circles) dots_visibility_button.place(x=15, y=720) zoom_lable = Label(root, text="Zoom:", relief=RIDGE, bd=0) zoom_lable.place(x=15, y=765) zoom_scale = Scale(root, orient=HORIZONTAL, from_=10, to=170, length=200, command=_scale) zoom_scale.set(zoom) zoom_scale.place(x=70, y=765) ######## initialisation ##### _update_all() root.bind('<Motion>', motion) root.config(cursor="@move.cur") root.mainloop()
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0, 0) self.pen_color = "black" self.eraser_color = "white" self.color_frame = LabelFrame(self.root, text='Color', font=('arial', 15), bd=5, relief=RIDGE, bg="white") self.color_frame.place(x=0, y=0, width=70, height=185) colors = [ 'red', 'blue', 'yellow', 'green', 'cyan', 'purple', 'violet', 'pink', 'orange', 'brown', 'black', 'white' ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=3, command=lambda col=color: self.select_color(col)).grid( row=i, column=j) i += 1 if i == 6: i = 0 j += 1 self.eraser_button = Button(self.root, text="ERASER", bd=4, bg='white', command=self.eraser, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=187) self.clear_button = Button(self.root, text="CLEAR", bd=4, bg='white', command=lambda: self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=217) self.save_button = Button(self.root, text="SAVE", bd=4, bg='white', command=self.save_paint, width=8, relief=RIDGE) self.save_button.place(x=0, y=247) self.canvas_color_button = Button(self.root, text="CANVAS", bd=4, bg='white', command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=277) self.custom_color_button = Button(self.root, text="COLOR", bd=4, bg='white', command=self.custom_color, width=8, relief=RIDGE) self.custom_color_button.place(x=0, y=307) self.pen_size_scale_frame = LabelFrame(self.root, text='Size', font=('arial', 15), bd=5, relief=RIDGE, bg="white") self.pen_size_scale_frame.place(x=0, y=337, width=70, height=170) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length=140) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) self.canvas = Canvas(self.root, bg='white', bd=5, relief=GROOVE, height=500, width=700) self.canvas.place(x=80, y=0) self.canvas.bind("<B1-Motion>", self.paint) def paint(self, event): x1, y1 = (event.x - 2), (event.y - 2) x2, y2 = (event.x + 2), (event.y + 2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): self.pen_color = col def eraser(self): self.pen_color = self.eraser_color def canvas_color(self): color = colorchooser.askcolor() self.eraser_color = color[1] self.canvas.configure(background=color[1]) def custom_color(self): color = colorchooser.askcolor() self.pen_color = color[1] def save_paint(self): try: self.canvas.update() filename = filedialog.asksaveasfilename(defaultextension='.jpg') x = self.root.winfo_rootx() + self.canvas.winfo_x() y = self.root.winfo_rooty() + self.canvas.winfo_y() x1 = x + self.canvas.winfo_width() y1 = y + self.canvas.winfo_height() ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo('Paint Says ', 'Image Is Saved As ' + str(filename)) except: messagebox.showinfo('Paint Says ', 'Something Went Wrong, Cannot Save File')
class Slider(Frame): MINIMO = 100 MAXIMO = 2400 def __init__(self, master, label, *args, **kwargs): ''' parametros ---------- master : tkinter.widget label : str ''' super(Slider, self).__init__(master, *args, **kwargs) self._criar_estilo_label() self._criar_scale() self._criar_spinbox() self._criar_label(label) self.set_atual(self.MINIMO) def _criar_estilo_label(self): estilo = Style() estilo.configure('Slider.TLabel', font=('Arial', 14, 'normal')) def _criar_label(self, label): ''' Criar label. ''' frame = Frame(self, width=150, height=50) label = Label(frame, text=label, anchor='center', style='Slider.TLabel') label.bind('<Double-Button-1>', lambda e: self._spinbox.focus()) label.pack(fill='both', expand=True, padx=5, pady=5) frame.pack(side='left') frame.pack_propagate(False) def _criar_spinbox(self): ''' Criar Widget spinbox. ''' self._spinbox = Spinbox(self, from_=self.MINIMO, to=self.MAXIMO, font=('Arial', 14, 'normal'), width=10) self._spinbox['command'] = lambda: \ self.set_atual(self._spinbox.get(), widget=self._spinbox) self._spinbox.bind('<Return>', lambda e: \ self.set_atual(self._spinbox.get())) self._spinbox.pack(side='left', anchor='center') def _criar_scale(self): ''' Criar widget Scale. ''' self._scale = Scale(self, from_=self.MINIMO, to=self.MAXIMO, orient='horizontal') self._scale['command'] = lambda e: \ self.set_atual(self._scale.get(), widget=self._scale) self._scale.pack(side='left', fill='x', anchor='center', expand=True, ) def atual(self): ''' Obter o valor atual retornos -------- int ''' return self._scale.get() def set_atual(self, atual, **kwargs): ''' Define o valor atual. parametros ---------- atual : int ''' # caractere númerico é convertido em inteiro. if isinstance(atual, str) and atual.isdigit(): atual = int(atual) # caractere não númerico convertido em inteiro. if not isinstance(atual, int): atual = self._scale.get() # atual fora do range. if atual not in range(self.MINIMO, self.MAXIMO): atual = self._scale.get() widget = kwargs.get('widget') if widget: if isinstance(widget, Scale): self._spinbox.delete(0, 'end') self._spinbox.insert(0, str(atual)) elif isinstance(widget, Spinbox): self._scale.set(atual) else: self._spinbox.delete(0, 'end') self._spinbox.insert(0, str(atual)) self._scale.set(atual)
class aFrame(Frame): stepy = False stepx = False dc_running = False Motor1E = 22 Motor1A = 16 Motor1B = 18 Motor2E = 15 Motor2B = 11 Motor2A = 13 w = None def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.imageName = "" self.w = Scale(parent, from_=1, to=100, orient=HORIZONTAL) self.w.place(x=600, y=140) self.w.set(100) GPIO.setup(self.Motor1A, GPIO.OUT) GPIO.setup(self.Motor1B, GPIO.OUT) GPIO.setup(self.Motor1E, GPIO.OUT) GPIO.setup(self.Motor2A, GPIO.OUT) GPIO.setup(self.Motor2B, GPIO.OUT) GPIO.setup(self.Motor2E, GPIO.OUT) self.initUI() def initUI(self): self.parent.title("DC Motor Control Box") self.style = Style().configure("TFrame", background="#333") # self.iconbitmap("icon.png") # self.style.theme_use("default") self.pack(fill=BOTH, expand=1) # quitButton = Button(self, text="Open File", command=self.onFilePicker) # quitButton.place(x=10, y=10) printButton = Button(self, text="Forward", command=self.forward_dc) printButton2 = Button(self, text="Left", command=self.left_dc) printButton3 = Button(self, text="Back", command=self.backwards_dc) printButton4 = Button(self, text="Right", command=self.right_dc) printButton5 = Button(self, text="Stop Motors", command=self.stop_dc) printButton6 = Button(self, text="Quit", command=self.quit) printButton7 = Button(self, text="Stop Stepper Y", command=self.stop_steppery) printButton8 = Button(self, text="Stepper up", command=self.thread_step_up) printButton9 = Button(self, text="Stepper Left", command=self.thread_step_left) printButton10 = Button(self, text="Stepper Down", command=self.thread_step_down) printButton11 = Button(self, text="Stepper Right", command=self.thread_step_right) printButton12 = Button(self, text="Stop Stepper X", command=self.stop_stepperx) printButton.place(x=200, y=40) printButton2.place(x=110, y=90) printButton3.place(x=200, y=90) printButton4.place(x=290, y=90) printButton5.place(x=210, y=200) printButton6.place(x=350, y=200) printButton7.place(x=400, y=85) printButton8.place(x=400, y=40) printButton9.place(x=500, y=90) printButton10.place(x=400, y=130) printButton11.place(x=710, y=90) printButton12.place(x=600, y=90) # self.thread_step_up() self.centerWindow() def set_speed(sefl, val): return round(-(0.09 / 100) * val + 0.1, 3) def centerWindow(self): w = 1000 h = 300 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w) / 2 y = (sh - h) / 2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def onDetect(self): pass def stop_dc(self): # print(self.w.get()) # print(self.set_speed(self.w.get())) GPIO.output(self.Motor1E, False) GPIO.output(self.Motor2E, False) self.dc_running = False def forward_dc(self): if self.dc_running is True: self.stop_dc() else: GPIO.output(self.Motor1A, True) GPIO.output(self.Motor1B, False) GPIO.output(self.Motor1E, True) GPIO.output(self.Motor2A, True) GPIO.output(self.Motor2B, False) GPIO.output(self.Motor2E, True) self.dc_running = True def backwards_dc(self): if self.dc_running is True: self.stop_dc() else: GPIO.output(self.Motor1A, False) GPIO.output(self.Motor1B, True) GPIO.output(self.Motor1E, True) GPIO.output(self.Motor2A, False) GPIO.output(self.Motor2B, True) GPIO.output(self.Motor2E, True) self.dc_running = True def left_dc(self): if self.dc_running is True: self.stop_dc() else: GPIO.output(self.Motor1A, False) GPIO.output(self.Motor1B, True) GPIO.output(self.Motor1E, True) GPIO.output(self.Motor2A, True) GPIO.output(self.Motor2B, False) GPIO.output(self.Motor2E, True) self.dc_running = True def right_dc(self): if self.dc_running is True: self.stop_dc() else: GPIO.output(self.Motor1A, True) GPIO.output(self.Motor1B, False) GPIO.output(self.Motor1E, True) GPIO.output(self.Motor2A, False) GPIO.output(self.Motor2B, True) GPIO.output(self.Motor2E, True) self.dc_running = True def stepper_up(self): # print(1) StepPins = [40, 38, 36, 37] direction = 1 for pin in StepPins: #pass GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) Seq = [[1, 0, 0, 1], [1, 0, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 1]] StepCount = len(Seq) StepCounter = 0 while self.stepy is True: sleep(self.set_speed(self.w.get())) # print StepCounter, # print Seq[StepCounter] for pin in range(0, 4): xpin = StepPins[pin] if Seq[StepCounter][pin] != 0: # print " Enable GPIO %i" %(xpin) GPIO.output(xpin, True) else: GPIO.output(xpin, False) StepCounter += direction if (StepCounter >= StepCount): StepCounter = 0 if (StepCounter < 0): StepCounter = StepCount + direction for pin in StepPins: # print "Setup pins" GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) def stepper_down(self): StepPins = [40, 38, 36, 37] direction = -1 for pin in StepPins: #pass GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) Seq = [[1, 0, 0, 1], [1, 0, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 1]] StepCount = len(Seq) StepCounter = 0 while self.stepy is True: sleep(self.set_speed(self.w.get())) # print StepCounter, # print Seq[StepCounter] for pin in range(0, 4): xpin = StepPins[pin] if Seq[StepCounter][pin] != 0: # print " Enable GPIO %i" %(xpin) GPIO.output(xpin, True) else: GPIO.output(xpin, False) StepCounter += direction if (StepCounter >= StepCount): StepCounter = 0 if (StepCounter < 0): StepCounter = StepCount + direction for pin in StepPins: # print "Setup pins" GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) def stepper_left(self): # print(1) StepPins = [33, 31, 29, 32] direction = 1 for pin in StepPins: #pass GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) Seq = [[1, 0, 0, 1], [1, 0, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 1]] StepCount = len(Seq) StepCounter = 0 while self.stepx is True: sleep(self.set_speed(self.w.get())) # print StepCounter, # print Seq[StepCounter] for pin in range(0, 4): xpin = StepPins[pin] if Seq[StepCounter][pin] != 0: # print " Enable GPIO %i" %(xpin) GPIO.output(xpin, True) else: GPIO.output(xpin, False) StepCounter += direction if (StepCounter >= StepCount): StepCounter = 0 if (StepCounter < 0): StepCounter = StepCount + direction for pin in StepPins: # print "Setup pins" GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) def stepper_right(self): StepPins = [33, 31, 29, 32] direction = -1 for pin in StepPins: #pass GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) Seq = [[1, 0, 0, 1], [1, 0, 0, 0], [1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 1, 1], [0, 0, 0, 1]] StepCount = len(Seq) StepCounter = 0 while self.stepx is True: sleep(self.set_speed(self.w.get())) # print StepCounter, # print Seq[StepCounter] for pin in range(0, 4): xpin = StepPins[pin] if Seq[StepCounter][pin] != 0: # print " Enable GPIO %i" %(xpin) GPIO.output(xpin, True) else: GPIO.output(xpin, False) StepCounter += direction if (StepCounter >= StepCount): StepCounter = 0 if (StepCounter < 0): StepCounter = StepCount + direction for pin in StepPins: # print "Setup pins" GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, False) def stop_steppery(self): self.stepy = False def stop_stepperx(self): self.stepx = False def thread_step_up(self): self.stepy = True _thread.start_new_thread(self.stepper_up, ()) def thread_step_down(self): self.stepy = True _thread.start_new_thread(self.stepper_down, ()) def thread_step_left(self): self.stepx = True _thread.start_new_thread(self.stepper_left, ()) def thread_step_right(self): self.stepx = True _thread.start_new_thread(self.stepper_right, ())
class Paint(): def __init__(self, root): self.root = root self.root.title("Paint in Python") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0, 0) self.root.iconbitmap('icons/paint.ico') # imp thing self.pen_color = "black" self.eraser_color = "white" # adding widgeths to tkinter window self.color_frame = LabelFrame(self.root, text="color", font=('arial, 13'), bd=5, relief=RIDGE, bg="white") self.color_frame.place(x=0, y=0, width=70, height=185) colors = [ '#ff0000', '#ff4dd2', '#ffff33', '#000000', '#0066ff', '#660033', '#4dff4d', '#b300b3', '#00ffff', '#00ffff', '#808080', '#99ffcc' ] i = j = 0 for color in colors: Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=3, command=lambda col=color: self.select_color(col)).grid( row=i, column=j) i += 1 if i == 6: i = 0 j = 1 self.eraser_button = Button(self.root, text="Borrador", bd=4, bg="white", command=self.eraser, width=8, relief=RIDGE) self.eraser_button.place(x=0, y=187) self.clear_button = Button(self.root, text="Limpiar", bd=4, bg="white", command=lambda: self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=217) self.save_button = Button(self.root, text="Guardar", bd=4, bg="white", command=self.save_paint, width=8, relief=RIDGE) self.save_button.place(x=0, y=247) self.canvas_color_button = Button(self.root, text="Lienzo", bd=4, bg="white", command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=277) # creating a scale for pen and araser size.. self.pen_size_scale_frame = LabelFrame(self.root, text="size", bd=5, bg="white", font=('arial', 15, 'bold'), relief=RIDGE) self.pen_size_scale_frame.place(x=0, y=310, height=200, width=70) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length=170) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) # creating canvas self.canvas = Canvas(self.root, bg='white', bd=5, relief=GROOVE, height=500, width=700) self.canvas.place(x=80, y=0) # bind the canvas with mouse drag self.canvas.bind("<B1-Motion>", self.paint) # funtions are defined here def paint(self, event): #print("mouse es dragged") x1, y1 = (event.x - 2), (event.y - 2) x2, y2 = (event.x + 2), (event.y + 2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): self.pen_color = col def eraser(self): self.pen_color = self.eraser_color def canvas_color(self): color = colorchooser.askcolor() self.canvas.config(background=color[1]) self.eraser_color = color[1] def save_paint(self): try: filename = filedialog.asksaveasfilename(defaultextension=".jpg") print(filename) x = self.root.winfo_rootx() + self.canvas.winfo_x() print(x, self.canvas.winfo_x()) y = self.root.winfo_rooty() + self.canvas.winfo_y() print(y) x1 = x + self.canvas.winfo_width() print(x1) y1 = y + self.canvas.winfo_height() print(y1) ImageGrab.grab().crop((x, y, x1, y1)).save(filename) messagebox.showinfo('paint says', 'image is saved as' + str(filename)) except: print("Not saved somo thing want wrong")
class Paint(): DEFAULT_PEN_SIZE = 5.0 DEFAULT_COLOR = 'black' def __init__(self): self.root = Tk() self.root.geometry('1000x800') #adding widgets self.color_frame = LabelFrame(self.root, text='Color', font=('arial', 15), bd=5, relief=RIDGE, bg="white") #bd is borderwidth self.color_frame.place(x = 0, y =0, width=82, height= 185) colors = ["white", "black", "red", "green", "blue", "cyan", "yellow", "magenta", 'pale violet red', 'maroon', 'turquoise1', 'purple2'] i = 0 j = 0 #i for row and j for column for color in colors: Button(self.color_frame, bg = color, bd=2, relief=RIDGE, width=1, command=lambda col=color:self.select_color(col)).grid(row = i, column = j) i = i + 1 if(i == 6): i = 0 j = 1 #eraser button image = Image.open("eraser.png") image = image.resize((40, 40)) self.photo_image_eraser = ImageTk.PhotoImage(image) self.eraser_button = Button(self.root, image = self.photo_image_eraser, command = self.use_eraser, relief= RIDGE) self.eraser_button.place(x = 0, y = 187) #pen button image = Image.open("pen.jpeg") image = image.resize((40, 40)) self.photo_image_pen = ImageTk.PhotoImage(image) self.pen_button = Button( self.root, image=self.photo_image_pen, command=self.use_pen, relief=RIDGE) self.pen_button.place(x = 43, y = 187) #clear button self.clear_button = Button(self.root, text="CLEAR", bd = 4, bg='white', command = lambda:self.c.delete("all"), width = 8, relief=RIDGE) self.clear_button.place(x = 0, y = 225) #save button self.save_button = Button( self.root, text="SAVE", bd=4, bg='white', command = self.save, width=8, relief=RIDGE) self.save_button.place(x=0, y= 255) self.canvas_color_button = Button( self.root, text="Canvas", bd=4, bg='white', command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=285) #creating a scale for pen and eraser size self.pen_size_scale_frame = LabelFrame(self.root, text="SIZE",bd = 5, bg="white", font=('arial', 15, 'bold'), relief=RIDGE) self.pen_size_scale_frame.place(x = 0, y = 318, height = 200, width = 85) self.pen_size = Scale(self.pen_size_scale_frame, orient=VERTICAL, from_=50, to=0, length = 170) #setting the default value self.pen_size.set(1) self.pen_size.grid(row = 0 , column = 1, padx = 15) #Circle button image = Image.open('circle.jpg') image = image.resize((40, 40)) self.photo_image_circle = ImageTk.PhotoImage(image) self.circle_button = Button( self.root, image=self.photo_image_circle, command=self.draw_circle, relief=RIDGE) self.circle_button.place(x = 0, y = 518) #FILLED_CIRCLE image = Image.open('filled_circle.png') image = image.resize((40, 40)) self.photo_image_circle_filled = ImageTk.PhotoImage(image) self.circle_filled_button = Button( self.root, image=self.photo_image_circle_filled, command=self.draw_circle_filled, relief=RIDGE) self.circle_filled_button.place(x = 43, y = 518) #Rectangle image = Image.open("rectangle.png") image = image.resize((40, 40)) self.photo_image_rectangle = ImageTk.PhotoImage(image) self.rectangle_button = Button( self.root, image=self.photo_image_rectangle, command=self.draw_rect, relief=RIDGE) self.rectangle_button.place(x = 0, y = 564) #Filled Rectangle image = Image.open("filled_rectangle.png") image = image.resize((40, 40)) self.photo_image_rectangle_filled = ImageTk.PhotoImage(image) self.rectangle_filled_button = Button( self.root, image=self.photo_image_rectangle_filled, command=self.draw_rect_filled, relief=RIDGE) self.rectangle_filled_button.place(x = 43, y = 564) #Arc image = Image.open("arc.png") image = image.resize((40, 40)) self.photo_image_arc = ImageTk.PhotoImage(image) self.arc_button = Button( self.root, image=self.photo_image_arc, command=self.draw_arc, relief=RIDGE) self.arc_button.place(x = 0 , y = 610) #Filled arc image = Image.open("filled_arc.png") image = image.resize((40, 40)) self.photo_arc_circle_filled = ImageTk.PhotoImage(image) self.arc_filled_button = Button( self.root, image=self.photo_arc_circle_filled, command=self.draw_arc_filled, relief=RIDGE) self.arc_filled_button.place(x = 43, y = 610) #line image = Image.open("line.png") image = image.resize((40, 40)) self.photo_image_line = ImageTk.PhotoImage(image) self.line_button = Button( self.root, image=self.photo_image_line, command=self.draw_line, relief=RIDGE) self.line_button.place(x = 0, y = 656) #dashed_line image = Image.open("dashed_line.png") image = image.resize((40, 40)) self.photo_image_dashed_line = ImageTk.PhotoImage(image) self.dashed_line_button = Button( self.root, image=self.photo_image_dashed_line, command=self.draw_dashed_line, relief=RIDGE) self.dashed_line_button.place(x = 43, y = 656) #creating canvas self.c = Canvas(self.root, bg = "white", bd = 5, height=500, width = 700) self.c.place(x = 90, y = 0) self.drawn = None self.kinds = [self.c.create_oval, self.c.create_rectangle, self.c.create_arc, self.c.create_line] self.setup() self.eraser_color = 'white' self.root.mainloop() def setup(self): self.old_x = None self.old_y = None self.line_width = self.pen_size.get() self.color = self.DEFAULT_COLOR self.eraser_on = False #self.active_button = self.pen_button def use_pen(self): self.activate_button(self.pen_button) self.c.bind('<B1-Motion>', self.paint) self.c.bind('<ButtonRelease-1>', self.reset) def use_eraser(self): self.activate_button(self.eraser_button, eraser_mode=True) self.c.bind('<B1-Motion>', self.paint) self.c.bind('<ButtonRelease-1>', self.reset) def activate_button(self, some_button, eraser_mode=False): #self.active_button.config(relief=RAISED) #some_button.config(relief=SUNKEN) self.active_button = some_button self.eraser_on = eraser_mode def draw_circle(self): self.activate_button(self.circle_button) self.c.bind('<ButtonPress-1>', self.on_start_circle) self.c.bind('<B1-Motion>', self.on_grow_shapes) def on_start_circle(self, event): self.shape = self.kinds[0] self.start = event self.drawn = None def draw_circle_filled(self): self.activate_button(self.circle_filled_button) self.c.bind('<ButtonPress-1>', self.on_start_circle_filled) self.c.bind('<B1-Motion>', self.on_grow_shapes_filled) def on_start_circle_filled(self, event): self.shape = self.kinds[0] self.start = event self.drawn = None def draw_rect(self): self.activate_button(self.rectangle_button) self.c.bind('<ButtonPress-1>', self.on_start_rect) self.c.bind('<B1-Motion>', self.on_grow_shapes) def on_start_rect(self, event): self.shape = self.kinds[1] self.start = event self.drawn = None def draw_rect_filled(self): self.activate_button(self.rectangle_filled_button) self.c.bind('<ButtonPress-1>', self.on_start_rect_filled) self.c.bind('<B1-Motion>', self.on_grow_shapes_filled) def on_start_rect_filled(self, event): self.shape = self.kinds[1] self.start = event self.drawn = None def draw_arc(self): self.activate_button(self.arc_button) self.c.bind('<ButtonPress-1>', self.on_start_arc) self.c.bind('<B1-Motion>', self.on_grow_shapes) def on_start_arc(self, event): self.shape = self.kinds[2] self.start = event self.drawn = None def draw_arc_filled(self): self.activate_button(self.arc_filled_button) self.c.bind('<ButtonPress-1>', self.on_start_arc_filled) self.c.bind('<B1-Motion>', self.on_grow_shapes_filled) def on_start_arc_filled(self, event): self.shape = self.kinds[2] self.start = event self.drawn = None def on_grow_shapes(self, event): self.line_width = self.pen_size.get() c = event.widget if self.drawn: c.delete(self.drawn) objectId = self.shape(self.start.x, self.start.y, event.x, event.y, outline=self.color, width=self.line_width) if trace: print(objectId) self.drawn = objectId def on_grow_shapes_filled(self, event): c = event.widget if self.drawn: c.delete(self.drawn) objectId = self.shape(self.start.x, self.start.y, event.x, event.y, outline=self.color, fill=self.color) if trace: print(objectId) self.drawn = objectId def draw_line(self): self.activate_button(self.line_button) self.c.bind('<ButtonPress-1>', self.on_start_line) self.c.bind('<B1-Motion>', self.on_grow_line) def on_start_line(self, event): self.shape = self.kinds[3] self.start = event self.drawn = None def on_grow_line(self, event): self.line_width = self.pen_size.get() c = event.widget if self.drawn: c.delete(self.drawn) objectId = self.shape(self.start.x, self.start.y, event.x, event.y, fill=self.color, width=self.line_width) if trace: print(objectId) self.drawn = objectId def draw_dashed_line(self): self.activate_button(self.dashed_line_button) self.c.bind('<ButtonPress-1>', self.on_start_dashed_line) self.c.bind('<B1-Motion>', self.on_grow_dashed_line) def on_start_dashed_line(self, event): self.shape = self.kinds[3] self.start = event self.drawn = None def on_grow_dashed_line(self, event): self.line_width = self.pen_size.get() c = event.widget if self.drawn: c.delete(self.drawn) objectId = self.shape(self.start.x, self.start.y, event.x, event.y, fill=self.color, dash=(4, 2), width=self.line_width) if trace: print(objectId) self.drawn = objectId def paint(self, event): self.line_width = self.pen_size.get() paint_color = self.eraser_color if self.eraser_on else self.color if self.old_x and self.old_y: self.c.create_line(self.old_x, self.old_y, event.x, event.y, width=self.line_width, fill=paint_color, capstyle=ROUND, smooth=TRUE, splinesteps=36) self.old_x = event.x self.old_y = event.y def reset(self, event): self.old_x, self.old_y = None, None def select_color(self, col): self.color = col def canvas_color(self): color = askcolor() #returns a tuple (rgbvalue, hexadecimal value) #we are using hexadecimal value self.c.configure(background = color[1]) self.eraser_color = color[1] def save(self): try: filename = filedialog.asksaveasfilename(defaultextension=".jpg") x = self.root.winfo_rootx() + self.c.winfo_x() y = self.root.winfo_rooty() + self.c.winfo_y() x1 = x + self.c.winfo_width() y1 = y + self.c.winfo_height() im = ImageGrab.grab(bbox = (x, y, x1, y1)) #print(str(filename)) im.save(str(filename)) #messagebox.showinfo("Image is saved as", str(filename)) except: pass
class paint(object): DEFAULT_PEN_SIZE = 10.0 def __init__(self): self.root= Tk() self.root.title("My Paint") self.root.geometry("800x500") self.size=Canvas(self.root, width=800, height=500) self.root.configure(bg="white") self.pen_color="black" self.eraser_color="white" self.color_frame=LabelFrame(self.root, text="Color", font=('arial', 15, 'bold'), bd=5, relief=RIDGE, bg="#6FA5F5") self.color_frame.place(x=10, y=400, width=240, height=90) colors=['white', 'black', 'brown','red', 'orange','yellow','green', 'blue', '#3E1C91', '#F20A85'] i=j=0 for color in colors: #col is value of color Button(self.color_frame, bg=color, bd=2, relief=RIDGE, width=5, command=lambda col= color: self.select_color(col)).grid(row=i, column=j) j+=1 if j==5: j=0 i=1 self.edit_color_button=Button(self.root, text="Edit Color",font=('arial', 11, 'bold'), bd=3, bg="#6FA5F5", command=self.edit_color, width=12,height=2, relief=RIDGE) self.edit_color_button.place(x=255, y=400) self.eraser_button=Button(self.root, text="Eraser",font=('arial', 11, 'bold'), bd=3, bg="#6FA5F5", command=self.eraser, width=12,height=2, relief=RIDGE) self.eraser_button.place(x=255, y=445) self.clear_button=Button(self.root, text="Clear",font=('arial', 11, 'bold'), bd=3, bg="#6FA5F5", command=lambda : self.canvas.delete("all"), width=12,height=2, relief=RIDGE) self.clear_button.place(x=355, y=400) self.save_button=Button(self.root, text="Save",font=('arial', 11, 'bold'), bd=3, bg="#6FA5F5", command=self.save_paint, width=12,height=2, relief=RIDGE) self.save_button.place(x=355, y=445) self.pen_size_scale_frame=LabelFrame(self.root, text="size", bd=5, bg="#6FA5F5", font=('areal',15,'bold'), relief=RIDGE) self.pen_size_scale_frame.place(x=480, y=400, height=70, width=250) self.pen_size=Scale(self.pen_size_scale_frame, orient=HORIZONTAL, from_=0, to=50, length=220) self.pen_size.set(1) self.pen_size.grid(row=0, column=1, padx=15) self.canvas=Canvas(self.root, bg='white', bd=5, relief=GROOVE, height=380, width=787) self.canvas.place(x=0, y=0) #self.setup() self.canvas.bind('<B1-Motion>', self.paint) self.root.mainloop() #dragging of mouse def paint(self, event): x1, y1=(event.x-2), (event.y-2) x2, y2=(event.x+2),(event.y+2) self.canvas.create_oval(x1, y1, x2, y2, fill=self.pen_color, outline=self.pen_color, width=self.pen_size.get()) def select_color(self, col): self.pen_color=col def eraser(self): self.pen_color=self.eraser_color def edit_color(self): color=colorchooser.askcolor() self.pen_color=color[1] def save_paint(self): try: #self.canvas.update() filename = filedialog.asksaveasfilename(defaultextension='.jpg') #print(filename) x = self.root.winfo_rootx() + self.canvas.winfo_x() #print(x, self.canvas.winfo_x()) y = self.root.winfo_rooty() + self.canvas.winfo_y() #print(y) x1 = x + self.canvas.winfo_width() #print(x1) y1 = y + self.canvas.winfo_height() #print(y1) ImageGrab.grab().crop(x, y, x1, y1).save(filename) messagebox.showinfo('paint says image is saved as ', + str(filename)) except: messagebox.showerror("paint says", "unable to save image, \n something went wrong")
class NotebookDemo: def __init__(self, fr): self.fr = fr self.style = Style() # ts.ThemedStyle() # Style() self._create_demo_panel() # run this before allBtns self.allBtns = self.ttkbut + self.cbs[1:] + self.rb try: piratz_theme.install('piratz') except Exception: import warnings warnings.warn("piratz theme being used without images") def _create_demo_panel(self): demoPanel = Frame(self.fr, name="demo") demoPanel.pack(side='top', fill='both', expand='y') # create the notebook self.nb = nb = Notebook(demoPanel, name="nb") nb.bind("<<NotebookTabChanged>>", self._on_tab_changed) # extend bindings to top level window allowing # CTRL+TAB - cycles thru tabs # SHIFT+CTRL+TAB - previous tab # ALT+K - select tab using mnemonic (K = underlined letter) nb.enable_traversal() nb.pack(fill='both', expand='y', padx=2, pady=3) self._create_descrip_tab(nb) self._create_treeview_tab(nb) self._create_text_tab(nb) def _create_descrip_tab(self, nb): # frame to hold contents frame = Frame(nb, name='descrip') # widgets to be displayed on 'Description' tab # position and set resize behaviour frame.rowconfigure(1, weight=1) frame.columnconfigure((0, 1), weight=1, uniform=1) lf = LabelFrame(frame, text='Animals') lf.pack(pady=5, padx=5, side='left', fill='y') themes = ['horse', 'elephant', 'crocodile', 'bat', 'grouse'] self.ttkbut = [] for t in themes: b = Button(lf, text=t) b.pack(pady=2) self.ttkbut.append(b) lF2 = LabelFrame(frame, text="Theme Combobox") lF2.pack(pady=5, padx=5) themes = list(sorted( self.style.theme_names())) # get_themes # used in ttkthemes themes.insert(0, "Pick a theme") self.cb = cb = Combobox(lF2, values=themes, state="readonly", height=10) cb.set(themes[0]) #cb.bind('<<ComboboxSelected>>', self.change_style) cb.grid(row=0, column=0, sticky='nw', pady=5) lf1 = LabelFrame(frame, text='Checkbuttons') lf1.pack(pady=5, padx=5, side='left', fill='y') # control variables self.enabled = IntVar() self.cheese = IntVar() self.tomato = IntVar() self.basil = IntVar() self.oregano = IntVar() # checkbuttons self.cbOpt = Checkbutton(lf1, text='Enabled', variable=self.enabled, command=self._toggle_opt) cbCheese = Checkbutton(text='Cheese', variable=self.cheese, command=self._show_vars) cbTomato = Checkbutton(text='Tomato', variable=self.tomato, command=self._show_vars) sep1 = Separator(orient='h') cbBasil = Checkbutton(text='Basil', variable=self.basil, command=self._show_vars) cbOregano = Checkbutton(text='Oregano', variable=self.oregano, command=self._show_vars) sep2 = Separator(orient='h') self.cbs = [ self.cbOpt, sep1, cbCheese, cbTomato, sep2, cbBasil, cbOregano ] for opt in self.cbs: if opt.winfo_class() == 'TCheckbutton': opt.configure(onvalue=1, offvalue=0) opt.setvar(opt.cget('variable'), 0) opt.pack(in_=lf1, side='top', fill='x', pady=2, padx=5, anchor='nw') lf2 = LabelFrame(frame, text='Radiobuttons', labelanchor='n') lf2.pack(pady=5, padx=5, side='left', fill='y') self.rb = [] self.happiness = StringVar() for s in ['Great', 'Good', 'OK', 'Poor', 'Awful']: b = Radiobutton(lf2, text=s, value=s, variable=self.happiness, command=lambda s=s: self._show_vars()) b.pack(anchor='nw', side='top', fill='x', pady=5, padx=5) self.rb.append(b) right = LabelFrame(frame, text='Control Variables') right.pack(pady=5, padx=5, side='left', fill='y') self.vb0 = Label(right, font=('Courier', 10)) self.vb1 = Label(right, font=('Courier', 10)) self.vb2 = Label(right, font=('Courier', 10)) self.vb3 = Label(right, font=('Courier', 10)) self.vb4 = Label(right, font=('Courier', 10)) self.vb5 = Label(right, font=('Courier', 10)) self.vb0.pack(anchor='nw', pady=5, padx=5) self.vb1.pack(anchor='nw', pady=5, padx=5) self.vb2.pack(anchor='nw', pady=5, padx=5) self.vb3.pack(anchor='nw', pady=5, padx=5) self.vb4.pack(anchor='nw', pady=5, padx=5) self.vb5.pack(anchor='nw', pady=5, padx=5) self._show_vars() # add to notebook (underline = index for short-cut character) nb.add(frame, text='Description', underline=0, padding=2) # ============================================================================= def _create_treeview_tab(self, nb): # Populate the second pane. Note that the content doesn't really matter tree = None self.backg = ["white", '#f0f0ff'] tree_columns = ("country", "capital", "currency") tree_data = [("Argentina", "Buenos Aires", "ARS"), ("Australia", "Canberra", "AUD"), ("Brazil", "Brazilia", "BRL"), ("Canada", "Ottawa", "CAD"), ("China", "Beijing", "CNY"), ("France", "Paris", "EUR"), ("Germany", "Berlin", "EUR"), ("India", "New Delhi", "INR"), ("Italy", "Rome", "EUR"), ("Japan", "Tokyo", "JPY"), ("Mexico", "Mexico City", "MXN"), ("Russia", "Moscow", "RUB"), ("South Africa", "Pretoria", "ZAR"), ("United Kingdom", "London", "GBP"), ("United States", "Washington, D.C.", "USD")] container = Frame(nb) container.pack(fill='both', expand=False) self.tree = Treeview(container, columns=tree_columns, show="headings") vsb = Scrollbar(container, orient="vertical", command=self.tree.yview) hsb = Scrollbar(container, orient="horizontal", command=self.tree.xview) self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set) self.tree.grid(column=0, row=0, sticky='ns', in_=container) vsb.grid(column=1, row=0, sticky='ns', in_=container) hsb.grid(column=0, row=1, sticky='ew', in_=container) container.grid_columnconfigure(0, weight=1) container.grid_rowconfigure(0, weight=1) for col in tree_columns: self.tree.heading( col, text=col.title(), command=lambda c=col: self.sortby(self.tree, c, 0)) # XXX tkFont.Font().measure expected args are incorrect according # to the Tk docs self.tree.column(col, width=Font().measure(col.title()), stretch=False) for ix, item in enumerate(tree_data): itemID = self.tree.insert('', 'end', values=item) self.tree.item(itemID, tags=itemID) self.tree.tag_configure(itemID, background=self.backg[ix % 2]) # adjust columns lengths if necessary for indx, val in enumerate(item): ilen = Font().measure(val) if self.tree.column(tree_columns[indx], width=None) < ilen: self.tree.column(tree_columns[indx], width=ilen) sg = Sizegrip(container) sg.grid(sticky='e') nb.add(container, text='Treeview', underline=0, padding=2) # ============================================================================= def _create_text_tab(self, nb): self.dir0 = 1 self.dir1 = 1 # populate the third frame with other widgets fr = Frame(nb, name='fr') lF = LabelFrame(fr, text="Slider") fr1 = Frame(lF) fr1.grid(row=0, column=0, sticky='nsew') from_ = 100 to = 0 value = 0 step = 10 fontSize = 9 self.scvar = IntVar() scRange = self.any_number_range(from_, to, step) scLen = len(scRange[1]) * (fontSize + 10) self.sc = Scale(fr1, from_=from_, to=to, variable=self.scvar, orient='vertical', length=scLen, command=self.v_scale) self.sc.set(value) l1 = Label(fr1, textvariable=self.scvar, width=5) l1.grid(row=0, column=0, padx=5, pady=5) self.sc.grid(row=0, column=1, padx=5, pady=5) fr4 = Frame(fr1) fr4.grid(row=0, column=2) sc_split = '\n'.join(scRange[0].split()) lb = Label(fr1, text=sc_split, font=('Courier New', str(fontSize))) lb.grid(row=0, column=2, padx=5, pady=5) fr2 = Frame(lF, name='fr2') fr2.grid(row=0, column=1, sticky='nsew') self.schvar = IntVar() a = 0 b = 100 schRange = self.any_number_range(a, b, s=10) schLen = Font().measure(schRange[0]) self.sch = Scale(fr2, from_=a, to=b, length=schLen, variable=self.schvar, orient='horizontal', command=self.h_scale) self.sch.set(0) l2 = Label(fr2, textvariable=self.schvar) l2.grid(row=1, column=1, pady=2) self.sch.grid(row=2, column=1, padx=5, pady=5, sticky='nsew') l3 = Label(fr2, text=schRange[0], font=('Courier New', str(fontSize))) l3.grid(row=3, column=1, padx=5, pady=5) lF.grid(row=0, column=0, sticky='nesw', pady=5, padx=5) lF1 = LabelFrame(fr, text="Progress", name='lf') pb1var = IntVar() pb2var = IntVar() self.pbar = Progressbar(lF1, variable=pb1var, length=150, mode="indeterminate", name='pb1', orient='horizontal') self.pb2 = Progressbar(lF1, variable=pb2var, length=150, mode='indeterminate', name='pb2', orient='vertical') self.pbar["value"] = 25 self.h_progress() self.v_progress() self.pbar.grid(row=1, column=0, padx=5, pady=5, sticky='nw') self.pb2.grid(row=1, column=1, padx=5, pady=5, sticky='nw') l3 = Label(lF1, textvariable=pb1var) l3.grid(row=0, column=0, pady=2, sticky='nw') l4 = Label(lF1, textvariable=pb2var) l4.grid(row=0, column=1, pady=2, sticky='nw') sg1 = Sizegrip(fr) sg1.grid(row=2, column=2, sticky='e') lF1.grid(row=1, column=0, sticky='nesw', pady=5, padx=5) # add to notebook (underline = index for short-cut character) nb.add(fr, text='Sliders & Others', underline=0) #========================================================================= def _toggle_opt(self): # state of the option buttons controlled # by the state of the Option frame label widget for opt in self.allBtns: if opt.winfo_class() != 'TSeparator': if self.cbOpt.instate(('selected', )): opt['state'] = '!disabled' # enable option self.nb.tab(1, state='normal') else: opt['state'] = 'disabled' self.nb.tab(1, state='disabled') self._show_vars() def _show_vars(self): # set text for labels in var_panel to include the control # variable name and current variable value self.vb0['text'] = '{:<11} {:<8}'.format('enabled:', self.enabled.get()) self.vb1['text'] = '{:<11} {:<8}'.format('cheese:', self.cheese.get()) self.vb2['text'] = '{:<11} {:<8}'.format('tomato:', self.tomato.get()) self.vb3['text'] = '{:<11} {:<8}'.format('basil:', self.basil.get()) self.vb4['text'] = '{:<11} {:<8}'.format('oregano:', self.oregano.get()) self.vb5['text'] = '{:<11} {:<8}'.format('happiness:', self.happiness.get()) def sortby(self, tree, col, descending): """Sort tree contents when a column is clicked on.""" # grab values to sort data = [(tree.set(child, col), child) for child in tree.get_children('')] # reorder data data.sort(reverse=descending) for indx, item in enumerate(data): tree.move(item[1], '', indx) # switch the heading so that it will sort in the opposite direction tree.heading(col, command=lambda col=col: self.sortby( tree, col, int(not descending))) # reconfigure tags after ordering list_of_items = tree.get_children('') for i in range(len(list_of_items)): tree.tag_configure(list_of_items[i], background=self.backg[i % 2]) def any_number_range(self, a, b, s=1): """ Generate consecutive values list between two numbers with optional step (default=1).""" if (a == b): return a else: mx = max(a, b) mn = min(a, b) result = [] output = '' # inclusive upper limit. If not needed, delete '+1' in the line below while (mn < mx + 1): # if step is positive we go from min to max if s > 0: result.append(mn) mn += s # if step is negative we go from max to min if s < 0: result.append(mx) mx += s # val maxLen = 0 output = "" for ix, res in enumerate(result[:-1]): # last value ignored if len(str(res)) > maxLen: maxLen = len(str(res)) if maxLen == 1: output = ' '.join(str(i) for i in result) # converts list to string else: for ix, res in enumerate(result): if maxLen == 2: if len(str(res)) == 1: output = output + str(res) + " " * maxLen elif len(str(res)) == 2: output = output + str(res) + " " else: output = output + str(res) #print(output) return output, result def change_style(self, event=None): """set the Style to the content of the Combobox""" content = self.cb.get() try: self.style.theme_use(content) except TclError as err: messagebox.showerror('Error', err) else: root.title(content) def change_theme(self, theme): window = ttktheme.ThemedTk() window.set_theme(theme) root.title(theme) def _on_tab_changed(self, event): event.widget.update_idletasks() tab = event.widget.nametowidget(event.widget.select()) event.widget.configure(height=tab.winfo_reqheight(), width=tab.winfo_reqwidth()) def h_progress(self): widg = self.pbar widg['value'] += 1 * self.dir0 if widg['value'] == 100: widg.state(['background', '!active']) self.dir0 = -1 widg.after(50, self.h_progress) elif widg['value'] == 0: widg.state(['active', '!background']) self.dir0 = 1 widg.after(50, self.h_progress) else: widg.after(50, self.h_progress) def v_progress(self): widg1 = self.pb2 widg1['value'] += 1 * self.dir1 if widg1['value'] == 0: # (dir1-1)*100+16 widg1.state(['active', '!invalid', '!background']) self.dir1 = 1 widg1.after(40, self.v_progress) elif widg1['value'] == 16: # (dir1-1)*100+16 widg1.state(['background', '!invalid', '!active']) widg1.after(40, self.v_progress) elif widg1['value'] == 33: widg1.state(['invalid', '!background', '!active']) widg1.after(40, self.v_progress) elif widg1['value'] == 50: widg1.state(['active', '!invalid', '!background']) widg1.after(40, self.v_progress) elif widg1['value'] == 66: widg1.state(['background', '!invalid', '!active']) widg1.after(40, self.v_progress) elif widg1['value'] == 83: widg1.state(['invalid', '!background', '!active']) widg1.after(40, self.v_progress) elif widg1['value'] == 100: widg1.state(['active', '!invalid', '!background']) self.dir1 = -1 widg1.after(40, self.v_progress) else: widg1.after(40, self.v_progress) def h_scale(self, schvar): v = int(float(schvar)) widg = self.sch imgw = { 0: ['readonly', '!selected', '!background', '!focus', '!active'], 1: ['selected', '!readonly', '!background', '!focus', '!active'] } if v >= 0 and v < 10: widg.state(['active', '!readonly', '!selected']) elif v > 80 and v < 91: widg.state(['focus', '!background', '!readonly', '!selected']) elif v > 90 and v < 100: widg.state(['background', '!invalid', '!focus']) elif v == 100: widg.state(['invalid', '!background']) else: widg.state(imgw[v % 2]) def v_scale(self, scvar): v = int(float(scvar)) widg1 = self.sc imgw = { 0: ['background', '!selected', '!invalid', '!active'], 1: ['selected', '!invalid', '!background', '!active'] } if v >= 0 and v < 5: widg1.state(['active', '!background', '!selected']) elif v > 90: widg1.state(['invalid', '!selected', '!background']) else: widg1.state(imgw[v % 2])
class Paint(): def __init__(self, root): self.root = root self.root.title("paint") self.root.geometry("800x520") self.root.configure(background="white") self.root.resizable(0,0) self.pen_color = "black" self.eraser_color = "white" #adding widges to paint self.color_frame = LabelFrame(self.root,text='Color',font = ('Times New Roman',15),bd=5,relief=RIDGE,bg="white") self.color_frame.place(x=0,y=0,width=70,height=195) colors = ['red','black','pink','blue','grey','cyan','brown','yellow','purple','hotpink','green','olive','plum','indigo'] i=j=0 for color in colors: Button(self.color_frame,bg=color,bd=1,relief=RIDGE,width=3,command=lambda col =color:self.select_color(col)).grid(row=i,column=j) i+=1 if i==7: i=0 j+=1 self.eraser_button = Button(self.root,text="ERASER",bd=4,bg="white",command=self.eraser,width=8,relief=RIDGE) self.eraser_button.place(x=0,y=192) self.clear_button = Button(self.root, text="CLEAR", bd=4, bg="white", command=lambda : self.canvas.delete("all"), width=8, relief=RIDGE) self.clear_button.place(x=0, y=222) self.save_button = Button(self.root, text="SAVE", bd=4, bg="white", command=None, width=8, relief=RIDGE) self.save_button.place(x=0, y=252) self.canvas_color_button = Button(self.root, text="FILL", bd=4, bg="white", command=self.canvas_color, width=8, relief=RIDGE) self.canvas_color_button.place(x=0, y=282) #creating a Scale for pen and Eraser Size self.pen_size_scale_frame = LabelFrame(self.root,text="size",bd=5,bg="white",font=('Times New Roman',15,'bold'),relief=RIDGE) self.pen_size_scale_frame.place(x=0,y=313,height=200,width=70) self.pen_size = Scale(self.pen_size_scale_frame,orient=VERTICAL,from_=50,to=0,length=170) self.pen_size.set(1) self.pen_size.grid(row=0,column=1,padx=15) #creating canvas self.canvas = Canvas(self.root,bg="white",bd=5,relief=GROOVE,height=500,width=700) self.canvas.place(x=80,y=0) #bind canvas with mouse drag self.canvas.bind("<B1-Motion>",self.paint) #functions def paint(self,event): x1,y1 = (event.x-2),(event.y-2) x2, y2 = (event.x + 2), (event.y + 2) self.canvas.create_oval(x1,y1,x2,y2,fill=self.pen_color,outline=self.pen_color,width=self.pen_size.get()) def select_color(self, col): self.pen_color = col def eraser(self): self.pen_color = self.eraser_color def canvas_color(self): color = colorchooser.askcolor() self.canvas.configure(background=color[1]) self.eraser_color = color[1]
class Mplay(Frame): """Music player made with tkinter and pygame / mutagen Usage: app = Mplay(master: tk.Tk, *, title: str=, width: int=, height=)""" master: Frame # shut up mypy def __init__(self, parent: Union[Tk, tk.ThemedTk] = None, *, title: str = "Music Player", width: int = 600, height: int = 400, ) -> None: super().__init__(parent) # call ttk.Frame constructor mixer.init() # initializethe pygame mixer self.assets_path: str = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets') if parent is not None: self.parent = parent else: self.parent = self.master self.parent.geometry(f'{width}x{height}') self.parent.title(title) self.parent.minsize(width // 2, height // 2) self.parent.iconbitmap(self.assets_path + '/icons/melody.ico') self.parent.protocol("WM_DELETE_WINDOW", self.on_closing) self.init_vol: int = 70 self.paused: bool = False self.muted: bool = False self.playing: bool = False self.current_song: Opt[str] = None self.selected_song_num: Opt[int] = None self.playlist: List[str] = [] self._init_ui() def _init_ui(self) -> None: self._menubar() self._statusbar() self._create_leftframe() self._create_rightframe() self._create_middleframe() self._create_bottomframe() def about_us(self) -> None: messagebox.showinfo('About Melody', 'This is a music player built using Python Tkinter by @meee') def browse_file(self) -> None: filename_path = filedialog.askopenfilename() if filename_path: self.add_to_playlist(filename_path) mixer.music.queue(filename_path) def add_to_playlist(self, filepath: str) -> None: filename = os.path.basename(filepath) index = 0 self.playlistbox.insert(index, filename) self.playlist.insert(index, filepath) index += 1 def _create_leftframe(self) -> None: self.leftframe = Frame(self.parent) self.leftframe.pack(side=LEFT, padx=30) self.playlistbox = Listbox(self.leftframe) self.playlistbox.pack() addBtn = Button(self.leftframe, text="+ Add", command=self.browse_file) addBtn.pack(side=LEFT) delBtn = Button(self.leftframe, text="- Del", command=self.del_song) delBtn.pack(side=LEFT) def _statusbar(self) -> None: self.statusbar = Label(self.parent, text="Welcome to Melody", relief=SUNKEN, anchor=W) self.statusbar.pack(side=BOTTOM, fill=X) def _menubar(self) -> None: menubar = Menu(self.parent) root.config(menu=menubar) # Create the submenu1 subMenu1 = Menu(menubar, tearoff=0) menubar.add_cascade(label="File", menu=subMenu1) subMenu1.add_command(label="Open", command=self.browse_file) subMenu1.add_command(label="Exit", command=root.destroy) # Create the submenu2 subMenu2 = Menu(menubar, tearoff=0) menubar.add_cascade(label="Help", menu=subMenu2) subMenu2.add_command(label="About Us", command=self.about_us) def del_song(self) -> None: self.get_selected_song_num() # update self.selected_song_num if self.selected_song_num is not None: # if a song is selected if self.playlist[self.selected_song_num] == self.current_song: # if song is currently playing self.stop_music() # stop it self.playlistbox.delete(self.selected_song_num) # delete the song from the box self.playlist.pop(self.selected_song_num) # and playlist # self.selected_song_num remains same, so will play/del next song? self.reset_song() self.selected_song_num = None # reset self.selected_song_num def _create_rightframe(self) -> None: self.rightframe = Frame(self.parent) self.rightframe.pack() self.filelabel = Label(self.rightframe, text='Lets make some noise!') self.filelabel.pack(pady=10) self.lengthlabel = Label(self.rightframe, text='Total Length : --:--') self.lengthlabel.pack() self.currenttimelabel = Label(self.rightframe, text='Current Time : --:--', relief=GROOVE) self.currenttimelabel.pack() def start_count(self, total_time: int) -> None: """.""" current_time = 0 while current_time <= total_time and mixer.music.get_busy(): # music.get_busy() -> Returns False when stopped if self.paused: continue # if paused, infinite loop (don't count) else: mins, secs = divmod(current_time, 60) mins = round(mins) secs = round(secs) timeformat = '{:02d}:{:02d}'.format(mins, secs) self.currenttimelabel['text'] = "Current Time" + ' - ' + timeformat time.sleep(1) current_time += 1 def reset_song(self) -> None: self.current_song = None self.filelabel['text'] = "" self.lengthlabel['text'] = 'Total Length : --:--' self.currenttimelabel['text'] = "Current Time : --:--" self.statusbar['text'] = "" def show_details(self, play_song: str) -> None: self.filelabel['text'] = "Playing" + ' - ' + os.path.basename(play_song) file_data = os.path.splitext(play_song) if file_data[1] == '.mp3': audio = MP3(play_song) total_length = audio.info.length elif file_data[1] == '.wav': a = mixer.Sound(play_song) total_length = a.get_length() else: try: a = mixer.Sound(play_song) total_length = a.get_length() except Exception as e: print(e, "not a supported file type? e.g. .wav, .mp3") mins, secs = divmod(total_length, 60) # returns (time//60, remainder) mins = round(mins) secs = round(secs) timeformat = '{:02d}:{:02d}'.format(mins, secs) self.lengthlabel['text'] = "Total Length" + ' - ' + timeformat t1 = threading.Thread(target=self.start_count, args=(total_length, )) t1.start() def pause_music(self) -> None: if self.playing: self.paused = True mixer.music.pause() self.statusbar['text'] = "Music Paused" def get_selected_song_num(self) -> None: try: selected_song_from_box: Tuple[int] = self.playlistbox.curselection() self.selected_song_num = int(selected_song_from_box[0]) except IndexError as e: # no files in the playlistbox tuple self.statusbar['text'] = "Choose a file from the playlist" if DEBUG: print(e) except Exception as e: messagebox.showerror('File not found, or unknown file type. Please check again.') if DEBUG: print(e) def play_music(self) -> None: """if not playing: play, if playing and paused, unpause""" self.get_selected_song_num() # update self.selected_song_num if self.selected_song_num is not None and self.playlist: play_it: Opt[str] = self.playlist[self.selected_song_num] else: play_it = None if not self.playing and play_it: # if not yet playing, play selected song try: self.stop_music() time.sleep(0.5) mixer.music.load(play_it) mixer.music.play() except Exception as e: messagebox.showerror('File not found, or unknown file type. Please check again.') if DEBUG: print(e) else: self.playing = True self.current_song = play_it self.show_details(play_it) self.statusbar['text'] = "Playing music" + ' - ' + os.path.basename(play_it) elif self.playing and self.paused: # if paused, resume mixer.music.unpause() self.statusbar['text'] = "Music Resumed" self.paused = False elif self.playing and not self.paused: if play_it == self.current_song and play_it is not None: # if already playing song, do nothing self.statusbar['text'] = "Playing music" + ' - ' + os.path.basename(play_it) else: # if different song selected, retry self.playing = False self.play_music() def stop_music(self) -> None: if self.playing: self.playing = False self.current_song = None mixer.music.stop() self.statusbar['text'] = "Music Stopped" def rewind_music(self) -> None: if self.playing: self.stop_music() time.sleep(0.5) self.play_music() self.statusbar['text'] = "Music Rewound to start" def set_vol(self, val: str) -> None: vol_float = float(val) volume = int(vol_float) / 100 mixer.music.set_volume(volume) # set_volume of mixer takes value only from 0 to 1 def mute_music(self) -> None: if self.muted: # Unmute the music mixer.music.set_volume(0.7) self.volumeBtn.configure(image=self.volumePhoto) self.scale.set(70) self.muted = False else: # mute the music mixer.music.set_volume(0) self.volumeBtn.configure(image=self.mutePhoto) self.scale.set(0) self.muted = True def _create_middleframe(self) -> None: self.middleframe = Frame(self.rightframe) self.middleframe.pack(pady=30, padx=30) self.playPhoto = PhotoImage(file=self.assets_path + '/icons/play.png') playBtn = Button(self.middleframe, image=self.playPhoto, command=self.play_music) playBtn.grid(row=0, column=1, padx=10) self.stopPhoto = PhotoImage(file=self.assets_path + '/icons/stop.png') stopBtn = Button(self.middleframe, image=self.stopPhoto, command=self.stop_music) stopBtn.grid(row=0, column=2, padx=10) self.pausePhoto = PhotoImage(file=self.assets_path + '/icons/pause.png') pauseBtn = Button(self.middleframe, image=self.pausePhoto, command=self.pause_music) pauseBtn.grid(row=0, column=3, padx=10) def _create_bottomframe(self) -> None: self.bottomframe = Frame(self.rightframe) self.bottomframe.pack() self.mutePhoto = PhotoImage(file=self.assets_path + '/icons/mute.png') self.volumePhoto = PhotoImage(file=self.assets_path + '/icons/volume.png') self.volumeBtn = Button(self.bottomframe, image=self.volumePhoto, command=self.mute_music) self.volumeBtn.grid(row=0, column=1) self.rewindPhoto = PhotoImage(file=self.assets_path + '/icons/rewind.png') rewindBtn = Button(self.bottomframe, image=self.rewindPhoto, command=self.rewind_music) rewindBtn.grid(row=0, column=0) self.scale = Scale(self.bottomframe, from_=0, to=100, orient=HORIZONTAL, command=self.set_vol) self.scale.set(self.init_vol) mixer.music.set_volume(self.init_vol / 100) self.scale.grid(row=0, column=2, pady=15, padx=30) def on_closing(self) -> None: try: self.stop_music() self.parent.destroy() except Exception as e: if DEBUG: print(e) else: print('App closed')