PyQt5 - Palette/StyleSheet changes causes program to crash using eventFilter

0

I've been trying to mimic Windows' calculator using PyQt5. I reached a point where I needed to change the text's color that is on the QLabel that I am using as a custom window border(to allow things such as transparency).

I started experimenting with things such as QEvent and eventFilter and using methods such as isActiveWindow to try and switch between shades of black and between transparent color and non-transparent.

Doing so, I managed to get to a stage where the background changes perfectly, but the moment I try and add the QLabel/Text into the mix the program crashes at various points. I've been unable as of writing to figure out where or why and using the console just prints "Process finished with exit code -1073740791 (0xC0000409)".

Also, I couldn't find anything obvious for my current knowledge and experience as to why this is happening. So far YouTube, Google and existing StackOverflow content has let me down. :(

Please take into consideration I am extremely new to programming, Python and even more so PyQt5.

Thanks in advance,

-Omer

My full code:

# this program makes a simple(non-scientific) calculator
import os
import sys

from PyQt5 import QtCore
from PyQt5.QtCore import QObject, Qt, QEvent
from PyQt5.QtGui import QBrush, QFont, QIcon, QPalette, QPixmap, QRegion
from PyQt5.QtWidgets import QApplication, QDesktopWidget, QLabel, \
    QMainWindow, \
    QPushButton, QWidget


class Main(QApplication):
    def __init__(self):
        super(Main, self).__init__(sys.argv)

        self.current_dir = os.getcwd()
        self.current_dir = self.current_dir.replace('\\', '/')
        self.background_palette = QPalette()
        self.background_pixmap = QPixmap()
        self.border_palette = QPalette()
        self.border_pixmap = QPixmap()
        self.background = Background(self.current_dir,
                                     self.background_palette,
                                     self.background_pixmap,
                                     )
        self.main_window = MainWindow(self.background,
                                      self.current_dir,
                                      self.background_palette,
                                      self.background_pixmap)
        self.border = Border(self.current_dir,
                             self.background,
                             self.main_window.window_width,
                             self.main_window.window_title,
                             self.border_palette,
                             self.border_pixmap)

        self.display = Display(self.main_window)
        self.buttons = Buttons(self.background, self.current_dir)

        self.background.init_background()
        self.border.init_border()
        self.display.init_display()
        self.buttons.init_buttons()
        self.main_window.init_window()
        self.focus_coloring = FocusColoring(self.background, self.border)
        self.installEventFilter(self.focus_coloring)
        self.end()

    def end(self):
        sys.exit(self.exec())


# create the calculator's window
class MainWindow(QMainWindow):
    def __init__(self, background, current_dir, background_palette,
                 background_pixmap):
        super(MainWindow, self).__init__()

        self._window_geometry = self.frameGeometry()
        self.desktop_center = QDesktopWidget().availableGeometry().center()

        self.background = background

        self.window_width = 322
        self.window_height = 502
        self.window_title = 'Calculator'

        # set the current directory the script is running from to set a full
        # path for things like images such as the
        # window's icon
        self.current_dir = current_dir
        self.background_palette = background_palette
        self.background_pixmap = background_pixmap

        self.icon_path = '\\images\\icons\\calculator_icon.ico'

        self.full_icon_path = self.current_dir + self.icon_path

    def init_window(self):
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

        self.resize(self.window_width, self.window_height)
        self.setMinimumWidth(self.window_width)
        self.setMaximumWidth(self.window_height)

        # move the window to the center of the user's desktop
        self._window_geometry.moveCenter(self.desktop_center)
        self.move(self._window_geometry.topLeft())

        self.setWindowTitle(self.window_title)

        self.setWindowIcon(QIcon(self.full_icon_path))
        self.setObjectName('QMainWindow')

        self.setCentralWidget(self.background)

        self.show()


class Border(QLabel):
    def __init__(self, current_dir, parent, parent_width, parent_title,
                 border_palette,
                 border_pixmap):
        super(Border, self).__init__(parent)

        self.parent = parent
        self.border_height = 30
        self.border_width = parent_width
        self.border_title = '   ' + parent_title
        self.border_palette = border_palette
        self.border_pixmap = border_pixmap

        self.border_title_font = 'Arial'
        self.border_title_font_size = 9

        self.unfocused_background_path = '\\images\\backgrounds\\unfocused.png'
        self.focused_background_path = '\\images\\backgrounds\\focused.png'
        self.current_dir = current_dir
        self.full_unfocused_path = \
            self.current_dir + self.unfocused_background_path
        self.full_focused_path = \
            self.current_dir + self.focused_background_path
        self.region = QRegion(self.border_pixmap.mask())
        self.border_palette.setBrush(QPalette.Background, QBrush(
                QPixmap(self.full_unfocused_path)))

    def init_border(self):

        self.setObjectName('QLabel')
        self.resize(self.border_width, self.border_height)
        self.setText(self.border_title)
        self.setFont(QFont(
                 self.border_title_font,
                 self.border_title_font_size)
         )
        self.setPalette(self.border_palette)
        self.setAutoFillBackground(True)
        self.setMask(self.border_pixmap.mask())


