I'm at an impasse with this little project. I have a calculator with buttons for basic operations, a screen, and a history showing the previous numbers in the expression. As far as I can tell, I need to make the calculator's screen and history global so I can access them from the calculator's button's methods.
Here's the unfinished but functioning code, this is 99% GUI:
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QLineEdit
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import *
class Calculator(QWidget):
def __init__(self):
super().__init__()
# All our buttons are here
zero = QPushButton("0")
one = QPushButton("1")
two = QPushButton("2")
three = QPushButton("3")
four = QPushButton("4")
five = QPushButton("5")
six = QPushButton("6")
seven = QPushButton("7")
eight = QPushButton("8")
nine = QPushButton("9")
plus = QPushButton("+")
minus = QPushButton("-")
times = QPushButton("*")
divide = QPushButton("/")
dot = QPushButton(".")
equals = QPushButton("=")
# User's history will appear above the screen
history = QLabel()
# Creating a Regex validator to limit inputs to numbers and appropriate symbols
regex = QRegExp("\\d*(?:\\.\\d+)?")
num_validator = QRegExpValidator(regex)
# Screen is a one line text box using the above Regex validator
screen = QLineEdit()
screen.setAlignment(Qt.AlignRight)
screen.setValidator(num_validator)
# The calculator has a four column layout
first_col = QVBoxLayout()
second_col = QVBoxLayout()
third_col = QVBoxLayout()
fourth_col = QVBoxLayout()
# Creating Layout
zero_and_divide_container = QHBoxLayout()
button_container = QHBoxLayout()
screen_and_button_container = QVBoxLayout()
first_col.addWidget(seven)
first_col.addWidget(four)
first_col.addWidget(one)
second_col.addWidget(eight)
second_col.addWidget(five)
second_col.addWidget(two)
third_col.addWidget(nine)
third_col.addWidget(six)
third_col.addWidget(three)
fourth_col.addWidget(plus)
fourth_col.addWidget(minus)
fourth_col.addWidget(times)
button_container.addLayout(first_col)
button_container.addLayout(second_col)
button_container.addLayout(third_col)
button_container.addLayout(fourth_col)
zero_and_divide_container.addWidget(dot)
zero_and_divide_container.addWidget(zero)
zero_and_divide_container.addWidget(equals)
zero_and_divide_container.addWidget(divide)
screen_and_button_container.addWidget(history)
screen_and_button_container.addWidget(screen)
screen_and_button_container.addLayout(button_container)
screen_and_button_container.addLayout(zero_and_divide_container)
self.setLayout(screen_and_button_container)
self.show()
def main():
app = QApplication([])
calc = Calculator()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This does what it's supposed to. However, as stated before, I need to make the screen and history global so the button methods can access their contents. When I try to do that in the simplest way, by just moving the history and screen out of the method, like so:
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QLineEdit
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import *
class Calculator(QWidget):
# Screen will appear above buttons
screen = QLineEdit()
# User's history will appear above the screen
history = QLabel()
def __init__(self):
super().__init__()
zero = QPushButton("0")
one = QPushButton("1")
two = QPushButton("2")
three = QPushButton("3")
four = QPushButton("4")
five = QPushButton("5")
six = QPushButton("6")
seven = QPushButton("7")
eight = QPushButton("8")
nine = QPushButton("9")
plus = QPushButton("+")
minus = QPushButton("-")
times = QPushButton("*")
divide = QPushButton("/")
dot = QPushButton(".")
equals = QPushButton("=")
# Creating a Regex validator to limit inputs to numbers and appropriate symbols
regex = QRegExp("\\d*(?:\\.\\d+)?")
num_validator = QRegExpValidator(regex)
# Screen is a one line text box using the above Regex validator
self.screen.setAlignment(Qt.AlignRight)
self.screen.setValidator(num_validator)
# The calculator has a four column layout
first_col = QVBoxLayout()
second_col = QVBoxLayout()
third_col = QVBoxLayout()
fourth_col = QVBoxLayout()
# Creating Layout
zero_and_divide_container = QHBoxLayout()
button_container = QHBoxLayout()
screen_and_button_container = QVBoxLayout()
first_col.addWidget(seven)
first_col.addWidget(four)
first_col.addWidget(one)
second_col.addWidget(eight)
second_col.addWidget(five)
second_col.addWidget(two)
third_col.addWidget(nine)
third_col.addWidget(six)
third_col.addWidget(three)
fourth_col.addWidget(plus)
fourth_col.addWidget(minus)
fourth_col.addWidget(times)
button_container.addLayout(first_col)
button_container.addLayout(second_col)
button_container.addLayout(third_col)
button_container.addLayout(fourth_col)
zero_and_divide_container.addWidget(dot)
zero_and_divide_container.addWidget(zero)
zero_and_divide_container.addWidget(equals)
zero_and_divide_container.addWidget(divide)
screen_and_button_container.addWidget(self.history)
screen_and_button_container.addWidget(self.screen)
screen_and_button_container.addLayout(button_container)
screen_and_button_container.addLayout(zero_and_divide_container)
self.setLayout(screen_and_button_container)
self.show()
def main():
app = QApplication([])
calc = Calculator()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The window never opens and I get exit code -1073740791 (0xC0000409). What am I doing wrong here?
I recommend you run your code from the terminal to get a more explanatory error message, in your case I get:
QWidget: Must construct a QApplication before a QWidget
Aborted (core dumped)
And there the error is pointed out, QWidget must be created after QApplication but in your case they are created before, also I do not see any advantage in that they are variables of the class instead of attributes.
The solution is to move it to:
# ...
class Calculator(QWidget):
def __init__(self):
super().__init__()
# Screen will appear above buttons
self.screen = QLineEdit()
# User's history will appear above the screen
self.history = QLabel()
zero = QPushButton("0")
# ...
User contributions licensed under CC BY-SA 3.0