Paint

Got a project near completion? Got a project with lots of screens and media? This is the place. This is for nearly finished and Projects with lots of media.
Post Reply
User avatar
Script47
Posts: 147
Joined: Thu Nov 21, 2013 6:11 pm

Paint

Post by Script47 »

Hello, I got soooo bored so I decided to make something, I thought I would make a Paint type thing. :)

http://script47.tk/Paint/
User avatar
a_bertrand
Posts: 1537
Joined: Mon Feb 25, 2013 1:46 pm

Re: Paint

Post by a_bertrand »

Not a bad start, but you could make the code a lot smaller, and not even use things like setInterval.
Creator of Dot World Maker
Mad programmer and annoying composer
User avatar
vitinho444
Posts: 2825
Joined: Mon Mar 21, 2011 4:54 pm

Re: Paint

Post by vitinho444 »

Very nice :D
My Company Website: http://www.oryzhon.com

Skype: vpegas1234
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: Paint

Post by Jackolantern »

Nice! This reminds me a lot of a project I did last semester while learning Python. We even used a lot of the same methods for drawing. You may want to check out my Python code. Even if you don't use Python, it should be pretty easy to follow (Python is extremely easy to read) :D

Code: Select all

'''
File: MyPaint.py
Description: A Paint-like program for drawing with a GUI.
Author: Tim Crouch
Date: Nov 13, 2013
'''


from tkinter import *
import tkinter.simpledialog as tksd
import tkinter.messagebox as tkmb
from tkinter import filedialog as tkfd