class Background(QWidget):
    def __init__(self, current_dir, background_palette,
                 background_pixmap):
        super(Background, self).__init__()
        self.unfocused_background_path = '\\images\\backgrounds\\unfocused.png'
        self.focused_background_path = '\\images\\backgrounds\\focused.png'
        self.current_dir = current_dir
        self.background_palette = background_palette
        self.background_pixmap = background_pixmap
        self.full_unfocused_path = \
            self.current_dir + self.unfocused_background_path
        self.full_focused_path = \
            self.current_dir + self.focused_background_path
        self.region = QRegion(self.background_pixmap.mask())
        self.background_palette.setBrush(QPalette.Background, QBrush(
                QPixmap(self.full_unfocused_path)))

    def init_background(self):
        self.setAutoFillBackground(True)
        self.setPalette(self.background_palette)
        self.setMask(self.background_pixmap.mask())


class FocusColoring(QObject):
    def __init__(self, background, label):
        super(FocusColoring, self).__init__()
        self.background = background
        self.label = label

    def change_background(self):
        if self.background.isActiveWindow() is True:
            print(self.background.isActiveWindow())
            self.background.background_palette.setBrush(
                    QPalette.Background, QBrush(QPixmap(
                            self.background.full_focused_path)
                    ))
            self.background.init_background()

        elif self.background.isActiveWindow() is False:
            print(self.background.isActiveWindow())
            self.background.background_palette.setBrush(
                    QPalette.Background, QBrush(QPixmap(
                            self.background.full_unfocused_path)
                    ))
            self.background.init_background()

    def change_border(self):
        if self.background.isActiveWindow() is True:
            self.label.border_palette.setBrush(
                    QPalette.Background, QBrush(QPixmap(
                            self.label.full_focused_path)))
            self.label.init_border()

        elif self.background.isActiveWindow() is False:
            print(self.background.isActiveWindow())
            self.label.label_palette.setBrush(
                    QPalette.Background, QBrush(QPixmap(
                            self.background.full_unfocused_path)
                    ))
            self.label.init_border()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress or \
                QEvent.NonClientAreaMouseButtonPress:
            self.change_background()
            self.change_border()

        return False


class Display(object):
    def __init__(self, parent):
        super(Display, self).__init__()
        self.parent = parent

    # readied to implement

    def init_display(self):
        pass


class Memory(QWidget):
    def __init__(self, parent):
        super(Memory, self).__init__(parent)


