Skip to content

Instantly share code, notes, and snippets.

@mnemocron
Forked from nikhilkumarsingh/paint.py
Last active May 15, 2020 16:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnemocron/9825a5c2e1b4eae316c2b2ebd7e88ccb to your computer and use it in GitHub Desktop.
Save mnemocron/9825a5c2e1b4eae316c2b2ebd7e88ccb to your computer and use it in GitHub Desktop.
A simple paint application using tkinter in Python 3 to generate GCode for your 3D printer
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 29 12:09:09 2019
@author: simon
"""
from tkinter import *
from tkinter.colorchooser import askcolor
from pysvg import *
import serial
event_delay = 7
# size of the paint canvas on screen in px
canvas_x = 500
canvas_y = 500
# size of the printer bed in mm
printer_x = 200
printer_y = 200
stroke_speed = 5000
comport = 'COM8'
baudrate = 115200
z_pos_0 = 10 # when pen is down
z_pos_up = 15 # when pen is up
x_offset = 20.0 # pen to nozzle offset
y_offset = 40.0 # pen to nozzle offset
# python -m serial.tools.list_ports
class Paint(object):
DEFAULT_PEN_SIZE = 5.0
DEFAULT_COLOR = 'black'
def __init__(self):
self.root = Tk()
self.root.winfo_toplevel().title('Paint To 3DPrinter')
self.pen_button = Button(self.root, text='pen', command=self.use_pen)
self.pen_button.grid(row=0, column=0)
self.color_button = Button(self.root, text='color', command=self.choose_color)
self.color_button.grid(row=0, column=1)
self.eraser_button = Button(self.root, text='clear', command=self.clear_pane)
self.eraser_button.grid(row=0, column=2)
self.choose_size_button = Scale(self.root, from_=1, to=10, orient=HORIZONTAL)
self.choose_size_button.grid(row=0, column=3)
self.home_button = Button(self.root, text='home', command=self.home_axis)
self.home_button.grid(row=0, column=4)
self.c = Canvas(self.root, bg='white',
width=canvas_x,
height=canvas_y)
self.c.grid(row=1, columnspan=5)
self.console = Text(self.root, bg='black', fg='white', width=40)
self.console.grid(row=0, column=6, rowspan=2)
self.console.insert(0.0,'>>> G Code >')
self.console_line = 1.0
self.setup()
self.root.mainloop()
def setup(self):
self.old_x = None
self.old_y = None
self.line_width = self.choose_size_button.get()
self.color = self.DEFAULT_COLOR
self.eraser_on = False
self.active_button = self.pen_button
self.c.bind('<B1-Motion>', self.paint)
self.c.bind('<ButtonRelease-1>', self.reset_stroke)
self.c.bind('<Button-1>', self.begin_stroke)
self.old_gcode = ''
self.event_delay = 0
def use_pen(self):
self.activate_button(self.pen_button)
def choose_color(self):
self.eraser_on = False
self.color = askcolor(color=self.color)[1]
def clear_pane(self):
self.c.delete('all')
self.console.delete('1.0', END)
self.console.insert(0.0,'>>> G Code >')
self.console_line = 1.0
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 paint(self, event):
self.event_delay += 1
if self.event_delay < event_delay:
return
self.event_delay = 0
self.line_width = self.choose_size_button.get()
paint_color = self.color
if self.old_x and self.old_y:
x = event.x
y = event.y
if x < 0:
x = 0
if x > canvas_x:
x = canvas_x
if y < 0:
y = 0
if y > canvas_y:
y = canvas_y
self.c.create_line(self.old_x, self.old_y, x, y,
width=self.line_width, fill=paint_color,
capstyle=ROUND, smooth=TRUE, splinesteps=36)
gcode = ('G0 X' + str(round(x/canvas_x*printer_x, 3)+x_offset) +
' Y' + str(round(printer_y -
y/canvas_y*printer_y, 3)+y_offset) + ' F' + str(stroke_speed) + '\n')
# only print, when the distance is at least 1mm
if not (gcode in self.old_gcode):
self.print_gcode(gcode)
self.old_gcode = gcode
self.old_x = event.x
self.old_y = event.y
# place pen on paper
def begin_stroke(self, event):
gcode = ('G0 X' + str(int(event.x/canvas_x*printer_x + x_offset)) +
' Y' + str(int(printer_y -
event.y/canvas_y*printer_y) + y_offset) + ' \n')
self.print_gcode(gcode)
self.print_gcode('G0 Z' + str(z_pos_0) + '\n')
# remove pen from paper
def reset_stroke(self, event):
self.old_x, self.old_y = None, None
self.print_gcode('G0 Z' + str(z_pos_up) + '\n')
self.event_delay = 6
def home_axis(self):
self.print_gcode('G28\n')
self.print_gcode('G0 Z' + str(z_pos_up) + '\n')
def print_gcode(self, gcode):
self.console.insert(self.console_line, gcode)
self.console.yview_pickplace("end")
ser.write(bytes(gcode, 'utf-8'))
self.console_line += 1
if __name__ == '__main__':
try:
ser = serial.Serial(comport, baudrate) # open serial port
Paint()
finally:
ser.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment