Я пытался имитировать 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()