vendredi 1 mai 2020

How can I structure a large (canvas) GUI class to maintain clarity?

I am currently working on a program based on the tkinter framework. Among other things I use the tkinter canvas to draw objects like rectangles and the like. The canvas is also used as a graphical editor, which can be used to add, delete, drag and drop, zoom and much more.

I noticed that the handling of the canvas GUI is getting more and more difficult, because the class now has more than 1200 lines and it is obviously more difficult to see through the logic despite the use of mnemonic identifiers for variables and methods. So I ask myself how I can structure such a "universal editor" better( to get a better overview)?

I have already done some research in my code, and I have highlighted some central concepts. These are first of all the different modes I use. For example, I use a variable to specify the current canvas mode, i.e. whether an item is currently being moved by drag and drop (in which case methods used for this are executed when the mouse pointer is moved) or whether, for example, the "deleteitem" mode is active, so that left-clicking a method leads to the deletion of an item, e.g. a rectangle.

Often I then achieve a similar structure:

  1. at state XY and event XYY start modes "example mode"
  2. events are passed on and processed by standard methods (see e.g. method motionOperations) and mode methods
  3. for state XY and event XYY, exit modes "example mode

A possible structure would be that I build a separate class for each mode and integrate the respective methods there and switch back and forth between the modes in the main gui class if necessary and move the event bindings (e.g. mouse click or mouse movement) to the respective mode methods

Would this be a suitable way to achieve greater clarity? Or are there perhaps others - perhaps even a design pattern for large guis?

Extract from my code (abstracted):

class CanvasGui(tk.Canvas):

    def __init__(self):
        super().__init__()
        [...]
        self.currentMode = "default" # can also be: "draganddrop" or "deleteitem" or "additem"...
        self.bind("<Motion>", self.motionOperations)
        self.bind("<Button-1>", self.leftClickOperations)
        [...]

    def addItem(self):
        [...]

    def motionOperations(self, event):
        if self.currentMode == "dragandDrop":
            self.dragAndDrop(event)
        elif self.currentMode == "additem":
            self.addItem(event)
        [...]    

    def leftClickOperations(self):
        if self.currentMode == "dragandDrop":
            self.startDragAndDrop(event)
        elif self.currentMode == "deleteitem":
            self.deleteItem(event)
        elif self.currentMode == "additem":
            self.startAddingItem(event)
        [...]  


Aucun commentaire:

Enregistrer un commentaire