class PaintGui:

    def __init__(self):
        #create the main window
        window = Tk()
        window.title("MyPaint")

        #save the window reference
        self.window = window

        #Create the menu
        menubar = Menu(window)

        #Add the menu to the window
        window.config(menu = menubar)

        #Create memory object
        self.actionList = ActionList(self)

        #Create the shape drawers
        self.circleDrawer = CircleDrawer(self, self.actionList)
        self.squareDrawer = SquareDrawer(self, self.actionList)
        self.lineDrawer = LineDrawer(self, self.actionList)
        self.arcDrawer = ArcDrawer(self, self.actionList)
        self.freeDrawer = FreeDrawer(self, self.actionList)

        #Create the object for saving and opening files
        self.fileSaveOpen = FileSaveOpen(self.actionList, self.circleDrawer, self.squareDrawer, self.lineDrawer, self.arcDrawer)

        #give a reference to ActionList
        self.actionList.drawingObject(self.circleDrawer, self.squareDrawer, self.lineDrawer, self.arcDrawer, self.freeDrawer)

        #Create File sub-menu
        fileMenu = Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = "File", menu = fileMenu)
        fileMenu.add_command(label = "Save", command = self.saveFile)
        fileMenu.add_command(label = "Open", command = self.openFile)

        #Create shape sub-menu
        operationMenu = Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = "Shapes", menu = operationMenu)
        operationMenu.add_command(label = "Draw Circles", command = self.drawCircle)
        operationMenu.add_command(label = "Draw Squares", command = self.drawSquare)
        operationMenu.add_command(label = "Draw Lines", command = self.drawLine)
        operationMenu.add_command(label = "Draw Arcs", command = self.drawArc)
        operationMenu.add_command(label = "Free Draw", command = self.freeDraw)

        #default color is black
        self.color = "black"

        #set the mode; default is Circle
        self.shapeMode = "circle"

        #Create the color menu
        settingMenu = Menu(menubar, tearoff = 0)
        colorMenu = Menu(settingMenu, tearoff = 0)
        menubar.add_cascade(label = "Settings", menu = settingMenu)
        settingMenu.add_cascade(label = "Color", menu = colorMenu)
        colorMenu.add_command(label = "Black", command = self.setBlack)
        colorMenu.add_command(label = "Red", command = self.setRed)
        colorMenu.add_command(label = "Blue", command = self.setBlue)
        colorMenu.add_command(label = "Green", command = self.setGreen)
        colorMenu.add_command(label = "Yellow", command = self.setYellow)
        colorMenu.add_command(label = "Orange", command = self.setOrange)
        colorMenu.add_command(label = "Purple", command = self.setPurple)

        #Create the "change last color" menu
        lastColorMenu = Menu(settingMenu, tearoff = 0)
        settingMenu.add_cascade(label = "Last Color", menu = lastColorMenu)
        lastColorMenu.add_command(label = "Black", command = self.lastBlack)
        lastColorMenu.add_command(label = "Red", command = self.lastRed)
        lastColorMenu.add_command(label = "Blue", command = self.lastBlue)
        lastColorMenu.add_command(label = "Green", command = self.lastGreen)
        lastColorMenu.add_command(label = "Yellow", command = self.lastYellow)
        lastColorMenu.add_command(label = "Orange", command = self.lastOrange)
        lastColorMenu.add_command(label = "Purple", command = self.lastPurple)

        #Begin creating context-sensitive tool bars
        self.toolFrame = Frame(window)

        #Create the images for the toolbar menu
        self.circleImage = PhotoImage(file = "images/circle.gif")
        self.squareImage = PhotoImage(file = "images/square.gif")
        self.lineImage = PhotoImage(file = "images/line.gif")
        self.arcImage = PhotoImage(file = "images/arc.gif")
        self.drawImage = PhotoImage(file = "images/freedraw.gif")
        self.blackImage = PhotoImage(file = "images/black.gif")
        self.redImage = PhotoImage(file = "images/red.gif")
        self.blueImage = PhotoImage(file = "images/blue.gif")
        self.greenImage = PhotoImage(file = "images/green.gif")
        self.yellowImage = PhotoImage(file = "images/yellow.gif")
        self.orangeImage = PhotoImage(file = "images/orange.gif")
        self.purpleImage = PhotoImage(file = "images/purple.gif")

        #Create the controls for the tool bars
        circleButton = Button(self.toolFrame, image = self.circleImage, command = self.drawCircle)
        squareButton = Button(self.toolFrame, image = self.squareImage, command = self.drawSquare)
        lineButton = Button(self.toolFrame, image = self.lineImage, command = self.drawLine)
        arcButton = Button(self.toolFrame, image = self.arcImage, command = self.drawArc)
        drawButton = Button(self.toolFrame, image = self.drawImage, command = self.freeDraw)
        circleButton.grid(row = 1, column = 1)
        squareButton.grid(row = 1, column = 2)
        lineButton.grid(row = 1, column = 3)
        arcButton.grid(row = 1, column = 4)
        drawButton.grid(row = 1, column = 5)

        #Create the color buttons
        self.blackButton = Button(self.toolFrame, image = self.blackImage, command = self.setBlack)
        self.redButton = Button(self.toolFrame, image = self.redImage, command = self.setRed)
        self.blueButton = Button(self.toolFrame, image = self.blueImage, command = self.setBlue)
        self.greenButton = Button(self.toolFrame, image = self.greenImage, command = self.setGreen)
        self.yellowButton = Button(self.toolFrame, image = self.yellowImage, command = self.setYellow)
        self.orangeButton = Button(self.toolFrame, image = self.orangeImage, command = self.setOrange)
        self.purpleButton = Button(self.toolFrame, image = self.purpleImage, command = self.setPurple)
        self.blackButton.grid(row = 1, column = 12)
        self.redButton.grid(row = 1, column = 13)
        self.blueButton.grid(row = 1, column = 14)
        self.greenButton.grid(row = 1, column = 15)
        self.yellowButton.grid(row = 1, column = 16)
        self.orangeButton.grid(row = 1, column = 17)
        self.purpleButton.grid(row = 1, column = 18)


        #Create undo/redo buttons
        self.undoButton = Button(self.toolFrame, text = "Undo", command = self.actionList.undo)
        self.redoButton = Button(self.toolFrame, text = "Redo", command = self.actionList.redo)
        self.removeAllButton = Button(self.toolFrame, text = "Clear", command = self.actionList.removeAll)
        self.undoButton.grid(row = 1, column = 19)
        self.removeAllButton.grid(row = 1, column = 21)

        #create context-sensitive controls
        #Create width button
        self.widthLabel = Label(self.toolFrame, text = "Width: ")
        self.widthInput = StringVar()
        self.widthEntry = Entry(self.toolFrame, textvariable = self.widthInput, width = 3)
        self.widthButton = Button(self.toolFrame, text = "Set", command = self.setWidth)
        #create start button for arcs
        self.startLabel = Label(self.toolFrame, text = "Start: ")
        self.startInput = StringVar()
        self.startEntry = Entry(self.toolFrame, textvariable = self.startInput, width = 3)
        self.startButton = Button(self.toolFrame, text = "Set", command = self.setStart)
        #create extent button for arcs
        self.extentLabel = Label(self.toolFrame, text = "Extent: ")
        self.extentInput = StringVar()
        self.extentEntry = Entry(self.toolFrame, textvariable = self.extentInput, width = 3)
        self.extentButton = Button(self.toolFrame, text = "Set", comman = self.setExtent)

        self.toolFrame.pack(fill = X)

        #Create the canvas
        canvas = Canvas(window, width = 750, height = 500)
        canvas.pack()

        #Setup the events on canvas
        canvas.bind("<Button-1>", self.drawRoutine)
        canvas.bind("<B1-Motion>", self.midDraw)
        canvas.bind("<ButtonRelease-1>", self.endDraw)

        self.canvas = canvas

        #Start the main loop
        window.mainloop()

    def setStart(self):
        #send the start to the arc drawer
        if self.startInput.get():
            start = eval(self.startInput.get())
            self.arcDrawer.setStart(start)

    def setExtent(self):
        #send the extent to the arc drawer
        if self.extentInput.get():
            extent = eval(self.extentInput.get())
            self.arcDrawer.setExtent(extent)

    def setWidth(self):
        #check to see what mode we are in to send to correct class
        if self.shapeMode == "line":
            if self.widthInput.get():
                self.lineDrawer.setWidth(eval(self.widthInput.get()))

    #Set the shape modes
    def drawCircle(self):
        #remove other context controls
        self.removeContextControls()
        #set the mode to circle
        self.shapeMode = "circle"



    def drawSquare(self):
        #remove other mode's buttons
        self.removeContextControls()
        #set the mode to square
        self.shapeMode = "square"


    def drawLine(self):
        #remove other context controls
        self.removeContextControls()
        #set the mode to line
        self.shapeMode = "line"
        #add correct buttons
        self.widthLabel.grid(row = 1, column = 6)
        self.widthEntry.grid(row = 1, column = 7)
        self.widthButton.grid(row = 1, column = 8)

    def drawArc(self):
        #remove other buttons
        self.removeContextControls()
        #set the mode
        self.shapeMode = "arc"
        #now set the arc buttons
        self.startLabel.grid(row = 1, column = 6)
        self.startEntry.grid(row = 1, column = 7)
        self.startButton.grid(row = 1, column = 8)
        self.extentLabel.grid(row = 1, column = 9)
        self.extentEntry.grid(row = 1, column = 10)
        self.extentButton.grid(row = 1, column = 11)

    def freeDraw(self):
        #remove other buttons
        self.removeContextControls()
        #set the mode
        self.shapeMode = "free"

    #Set the drawing color
    def setPurple(self):
        self.color = "purple"

    def setBlack(self):
        self.color = "black"

    def setBlue(self):
        self.color = "blue"

    def setRed(self):
        self.color = "red"

    def setYellow(self):
        self.color = "yellow"

    def setOrange(self):
        self.color = "orange"

    def setGreen(self):
        self.color = "green"

    def lastBlack(self):
        self.actionList.undo()
        self.actionList.redo("black")

    #Methods for changing the color of the last object entered
    def lastRed(self):
        self.actionList.undo()
        self.actionList.redo("red")

    def lastBlue(self):
        self.actionList.undo()
        self.actionList.redo("blue")

    def lastGreen(self):
        self.actionList.undo()
        self.actionList.redo("green")

    def lastPurple(self):
        self.actionList.undo()
        self.actionList.redo("purple")

    def lastYellow(self):
        self.actionList.undo()
        self.actionList.redo("yellow")

    def lastOrange(self):
        self.actionList.undo()
        self.actionList.redo("orange")

    def removeContextControls(self):
        #remove other mode's buttons
        if self.shapeMode == 'arc':
            self.startLabel.grid_forget()
            self.startEntry.grid_forget()
            self.startButton.grid_forget()
            self.extentLabel.grid_forget()
            self.extentEntry.grid_forget()
            self.extentButton.grid_forget()
        if self.shapeMode == "line":
            self.widthLabel.grid_forget()
            self.widthEntry.grid_forget()
            self.widthButton.grid_forget()

    #the event handler to set the initial points for the objects
    def drawRoutine(self, event):
        if self.shapeMode == "circle":
            x1 = event.x
            y1 = event.y
            self.circleDrawer.setInitial(x1, y1)
        elif self.shapeMode == "square":
            x1 = event.x
            y1 = event.y
            self.squareDrawer.setInitial(x1, y1)
        elif self.shapeMode == "arc":
            x1 = event.x
            y1 = event.y
            self.arcDrawer.setInitial(x1, y1)
        elif self.shapeMode == "line":
            x1 = event.x
            y1 = event.y
            self.lineDrawer.setInitial(x1, y1)
        elif self.shapeMode == "free":
            #starting free draw, so make a first point
            self.freeDrawer.addPoint(event.x, event.y)


    #the event handler to draw the temp objects
    def midDraw(self, event):
        #remove the temp if exists
        self.canvas.delete("temp")

        if self.shapeMode == "circle":
            x2 = event.x
            y2 = event.y
            #now draw another temp circle
            self.circleDrawer.drawTempCircle(x2, y2)
        elif self.shapeMode == "square":
            x2 = event.x
            y2 = event.y
            #now draw another temp
            self.squareDrawer.drawTempSquare(x2, y2)
        elif self.shapeMode == "arc":
            x2 = event.x
            y2 = event.y
            #now draw another temp
            self.arcDrawer.drawTempArc(x2, y2)
        elif self.shapeMode == "line":
            x2 = event.x
            y2 = event.y
            #now draw another temp
            self.lineDrawer.drawTempLine(x2, y2)
        elif self.shapeMode == "free":
            #still free drawing, so make another point
            self.freeDrawer.addPoint(event.x, event.y)


    #the event handler for drawing the final objects
    def endDraw(self, event):
        #remove a temp if there is one
        self.canvas.delete("temp")

        if self.shapeMode == "circle":
            x2 = event.x
            y2 = event.y
            #now draw the final circle
            self.circleDrawer.drawCircle(x2, y2)
        elif self.shapeMode == "square":
            x2 = event.x
            y2 = event.y
            #now draw the final square
            self.squareDrawer.drawSquare(x2, y2)
        elif self.shapeMode == "arc":
            x2 = event.x
            y2 = event.y
            #now draw the final arc
            self.arcDrawer.drawArc(x2, y2)
        elif self.shapeMode == "line":
            x2 = event.x
            y2 = event.y
            #now draw the final line
            self.lineDrawer.drawLine(x2, y2)
        elif self.shapeMode == "free":
            self.freeDrawer.endFree()

    #save files
    def saveFile(self):
        #get the filename to save
        fileName = tksd.askstring("File Name", "Enter a name for the file")
        #make sure that the file extension is added if the user didn't enter it
        if fileName[-4:] != ".mpf":
            fileName += '.mpf'
        #open the file, creating it if needed
        with open(fileName, mode = 'w') as fileRef:
            self.fileSaveOpen.saveFile(fileRef)


    #open files
    def openFile(self):
        #get the filename to open
        fileName = tksd.askstring("File Name", "Enter a name for the file to open")
        #make sure that the file extension is added if the user didn't enter it
        if fileName[-4:] != ".mpf":
            fileName += '.mpf'
        #open the file
        with open(fileName, mode = 'r') as fileRef:
            self.fileSaveOpen.openFile(fileRef)


