Passing methods from secondary GUI to main GUI in python - python

So I have 2 GUIs. One is the main gui which has one push button to activate the second gui. The second gui is a simple calculator which sums two numbers when I push the button with external function.The second gui (the calculator) runs fine standalone However when I try to activate the second gui from the main one the program crashes so I probably doing something wrong.
Also if I change the code in main to this:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.SumCalcBtn.clicked.connect(self.OpenSecondWindow)
def OpenSecondWindow(self):
self.ex = SumCalculator(self)
self.ex.show()
It runs but doesn't do anything in second gui when I push the button to sum the numbers.(it seems the methods didn't pass to the instance)
I attach the code for better understanding:
Main.py
import sys
from calculators import summary
from PyQt5 import QtCore, QtGui, QtWidgets
from SummaryUI import Ui_SummaryUI
from SummaryMain import SumCalc
from MainWindow import Ui_MainWindow
class SumCalculator(SumCalc):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.SumCalcBtn.clicked.connect(self.OpenSecondWindow)
def OpenSecondWindow(self):
self.ex = SumCalc(self)
self.ex.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
SummaryMain.py
import sys
from calculators import summary
from PyQt5 import QtCore, QtGui, QtWidgets
from SummaryUI import Ui_SummaryUI
class SumCalc(QtWidgets.QMainWindow, Ui_SummaryUI):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_SummaryUI.__init__(self)
self.setupUi(self)
self.CalculateSumBtn.clicked.connect(self.sum_function)
def sum_function(self):
number_a = int(self.FirstNumberInput.text())
number_b = int(self.SecondNumberInput.text())
sum = summary(number_a, number_b)
self.SumResultsValue.setText(str(sum))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = SumCalc()
window.show()
sys.exit(app.exec_())

replace self.ex = SumCalc(self) with self.ex = SumCalc() because the constructor(__init__) function of SumCalc does not take any argument (def __init__(self))
or juts add parameter parent to SumCalc's constructor so it becomes def __init__(self, parent=none)

Related

Why is my gif appearing only after my function finishes running [duplicate]

I have got this problem. I´m trying to set text on a lineEdit object on pyqt4, then wait for a few seconds and changing the text of the same lineEdit. For this I´m using the time.sleep() function given on the python Time module. But my problem is that instead of setting the text, then waiting and finally rewrite the text on the lineEdit, it just waits the time it´s supposed to sleep and only shows the final text. My code is as follows:
from PyQt4 import QtGui
from gui import *
class Ventana(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
import time
self.lineEdit.setText('Start')
time.sleep(2)
self.lineEdit.setText('Stop')
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())
You can't use time.sleep here because that freezes the GUI thread, so the GUI will be completely frozen during this time.
You should probably use a QTimer and use it's timeout signal to schedule a signal for deferred delivery, or it's singleShot method.
For example (adapted your code to make it run without dependencies):
from PyQt4 import QtGui, QtCore
class Ventana(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setLayout(QtGui.QVBoxLayout())
self.lineEdit = QtGui.QLineEdit(self)
self.button = QtGui.QPushButton('clickme', self)
self.layout().addWidget(self.lineEdit)
self.layout().addWidget(self.button)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
self.lineEdit.setText('Start')
QtCore.QTimer.singleShot(2000, lambda: self.lineEdit.setText('End'))
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())
Also, take a look at the QThread sleep() function, it puts the current thread to sleep and allows other threads to run. https://doc.qt.io/qt-5/qthread.html#sleep
You can't use time.sleep here because that freezes the GUI thread, so the GUI will be completely frozen during this time.You can use QtTest module rather than time.sleep().
from PyQt4 import QtTest
QtTest.QTest.qWait(msecs)
So your code should look like:
from PyQt4 import QtGui,QtTest
from gui import *
class Ventana(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
import time
self.lineEdit.setText('Start')
QtTest.QTest.qWait(2000)
self.lineEdit.setText('Stop')
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())

PyQt5 .ui file not loading

So my expected outcome is for the login.ui to show when the login button is clicked. My code reached the def gotologin function and the class LoginScreen , but it doesn't load the ui
import sys
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication
class WelcomeScreen(QDialog):
def __init__(self):
super(WelcomeScreen, self).__init__()
loadUi('welcomescreen.ui', self)
self.login.clicked.connect(self.gotologin)
def gotologin(self):
login = LoginScreen()
widget.addWidget(login)
widget.setCurrentIndex(widget.currentIndex()+1)
class LoginScreen(QDialog):
def __init__(self):
super(LoginScreen, self).__init__()
loadUi('login.ui', self)
app = QApplication(sys.argv)
welcome = WelcomeScreen()
widget = QtWidgets.QStackedWidget()
widget.addWidget(welcome)
widget.setFixedHeight(800)
widget.setFixedWidth(1200)
window = WelcomeScreen()
window.show()
try:
sys.exit(app.exec_())
except:
print('Exiting')
Your logic is strange since you are creating 2 WelcomeScreen: One added to the QStackedWidget and the second as a window. Besides that, the QStackedWidget has never been shown. And as the icing on the cake you don't limit the scopes of the variables.
Considering the above, it is better to create a controller that implements the logic of switching widgets and limits scopes.
import sys
from functools import cached_property
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QApplication, QDialog, QStackedWidget
class WelcomeScreen(QDialog):
def __init__(self):
super(WelcomeScreen, self).__init__()
loadUi("welcomescreen.ui", self)
class LoginScreen(QDialog):
def __init__(self):
super(LoginScreen, self).__init__()
loadUi("login.ui", self)
class Controller:
def __init__(self):
self.stacked_widget.addWidget(self.welcome)
self.stacked_widget.addWidget(self.login)
self.welcome.login.clicked.connect(self.goto_login)
#cached_property
def stacked_widget(self):
return QStackedWidget()
#cached_property
def welcome(self):
return WelcomeScreen()
#cached_property
def login(self):
return LoginScreen()
def goto_login(self):
self.stacked_widget.setCurrentWidget(self.login)
def main(args):
app = QApplication(args)
controller = Controller()
controller.stacked_widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main(sys.argv)
And finally, do not silence the exceptions since their reason for being is to indicate that something is wrong. I prefer that when the program fails then it shouts at me that a silent error since the latter is the cause of many bugs.

