0

I am making a simple visual calculator in PyQt5. I haven't really gone to the actual calculator part because I'm having trouble with the buttons. This is the code:

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QMessageBox
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
        def __init__(self):
                super().__init__()
                self.initUI()
        def initUI(self):
                self.setWindowTitle('Calculator')
                self.setGeometry(100, 100, 4000, 1400)
                self.num1= QLineEdit(self)
                self.num1.move(20, 20)
                self.num1.resize(280,40)
                self.num2 = QLineEdit(self)
                self.num2.move(20, 100)
                self.num2.resize(280,40)

                #minus button
                self.minus = QPushButton('-' , self)
                self.minus.move(80,180)
                self.minus.resize(20,40)
                self.minus.clicked.connect(self.minus_onclick)
                self.show()

                #plus button
                self.plus = QPushButton('+' , self)
                self.plus.move(20,180)
                self.plus.resize(20,40)
                self.plus.clicked.connect(self.plus_onclick)
                self.show()

                #* button
                self.into = QPushButton('*' , self)
                self.into.move(140, 180)
                self.into.resize(20, 40)
                self.into.clicked.connect(self.into_onclick)
                self.show()

                 #division button
                self.div = QPushButton('/' , self)
                self.div.move(140, 180)
                self.div.resize(20, 40)
                self.div.clicked.connect(self.div_onclick)
                self.show()

        def plus_onclick(self):
               num1 =int(self.num1.text())
               op = '+'

        def minus_onclick(self):
               num1 =int(self.num1.text())
               op = '-'

        def into_onclick(self):
               num1 =int(self.num1.text())
               op = '*'

        def div_onclick(self):
               num1 =int(self.num1.text())
               op = '/'



if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

However, the problem is that only the first button works and is shown on the screen, no matter which one it is. What am I doing wrong? Thanks in advance

1
  • you are abusing the use of self.show(). Leave one - the last. Commented Aug 30, 2019 at 13:25

1 Answer 1

1

You need to specify a layout for your window and add your widgets to it:

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QMessageBox, \
    QVBoxLayout
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('Calculator')
        self.setGeometry(100, 100, 4000, 1400)

        self.layout = QVBoxLayout(self)
        self.setLayout(self.layout)

        self.num1 = QLineEdit(self)
        self.num1.move(20, 20)
        self.num1.resize(280, 40)
        self.layout.addChildWidget(self.num1)

        self.num2 = QLineEdit(self)
        self.num2.move(20, 100)
        self.num2.resize(280, 40)
        self.layout.addChildWidget(self.num2)

        # minus button
        self.minus = QPushButton('-', self)
        self.minus.move(80, 180)
        self.minus.resize(20, 40)
        self.minus.clicked.connect(self.minus_onclick)
        self.layout.addChildWidget(self.minus)

        # plus button
        self.plus = QPushButton('+', self)
        self.plus.move(20, 180)
        self.plus.resize(20, 40)
        self.plus.clicked.connect(self.plus_onclick)
        self.layout.addChildWidget(self.plus)

        # * button
        self.into = QPushButton('*', self)
        self.into.move(140, 180)
        self.into.resize(20, 40)
        self.into.clicked.connect(self.into_onclick)
        self.layout.addChildWidget(self.into)

        # division button
        self.div = QPushButton('/', self)
        self.div.move(140, 180)
        self.div.resize(20, 40)
        self.div.clicked.connect(self.div_onclick)
        self.layout.addChildWidget(self.div)

    def plus_onclick(self):
        if isinstance(self.num1.text(), int):
            num1 = int(self.num1.text())
            op = '+'

    def minus_onclick(self):
        if isinstance(self.num1.text(), int):
            num1 = int(self.num1.text())
            op = '-'

    def into_onclick(self):
        if isinstance(self.num1.text(), int):
            num1 = int(self.num1.text())
            op = '*'

    def div_onclick(self):
        if isinstance(self.num1.text(), int):
            num1 = int(self.num1.text())
            op = '/'


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()

    sys.exit(app.exec_())

Also, it is better to call show outside your class constructor.

Hope it helps.

Sign up to request clarification or add additional context in comments.

5 Comments

I realize this might be more a style question than a functional question but would it not make more intuitive sense to group like objects basically instead of spreading your layout all over the place simply group it altogether at the end after defining all the objects that particular layout is going to contain. I think that would make it easier to read/maintain going forward.
Also if your program (or example) does not use sys.argv for anything you ought to replace it with [ ] as functionally its like including a large function in your program that you never call nor ever plan to call. Otherwise nice answer ;)
I agree with both of your points, however, I don't like to change too much the code provided by the OP and try to focus on fixing / answering the problem using the existing code. I usually keep the user interface completely separated, design it with Qt designer and convert the .ui files to python and then inherit from them.
Ick you use the Designer ;) you do realize you can create the same design in the same amount of time (or less) by using the natural in-code usage of pyqt5 over that garbage code that the Designer puts out. I have taught several individuals how to code the right way and they have all found it a lot easier and more efficient to not use the Designer once they understood how to code it properly. But again to each their own just a suggestion or food for thought.
Oh btw I do understand your point of not changing the code too much - however to me it is more important to teach the individual proper coding techniques along with answering the question -- when I make such changes I often accompany it with an in-code explanation remark letting them know why I changed it and whether its a style thing or an actual code issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.