'''
The classes to handle drawing objects
'''
class CircleDrawer:

    def __init__(self, gui, memory):
        self.gui = gui
        #Counter to help keep track of drawing objects
        self.circleCounter = 0
        #attributes to set initial point
        self.__firstX = 0
        self.__firstY = 0
        self.__actionList = memory

    def setInitial(self, x, y):
        self.__firstX = x
        self.__firstY = y

    def drawTempCircle(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        self.gui.canvas.create_oval(coord, fill = self.gui.color, outline = self.gui.color, tags = "temp")

    def drawCircle(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        newTag = "circle" + str(self.circleCounter)
        self.gui.canvas.create_oval(coord, fill = self.gui.color, outline = self.gui.color, tags = newTag)
        self.circleCounter = self.circleCounter + 1
        #Add the object to memory
        self.__actionList.addCircle(self.gui.color, self.__firstX, self.__firstY, x2, y2, newTag)
        #remove the redo list
        self.__actionList.eraseRedo()

    def redoCircle(self, color, x1, y1, x2, y2, tag):
        coord = x1, y1, x2, y2
        self.gui.canvas.create_oval(coord, fill = color, outline = color, tags = tag)

class SquareDrawer:

    def __init__(self, gui, memory):
        self.gui = gui
        self.__firstX = 0
        self.__firstY = 0
        self.__actionList = memory
        #Counter to help keep track of drawing objects
        self.squareCounter = 0

    def setInitial(self, x, y):
        self.__firstX = x
        self.__firstY = y

    def drawTempSquare(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        self.gui.canvas.create_rectangle(coord, fill = self.gui.color, outline = self.gui.color, tags = "temp")

    def drawSquare(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        newTag = "square" + str(self.squareCounter)
        self.gui.canvas.create_rectangle(coord, fill = self.gui.color, outline = self.gui.color, tags = newTag)
        self.squareCounter = self.squareCounter + 1
        #Add the object to memory
        self.__actionList.addSquare(self.gui.color, self.__firstX, self.__firstY, x2, y2, newTag)
        #remove the redo list
        self.__actionList.eraseRedo()

    def redoSquare(self, color, x1, y1, x2, y2, tag):
        coord = x1, y1, x2, y2
        self.gui.canvas.create_rectangle(coord, fill = color, outline = color, tags = tag)


class LineDrawer:

    def __init__(self, gui, memory):
        #default width is 4
        self.__width = 4
        #save the canvas object
        self.gui = gui
        #hold the values of the first click
        self.__firstX = 0
        self.__firstY = 0
        self.__actionList = memory
        self.__lineCounter = 0

    def setInitial(self, x, y):
        self.__firstX = x
        self.__firstY = y

    def setWidth(self, width):
        self.__width = width

    def getWidth(self):
        return self.__width

    def drawTempLine(self, x2, y2):
        coords = self.__firstX, self.__firstY, x2, y2
        self.gui.canvas.create_line(coords, fill = self.gui.color, width = self.__width, tags = "temp")

    def drawLine(self, x2, y2):
        coords = self.__firstX, self.__firstY, x2, y2
        newTag = "line" + str(self.__lineCounter)
        self.gui.canvas.create_line(coords, fill = self.gui.color, width = self.__width, tags = newTag)
        self.__lineCounter = self.__lineCounter + 1
        #Add the line to memory
        self.__actionList.addLine(self.__width, self.gui.color, self.__firstX, self.__firstY, x2, y2, newTag)
        #remove the redo list
        self.__actionList.eraseRedo()

    def redoLine(self, width, color, x1, y1, x2, y2, tag):
        coords = x1, y1, x2, y2
        self.gui.canvas.create_line(coords, fill = color, width = width, tags = tag)

class ArcDrawer:

    def __init__(self, gui, memory):
        self.__start = 0
        self.__extent = 90
        self.__firstX = 0
        self.__firstY = 0
        self.__actionList = memory
        self.gui = gui
        #counter to help keep track of drawing objects
        self.arcCounter = 0

    def setInitial(self, x, y):
        self.__firstX = x
        self.__firstY = y

    def setStart(self, start):
        self.__start = start

    def getStart(self):
        return self.__start

    def setExtent(self, extent):
        self.__extent = extent

    def getExtent(self):
        return self.__extent

    def drawTempArc(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        self.gui.canvas.create_arc(coord, start = self.__start, extent = self.__extent, fill = self.gui.color, outline = self.gui.color, style = ARC, tags = "temp")

    def drawArc(self, x2, y2):
        coord = self.__firstX, self.__firstY, x2, y2
        newTag = "arc" + str(self.arcCounter)
        self.gui.canvas.create_arc(coord, start = self.__start, extent = self.__extent, fill = self.gui.color, outline = self.gui.color, style = ARC, tags = newTag)
        #Add object to memory
        self.__actionList.addArc(self.__start, self.__extent, self.gui.color, self.__firstX, self.__firstY, x2, y2, newTag)
        self.arcCounter = self.arcCounter + 1
        #remove the redo list
        self.__actionList.eraseRedo()

    def redoArc(self, start, extent, color, x1, y1, x2, y2, tag):
        coord = x1, y1, x2, y2
        self.gui.canvas.create_arc(coord, start = start, extent = extent, fill = color, outline = color, style = ARC, tags = tag)


#class for free-drawing
class FreeDrawer:

    def __init__(self, gui, memory):
        self.__gui = gui
        self.__memory = memory
        self.__freeCount = 0
        self.__tempPoints = []

    def getTempPoints(self):
        return self.__tempPoints

    def getFreeCount(self):
        return self.__freeCount

    def addPoint(self, x, y):
        x1 = x - 5
        y1 = y - 5
        x2 = x + 5
        y2 = y + 5
        #add a new point
        self.__gui.canvas.create_oval(x1, y1, x2, y2, fill = self.__gui.color, outline = self.__gui.color, tags = "free" + str(self.__freeCount))
        #add the new point to the tempPoints list
        self.__tempPoints.append([x1, y1, x2, y2, self.__gui.color])

    #this is the method to end the free drawing object. Add it to memory, reset memory, and increment the freeCount
    def endFree(self):
        #Erase any redo memory, since this is a new object, and redo would not make sense
        self.__memory.eraseRedo()
        self.__memory.addFreeDraw()
        self.__tempPoints = []
        self.__freeCount += 1



'''
Memory object to hold each change to the canvas
'''
class ActionList:

    def __init__(self, gui):
        self.__memory = []
        self.__memCount = 0
        self.__removed = []
        self.__remCount = 0
        self.__gui = gui
        self.__freeDrawMemory = dict(initial = ["something"])
        self.__freeDMemoryCount = 0

    #get memory objects (for file writing)
    def getMemory(self):
        return self.__memory

    def getFreeDrawMemory(self):
        return self.__freeDrawMemory

    #Take in references to all of the drawers
    def drawingObject(self, circle, square, line, arc, free):
        self.__circleDrawer = circle
        self.__squareDrawer = square
        self.__lineDrawer = line
        self.__arcDrawer = arc
        self.__freeDrawer = free

    #Methods for adding graphic objects into memory for undo and redo
    def addCircle(self, color, x1, y1, x2, y2, tag):
        self.__memory.append(["circle", color, x1, y1, x2, y2, tag])
        self.__memCount = self.__memCount + 1

    def addSquare(self, color, x1, y1, x2, y2, tag):
        self.__memory.append(["square", color, x1, y1, x2, y2, tag])
        self.__memCount = self.__memCount + 1

    def addLine(self, width, color, x1, y1, x2, y2, tag):
        self.__memory.append(["line", width, color, x1, y1, x2, y2, tag])
        self.__memCount = self.__memCount + 1

    def addArc(self, start, extent, color, x1, y1, x2, y2, tag):
        self.__memory.append(["arc", start, extent, color, x1, y1, x2, y2, tag])
        self.__memCount = self.__memCount + 1

    #Free draw memory is a bit more complex than the other shapes
    def addFreeDraw(self):
        #put the free draw points into the free draw memory
        label = "free" + str(self.__freeDMemoryCount)
        self.__freeDrawMemory[label] = self.__freeDrawer.getTempPoints()
        #put a record of the free draw into the main object memory
        self.__memory.append(["free", label, "free" + str(self.__freeDrawer.getFreeCount())])
        #update the 2 counts
        self.__freeDMemoryCount += 1
        self.__memCount += 1


    def undo(self):
        #only perform if there is something to remove
        if self.__memCount > 0:
            lastObject = self.__memory.pop(len(self.__memory) - 1)
            lastTag = lastObject[len(lastObject) - 1]
            self.__gui.canvas.delete(lastTag)
            #Object deleted. Now add to delete list for redo
            self.__removed.append(lastObject)
            #now adjust counts
            self.__memCount = self.__memCount - 1
            self.__remCount = self.__remCount + 1
            #now show the redo button
            self.__gui.redoButton.grid(row = 1, column = 20)


    def redo(self, newColor = None):
        #only perform if there is something to redo
        if self.__remCount > 0:
            lastRemoved = self.__removed.pop(len(self.__removed) - 1)
            shape = lastRemoved[0]
            shapeFound = False
            if shape == "circle":
                #if newColor is something besides None, then a color was passed in and the method call is from the last color options
                if newColor != None:
                    self.__circleDrawer.redoCircle(newColor, lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6])
                    #actually change the last color in memory
                    lastRemoved[1] = newColor
                else:
                    self.__circleDrawer.redoCircle(lastRemoved[1], lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6])
                shapeFound = True
            elif shape == "square":
                if newColor != None:
                    self.__squareDrawer.redoSquare(newColor, lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6])
                    lastRemoved[1] = newColor
                else:
                    self.__squareDrawer.redoSquare(lastRemoved[1], lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6])
                shapeFound = True
            elif shape == "line":
                if newColor != None:
                    self.__lineDrawer.redoLine(lastRemoved[1], newColor, lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6], lastRemoved[7])
                    lastRemoved[2] = newColor
                else:
                    self.__lineDrawer.redoLine(lastRemoved[1], lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6], lastRemoved[7])
                shapeFound = True
            elif shape == "arc":
                if newColor != None:
                    self.__arcDrawer.redoArc(lastRemoved[1], lastRemoved[2], newColor, lastRemoved[4], lastRemoved[5], lastRemoved[6], lastRemoved[7], lastRemoved[8])
                    lastRemoved[3] = newColor
                else:
                    self.__arcDrawer.redoArc(lastRemoved[1], lastRemoved[2], lastRemoved[3], lastRemoved[4], lastRemoved[5], lastRemoved[6], lastRemoved[7], lastRemoved[8])
                shapeFound = True
            elif shape == "free":
                #The label that the points are stored under is in the 2nd field of the last removed for "free" objects
                #.. __freeDrawMemory stores the actual points under the label.
                freeDrawMem = self.__freeDrawMemory[lastRemoved[1]]
                #now loop through the points memory. If a color was passed in, change the color in the point memory
                if newColor != None:
                    for pt in freeDrawMem:
                        self.__gui.canvas.create_oval(pt[0], pt[1], pt[2], pt[3], fill = newColor, outline = newColor, tags = lastRemoved[2])
                        pt[4] = newColor
                else:
                    for pt in freeDrawMem:
                        self.__gui.canvas.create_oval(pt[0], pt[1], pt[2], pt[3], fill = pt[4], outline = pt[4], tags = lastRemoved[2])
                shapeFound = True
            if shapeFound:
                #add the object back to the memory
                self.__memory.append(lastRemoved)
                self.__memCount = self.__memCount + 1
                #removed from the removed list, so decrement
                self.__remCount = self.__remCount - 1
            if self.__remCount == 0:
                self.__gui.redoButton.grid_forget()

    def eraseRedo(self):
        #this is for when the user creates a new object. The redo list is emptied at that point since it no longer makes sense
        self.__removed = []
        self.__remCount = 0
        self.__gui.redoButton.grid_forget()

    #method for erasing all objects
    def removeAll(self):
        if self.__memCount > 0:
            for x in range(self.__memCount - 1, -1, -1):
                lastObject = self.__memory.pop(x)
                lastTag = lastObject[len(lastObject) - 1]
                self.__gui.canvas.delete(lastTag)
                #Object deleted. Now add to delete list for redo
                self.__removed.append(lastObject)
                #now adjust counts
                self.__memCount = self.__memCount - 1
                self.__remCount = self.__remCount + 1
                #now show the redo button
                self.__gui.redoButton.grid(row = 1, column = 20)