How to change UI in same window using PyQt5?

I'm just getting started with PyQt5. I have been trying to accomplish a seemingly very simple task but haven't been able to get enough info about it. After a fair bit of googling I have been able to get one window to close and another to launch with the other UI loaded but that's not what I want to do here.
I want to switch the UI in the same window. I am loading the UI files as global variables in my python file where I have 2 classes for each UI. When I click a particular button in one UI, I want to switch to the other UI in the same window. Below is a sample of the code:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
from PyQt5.uic import loadUiType
import os
about_company_ui, _ = loadUiType(os.path.join('frontend', 'ui', 'about_company.ui'))
intern_placement_ui, _ = loadUiType(os.path.join('frontend', 'ui', 'intern_placement.ui'))
class InternPlacement(QMainWindow, intern_placement_ui):
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
self.intern_pushButton.clicked.connect(self.change)
def change(self):
self.about_company = AboutCompany()
self.about_company.show()
self.close()
class AboutCompany(QMainWindow, about_company_ui):
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = InternPlacement()
window.show()
app.exec_()
You have to use a QStackedWidget
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
ui_folder = os.path.join("frontend", "ui")
about_company_ui, _ = uic.loadUiType(os.path.join(ui_folder, "about_company.ui"))
intern_placement_ui, _ = uic.loadUiType(os.path.join(ui_folder, "intern_placement.ui"))
class InternPlacement(QtWidgets.QMainWindow, intern_placement_ui):
def __init__(self, parent=None):
super(InternPlacement, self).__init__(parent)
self.setupUi(self)
class AboutCompany(QtWidgets.QMainWindow, about_company_ui):
def __init__(self, parent=None):
super(AboutCompany, self).__init__(parent)
self.setupUi(self)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
intern_window = InternPlacement()
about_window = AboutCompany()
w = QtWidgets.QStackedWidget()
w.addWidget(intern_window)
w.addWidget(about_window)
intern_window.intern_pushButton.clicked.connect(lambda: w.setCurrentIndex(1))
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

Python Qt - Use button via function from outside a class

I am quite new to python. For my problem I cannot seem to find an answer. And sadly I didn't find anything that could held me. I try to call a function from another file in the same folder but it won't work. If I call the same function from the same file, it works just fine. The same goes for external classes.
This code works:
import sys
from PyQt5 import QtWidgets
from ui.mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.show()
self.ui.pushButton.clicked.connect(test_function)
def test_function():
window.ui.stackedWidget.setCurrentIndex(1)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
The following code won't work:
import sys
from PyQt5 import QtWidgets
from ui.mainwindow import Ui_MainWindow
from other_file import test_function
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.show()
self.ui.pushButton.clicked.connect(test_function)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
other_file.py
def test_function():
window.ui.stackedWidget.setCurrentIndex(1)
Error: cannot import name 'test_function'

Show dialog window

Can anyone tell me why this code is not working? The Test4 class is my converted simple UI:
import sys
import Test4
from PyQt4 import QtGui, QtCore
class UiViewer(QtGui.QApplication, Test4.Ui_Dialog):
def __init__(self, parent=None):
return super(UiViewer, self).__init__(parent)
self.setupUi(self)
def main(self):
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
uiViewer = UiViewer()
uiViewer.main()
app.exec_()
first of all
you need to use
if __name__ == '__main__'
not
if name == 'main':
and also adding the Error Message and describing the behavior of the application when you run it will help trace the problem.
from your question, it can be any number of problems.
Your UiViewer class needs to inherit from the same class as the top-level widget in Qt Designer (presumably QDialog, in your case, but it could also be a QMainWindow or a QWidget):
class UiViewer(QtGui.QDialog, Test4.Ui_Dialog):
def __init__(self, parent=None):
super(UiViewer, self).__init__(parent)
self.setupUi(self)
And note that you must not put return before the super call, otherwise the __init__ function will exit at that point, meaning the rest of its code won't be executed (in particular, setupUi would not be called).

Categories

Resources