class Buttons(QWidget):
    def __init__(self, parent, current_dir):
        super(Buttons, self).__init__(parent)

        self.width = 78
        self.height = 51

        self.parent = parent
        self.posx = -abs(self.width)
        self.posy = 196
        self.original_posx = self.posx
        self.original_posy = self.posy
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.buttons_dict = ['Remainder',
                             'CE',
                             'C',
                             'Backspace',
                             'Multiplicative Inverse',
                             'Power',
                             'Square Root',
                             'Division',
                             '7',
                             '8',
                             '9',
                             'Multiplication',
                             '4',
                             '5',
                             '6',
                             'Subtraction',
                             '1',
                             '2',
                             '3',
                             'Addition',
                             'Negation',
                             '0',
                             'Decimal',
                             'Equals']

        self.current_dir = current_dir

        self.buttons_path = self.current_dir + '/images/buttons'
        self.remainder_default = self.buttons_path + '/remainder/default.png'
        self.remainder_hover = self.buttons_path + '/remainder/hover.png'
        self.remainder_pressed = self.buttons_path + '/remainder/pressed.png'
        self.ce_default = self.buttons_path + '/ce/default.png'
        self.ce_hover = self.buttons_path + '/ce/hover.png'
        self.ce_pressed = self.buttons_path + '/ce/pressed.png'
        self.ce = (self.ce_default,
                   self.ce_hover,
                   self.ce_pressed)
        self.c_default = self.buttons_path + '/c/default.png'
        self.c_hover = self.buttons_path + '/c/hover.png'
        self.c_pressed = self.buttons_path + '/c/pressed.png'

        self.backspace_default = self.buttons_path + '/backspace/default.png'
        self.backspace_hover = self.buttons_path + '/backspace/hover.png'
        self.backspace_pressed = self.buttons_path + '/backspace/pressed.png'

        self.multi_inverse_default = self.buttons_path + \
            '/multi_inverse/default.png'
        self.multi_inverse_hover = self.buttons_path + \
            '/multi_inverse/hover.png'
        self.multi_inverse_pressed = self.buttons_path + \
            '/multi_inverse/pressed.png'

        self.power_default = self.buttons_path + '/power/default.png'
        self.power_hover = self.buttons_path + '/power/hover.png'
        self.power_pressed = self.buttons_path + '/power/pressed.png'

        self.sqrt_default = self.buttons_path + '/sqrt/default.png'
        self.sqrt_hover = self.buttons_path + '/sqrt/hover.png'
        self.sqrt_pressed = self.buttons_path + '/sqrt/pressed.png'

        self.division_default = self.buttons_path + '/division/default.png'
        self.division_hover = self.buttons_path + '/division/hover.png'
        self.division_pressed = self.buttons_path + '/division/pressed.png'

        self.seven_default = self.buttons_path + '/seven/default.png'
        self.seven_hover = self.buttons_path + '/seven/hover.png'
        self.seven_pressed = self.buttons_path + '/seven/pressed.png'

        self.eight_default = self.buttons_path + '/eight/default.png'
        self.eight_hover = self.buttons_path + '/eight/hover.png'
        self.eight_pressed = self.buttons_path + '/eight/pressed.png'

        self.nine_default = self.buttons_path + '/nine/default.png'
        self.nine_hover = self.buttons_path + '/nine/hover.png'
        self.nine_pressed = self.buttons_path + '/nine/pressed.png'

        self.multiply_default = self.buttons_path + '/multiply/default.png'
        self.multiply_hover = self.buttons_path + '/multiply/hover.png'
        self.multiply_pressed = self.buttons_path + '/multiply/pressed.png'

        self.four_default = self.buttons_path + '/four/default.png'
        self.four_hover = self.buttons_path + '/four/hover.png'
        self.four_pressed = self.buttons_path + '/four/pressed.png'

        self.five_default = self.buttons_path + '/five/default.png'
        self.five_hover = self.buttons_path + '/five/hover.png'
        self.five_pressed = self.buttons_path + '/five/pressed.png'

        self.six_default = self.buttons_path + '/six/default.png'
        self.six_hover = self.buttons_path + '/six/hover.png'
        self.six_pressed = self.buttons_path + '/six/pressed.png'

        self.subtract_default = self.buttons_path + '/subtract/default.png'
        self.subtract_hover = self.buttons_path + '/subtract/hover.png'
        self.subtract_pressed = self.buttons_path + '/subtract/pressed.png'

        self.one_default = self.buttons_path + '/one/default.png'
        self.one_hover = self.buttons_path + '/one/hover.png'
        self.one_pressed = self.buttons_path + '/one/pressed.png'

        self.two_default = self.buttons_path + '/two/default.png'
        self.two_hover = self.buttons_path + '/two/hover.png'
        self.two_pressed = self.buttons_path + '/two/pressed.png'

        self.three_default = self.buttons_path + '/three/default.png'
        self.three_hover = self.buttons_path + '/three/hover.png'
        self.three_pressed = self.buttons_path + '/three/pressed.png'

        self.addition_default = self.buttons_path + '/addition/default.png'
        self.addition_hover = self.buttons_path + '/addition/hover.png'
        self.addition_pressed = self.buttons_path + '/addition/pressed.png'

        self.negate_default = self.buttons_path + '/negate/default.png'
        self.negate_hover = self.buttons_path + '/negate/hover.png'
        self.negate_pressed = self.buttons_path + '/negate/pressed.png'

        self.zero_default = self.buttons_path + '/zero/default.png'
        self.zero_hover = self.buttons_path + '/zero/hover.png'
        self.zero_pressed = self.buttons_path + '/zero/pressed.png'

        self.decimal_default = self.buttons_path + '/decimal/default.png'
        self.decimal_hover = self.buttons_path + '/decimal/hover.png'
        self.decimal_pressed = self.buttons_path + '/decimal/pressed.png'

        self.equals_default = self.buttons_path + '/equals/default.png'
        self.equals_hover = self.buttons_path + '/equals/hover.png'
        self.equals_pressed = self.buttons_path + '/equals/pressed.png'

        self.button_style = '''
                QPushButton {{
                margin: 1px;
                border: 0px;
                background-image: url({});
                }}

                QPushButton:hover {{
                background-image: url({});
                }}

                QPushButton:pressed {{
                background-image: url({});
                }}
                '''

    def init_buttons(self):

        for button_index, button in enumerate(self.buttons_dict):
            self.buttons_dict[button_index] = QPushButton(self)
            self.buttons_dict[button_index].setObjectName('QPushButton')
            self.buttons_dict[button_index].resize(self.width, self.height)

            self.posx += self.width

            if self.posx == self.width * 4:
                self.posy = self.posy + self.height - 1
                self.posx = self.original_posx + self.width

            self.buttons_dict[button_index].move(self.posx + 5, self.posy)
            self.buttons_dict[button_index].setFlat(True)
            self.buttons_dict[button_index].setAutoFillBackground(True)

            self.buttons_dict[0].setStyleSheet(
                    self.button_style.format(self.remainder_default,
                                             self.remainder_hover,
                                             self.remainder_pressed)
            )

        self.buttons_dict[1].setStyleSheet(
                self.button_style.format(self.ce_default,
                                         self.ce_hover,
                                         self.ce_pressed)
        )

        self.buttons_dict[2].setStyleSheet(
                self.button_style.format(self.c_default,
                                         self.c_hover,
                                         self.c_pressed)
        )

        self.buttons_dict[3].setStyleSheet(
                self.button_style.format(self.backspace_default,
                                         self.backspace_hover,
                                         self.backspace_pressed)
        )

        self.buttons_dict[4].setStyleSheet(
                self.button_style.format(self.multi_inverse_default,
                                         self.multi_inverse_hover,
                                         self.multi_inverse_pressed)
        )

        self.buttons_dict[5].setStyleSheet(
                self.button_style.format(self.power_default,
                                         self.power_hover,
                                         self.power_pressed)
        )

        self.buttons_dict[6].setStyleSheet(
                self.button_style.format(self.sqrt_default,
                                         self.sqrt_hover,
                                         self.sqrt_pressed)
        )

        self.buttons_dict[7].setStyleSheet(
                self.button_style.format(self.division_default,
                                         self.division_hover,
                                         self.division_pressed)
        )

        self.buttons_dict[8].setStyleSheet(
                self.button_style.format(self.seven_default,
                                         self.seven_hover,
                                         self.seven_pressed)
        )

        self.buttons_dict[9].setStyleSheet(
                self.button_style.format(self.eight_default,
                                         self.eight_hover,
                                         self.eight_pressed)
        )

        self.buttons_dict[10].setStyleSheet(
                self.button_style.format(self.nine_default,
                                         self.nine_hover,
                                         self.nine_pressed)
        )

        self.buttons_dict[11].setStyleSheet(
                self.button_style.format(self.multiply_default,
                                         self.multiply_hover,
                                         self.multiply_pressed)
        )

        self.buttons_dict[12].setStyleSheet(
                self.button_style.format(self.four_default,
                                         self.four_hover,
                                         self.four_pressed)
        )

        self.buttons_dict[13].setStyleSheet(
                self.button_style.format(self.five_default,
                                         self.five_hover,
                                         self.five_pressed)
        )

        self.buttons_dict[14].setStyleSheet(
                self.button_style.format(self.six_default,
                                         self.six_hover,
                                         self.six_pressed)
        )

        self.buttons_dict[15].setStyleSheet(
                self.button_style.format(self.subtract_default,
                                         self.subtract_hover,
                                         self.subtract_pressed)
        )

        self.buttons_dict[16].setStyleSheet(
                self.button_style.format(self.one_default,
                                         self.one_hover,
                                         self.one_pressed)
        )

        self.buttons_dict[17].setStyleSheet(
                self.button_style.format(self.two_default,
                                         self.two_hover,
                                         self.two_pressed)
        )

        self.buttons_dict[18].setStyleSheet(
                self.button_style.format(self.three_default,
                                         self.three_hover,
                                         self.three_pressed)
        )

        self.buttons_dict[19].setStyleSheet(
                self.button_style.format(self.addition_default,
                                         self.addition_hover,
                                         self.addition_pressed)
        )

        self.buttons_dict[20].setStyleSheet(
                self.button_style.format(self.negate_default,
                                         self.negate_hover,
                                         self.negate_pressed)
        )

        self.buttons_dict[21].setStyleSheet(
                self.button_style.format(self.zero_default,
                                         self.zero_hover,
                                         self.zero_pressed)
        )

        self.buttons_dict[22].setStyleSheet(
                self.button_style.format(self.decimal_default,
                                         self.decimal_hover,
                                         self.decimal_pressed)
        )

        self.buttons_dict[23].setStyleSheet(
                self.button_style.format(self.equals_default,
                                         self.equals_hover,
                                         self.equals_pressed)
        )


if __name__ == '__main__':
    main = Main()
python
windows
pyqt5
eventfilter
asked on Stack Overflow Apr 12, 2020 by Omer

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0