'''
Class for saving and opening files
'''
class FileSaveOpen:

    def __init__(self, memory, circleDrawer, squareDrawer, lineDrawer, arcDrawer):
        self.__memory = memory
        self.__circleDrawer = circleDrawer
        self.__squareDrawer = squareDrawer
        self.__lineDrawer = lineDrawer
        self.__arcDrawer = arcDrawer

    def saveFile(self, fileRef):
        #get the memory
        memory = self.__memory.getMemory()
        freeDrawMemory = self.__memory.getFreeDrawMemory()
        #iterate through memory
        for m in memory:
            if m[0] != "free":
                #if it isn't a free draw object, the memory object itself is sufficient
                #convert the list to a string
                stringList = self.convertMemToString(m)

                #now write to a file
                fileRef.write(stringList + "\n")
            else:
                #get the listing of temp points
                points = freeDrawMemory[m[1]]
                #iterate through the points and add them all
                for p in points:
                    pointString = self.convertPointsToString(p)
                    fileRef.write(pointString + "\n")
        tkmb.showinfo("Done", "File saved!")

    def openFile(self, fileRef):
        #Clear the canvas for the file contents
        self.__memory.removeAll()
        content = ""
        totalList = []
        while True:
            content = fileRef.readline()
            if not content:
                break
            #assemble the list from the string
            obj = []
            parts = content[2:-2].split(",")
            for p in parts:
                obj.append(p)
            #now convert number strings to numbers
            if obj[0] == "circle" or obj[0] == "square":
                obj[1] = obj[1].strip()
                obj[2] = eval(obj[2])
                obj[3] = eval(obj[3])
                obj[4] = eval(obj[4])
                obj[5] = eval(obj[5])
                obj[6] = obj[6].strip()
                #now actually recreate the object
                if obj[0] == "circle":
                    self.__circleDrawer.redoCircle(obj[1], obj[2], obj[3], obj[4], obj[5], obj[6])
                else:
                    self.__squareDrawer.redoSquare(obj[1], obj[2], obj[3], obj[4], obj[5], obj[6])
            elif obj[0] == "line":
                obj[1] = eval(obj[1])
                obj[2] = obj[2].strip()
                obj[3] = eval(obj[3])
                obj[4] = eval(obj[4])
                obj[5] = eval(obj[5])
                obj[6] = eval(obj[6])
                obj[7] = obj[7].strip()
                #redraw the line
                self.__lineDrawer.redoLine(obj[1], obj[2], obj[3], obj[4], obj[5], obj[6], obj[7])
            elif obj[0] == "arc":
                obj[1] = eval(obj[1])
                obj[2] = eval(obj[2])
                obj[3] = obj[3].strip()
                obj[4] = eval(obj[4])
                obj[5] = eval(obj[5])
                obj[6] = eval(obj[6])
                obj[7] = eval(obj[7])
                obj[8] = obj[8].strip()
                self.__arcDrawer.redoArc(obj[1], obj[2], obj[3], obj[4], obj[5], obj[6], obj[7], obj[8])
            else:
                obj[0] = eval(obj[0])
                obj[1] = eval(obj[1])
                obj[2] = eval(obj[2])
                obj[3] = eval(obj[3])
                obj[4] = obj[4].strip()
                self.__circleDrawer.redoCircle(obj[4], obj[0], obj[1], obj[2], obj[3], "free")

    def convertMemToString(self, memory):
        output = "["
        count = 0
        if memory[0] == "circle":
            count = 7
        elif memory[0] == "square":
            count = 7
        elif memory[0] == "line":
            count = 8
        elif memory[0] == "arc":
            count = 9

        for x in range(0, count):
            output += " " + str(memory[x])
            if x != count - 1:
                output += ","
        output += "]"
        return output

    def convertPointsToString(self, points):
        output = "["
        for x in range(0, 5):
            output += " " + str(points[x])
            if x != 4:
                output += ","
        output += "]"
        return output

