Home > Software engineering >  Python Trigger a function when a function is called
Python Trigger a function when a function is called

Time:10-03

So, I am making a desktop app with PyQt6. I have a stylesheet and I want it to update every time I add something to it. Stylesheet is an array and I have multiple functions adding things to it:

    def set_color(self, color):
        self.stylesheet.append(f"color: {color}")

    def set_background_color(self, color):
        self.stylesheet.append(f"background-color: {color}")

    def set_border_radius(self, radius):
        self.stylesheet.append(f"border-radius: {radius}px")
    
    def set_alignment(self, alignment):
        self.stylesheet.append(f"text-align: {alignment}")

Now, I want to update the stylesheet every time I call one of these functions (or a function in the class as a whole) by calling another function that updates it. But I don't want to add it manually to every function. Is there a better way of doing this?

    def update_stylesheet(self):
        result = ""

        for css in self.stylesheet:
            if css.strip():
                result  = css.strip()
                result  = "; "

        self.setStyleSheet(result)

CodePudding user response:

Simple solution: Use function composition.

Instead of calling self.stylesheet.append you could make a helper method, that will call self.stylesheet.append and also call update_stylesheet

def set_color(self, color):
    self.add_style(f"color: {color}")

def set_background_color(self, color):
    self.add_style(f"background-color: {color}")

def set_border_radius(self, radius):
    self.add_style(f"border-radius: {radius}px")

def set_alignment(self, alignment):
    self.add_style(f"text-align: {alignment}")

def add_style(self, new_style):
    self.stylesheet.append(new_style)
    self.update_stylesheet()

More complex solution: Function decorators.

In this case we would make some assertions about what methods the class has present. Using the decorator, we can call the normal method and have extra logic run afterwards. Using the decorator we can hijack a reference to self and call the update_stylesheet method this way.

def update_method(func):
    def wrapper(self, *args, **kwargs):
        res = func(self, *args, **kwargs)
        self.update_stylesheet()
        return res
    return wrapper
@update_method
def set_color(self, color):
    self.stylesheet.append(f"color: {color}")

@update_method
def set_background_color(self, color):
    self.stylesheet.append(f"background-color: {color}")

@update_method
def set_border_radius(self, radius):
    self.stylesheet.append(f"border-radius: {radius}px")

@update_method
def set_alignment(self, alignment):
    self.stylesheet.append(f"text-align: {alignment}")
  • Related