PyQt5 - изменения палитры / таблицы стилей заставляют программу обрабатывать sh с помощью eventFilter - PullRequest
0 голосов
/ 12 апреля 2020

Я пытался имитировать c Windows 'калькулятор, используя PyQt5. Я достиг точки, когда мне нужно было изменить цвет текста на QLabel, который я использую в качестве пользовательской границы окна (чтобы разрешить такие вещи, как прозрачность).

Я начал экспериментировать с такими вещами, как QEvent и eventFilter и с использованием таких методов, как isActiveWindow, чтобы попытаться переключиться между оттенками черного и между прозрачным и непрозрачным.

Таким образом, мне удалось добраться до стадии, когда фон прекрасно меняется, но в тот момент, когда я пытаюсь добавить QLabel / Text в смесь, программа вылетает в разные моменты. На момент написания статьи мне не удалось выяснить, где и почему, и с помощью консоли просто выводится «Процесс завершен с кодом выхода -1073740791 (0xC0000409)».

Кроме того, я не смог найти ничего очевидного для моих текущих знаний и опыта относительно того, почему это происходит. Пока что YouTube, Google и существующий контент StackOverflow меня разочаровали. : (

Пожалуйста, примите во внимание, что я чрезвычайно новичок в программировании, Python и даже в большей степени PyQt5.

Заранее спасибо,

-Omer

мой полный код:

# 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()
...