#Start the application
PaintGui()
The indelible lord of tl;dr
User avatar
Script47
Posts: 147
Joined: Thu Nov 21, 2013 6:11 pm

Re: Paint

Post by Script47 »

Thanks all. :)

@Jack that is a lot more advanced than mine. :D
User avatar
Script47
Posts: 147
Joined: Thu Nov 21, 2013 6:11 pm

Re: Paint

Post by Script47 »

Thought I would just add some features:

Version: 1.2

-Save Image
-View Saved Image

http://script47.tk/Paint/

Enjoy. :)
User avatar
Jackolantern
Posts: 10893
Joined: Wed Jul 01, 2009 11:00 pm

Re: Paint

Post by Jackolantern »

Script47 wrote:@Jack that is a lot more advanced than mine. :D
That is why I thought you may want to see it ;)

You had the same idea as I had to freehand draw on a canvas. :cool:
The indelible lord of tl;dr
User avatar
Script47
Posts: 147
Joined: Thu Nov 21, 2013 6:11 pm

Re: Paint

Post by Script47 »

If anyone wants anything added, I can give it a shot. Just give me a shout on here or some other way. :)
User avatar
Script47
Posts: 147
Joined: Thu Nov 21, 2013 6:11 pm

Re: Paint

Post by Script47 »

I have now made the source available on http://www.github.com/Script47/Paint have fun! :)
User avatar
a_bertrand
Posts: 1537
Joined: Mon Feb 25, 2013 1:46 pm

Re: Paint

Post by a_bertrand »

You know right that your sources were anyhow available?
Creator of Dot World Maker
Mad programmer and annoying composer
Post Reply

Return to “Project Showoff Tier II”