how are you doing?
I have been coding for a couple months. I started with Python, now I am trying to learn PyQt5.
I have created two windows using the Designer Tool. I created a subclass for each specific page, so that it wont mess up my software once i make changes in the Designer.
I managed to make my second window open from the first window. It works well. However, nothing works in window 2 when its opened by window 1. However, when i run window 2 by itself, it does not work.
I am sure it is a inheritance problem that I am messing up. It seems my sofware is inheriting the window 2 layout but not its functions.
I have attached the code. Is it possible for someone to help me out? If possible, i would like a brief explanation on how to fix it too. I want to learn so I can teach others as well.
This is my main window:
from nonregusrscreen1 import NonReg
from Main import Ui_MainWindow # needs to import from the main file
from PyQt5 import QtCore, QtGui, QtWidgets #importing PyQt functionality
class mainWin(QtWidgets.QMainWindow, Ui_MainWindow): #mainWin is new subclass. QtWidgets.Whatever the window was / you need to get inheritance from Ui_MainWindow, otherwise you wil lahve to use self.ui.pushbutton....
def __init__(self, *args, **kwargs): #passing arguments from whatever was called
super().__init__(*args, **kwargs)
self.ui = Ui_MainWindow()
self.setupUi(self)
self.pushButton_2.clicked.connect(self.openwindow) # you have to include UI, otherwise it will not work.
def openwindow(self):
self.window = QtWidgets.QDialog()
self.ui = NonReg()
self.ui.setupUi(self.window)
self.window.show()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = mainWin()
w.show()
app.exec_()
This is my second window, here you can see the pushbutton_2 function that only works when the file is opened by itself (not opened using the first window)
from nonregusrscreen import Ui_NonRegUserScreen
from PyQt5 import QtCore, QtGui, QtWidgets
class NonReg(QtWidgets.QDialog, Ui_NonRegUserScreen):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ui = Ui_NonRegUserScreen
self.setupUi(self)
self.pushButton_2.clicked.connect(self.closewindow)
def closewindow(self):
self.window = exit()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = NonReg()
w.show()
app.exec_()
Thank you, i truly appreciate your help.
Related
I created two .ui files with Qtdesigner: the first "interface.ui" which is the main interface and the second "param.ui" a secondary window. I'm trying to boot directly from file.ui without converting the file to python format..
I'm starting the program from main.py and the problem starts when I try to open "param.ui" with a button (called "puls") present in "interface.ui".
The secondary window is not going to open after pressing "puls". I can not understand where is the problem ... If someone wants to help me I thank him in advance.
from PyQt5 import QtWidgets, uic
class ParamWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
uic.loadUi("param.ui", self)
print("ParamWindow init")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi("interface.ui", self)
self.puls = self.findChild(QtWidgets.QPushButton, "puls")
self.puls.clicked.connect(self.openParamWindow)
print("MainWindow init")
def openParamWindow(self):
paramWindow = ParamWindow()
paramWindow.show()
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
app.exec_()
I am having problems showing a QWidget window for the user to input some data.
My script has not GUI, but I just want to show this small QWidget window.
I created the window with QtDesigner, and now I am trying to show the QWidget window like this:
from PyQt4 import QtGui
from input_data_window import Ui_Form
class childInputData(QtGui.QWidget ):
def __init__(self, parent=None):
super(childInputData, self).__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setFocus(True)
self.show()
And then, from my main class, I am doing like that:
class myMainClass():
childWindow = childInputData()
That gave me the error:
QWidget: Must construct a QApplication before a QPaintDevice
So now I am doing, from my main class:
class myMainClass():
app = QtGui.QApplication(sys.argv)
childWindow = childInputData()
Now there is no error, but the window is showed twice and the script does not wait until the data is entered, it just shows the window and continues without waiting.
What is wrong here?
It's perfectly normal that the window is shown and the script goes on: you never told the script to wait for the user to answer. You just told it to show a window.
What you would like is the script to stop until the user is done and the window is closed.
Here's one way to do it:
from PyQt4 import QtGui,QtCore
import sys
class childInputData(QtGui.QWidget):
def __init__(self, parent=None):
super(childInputData, self).__init__()
self.show()
class mainClass():
def __init__(self):
app=QtGui.QApplication(sys.argv)
win=childInputData()
print("this will print even if the window is not closed")
app.exec_()
print("this will be print after the window is closed")
if __name__ == "__main__":
m=mainClass()
The exec() method "Enters the main event loop and waits until exit() is called" (doc):
the script will be blocked on the line app.exec_() until the window is closed.
NB: using sys.exit(app.exec_()) would cause the script to end when the window is closed.
An other way is to use QDialog instead of QWidget. You then replace self.show() by self.exec(), which will block the script
From the doc:
int QDialog::exec()
Shows the dialog as a modal dialog, blocking until the user closes it
Finally, this answer of a related question advocates not to use exec, but to set the window modality with win.setWindowModality(QtCore.Qt.ApplicationModal). However this doesn't work here: it blocks inputs in other windows, but do not block the script.
you dont need the myMainClass...do something like this:
import sys
from PyQt4 import QtGui
from input_data_window import Ui_Form
class childInputData(QtGui.QWidget):
def __init__(self, parent=None):
super(childInputData, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setFocus(True)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
win = childInputData()
win.show()
sys.exit(app.exec_())
I'm trying to set up an app in Linux using PyQt4 designer and I'm struggling to connect signals and slots to it. Right now all I want it to do is connect a button clicked signal to a custom slot, saveEnergyScheme which simply prints 'energy list' to the terminal.
I've translated the .ui code for my app to a python class with pyuic4 -w sumcorr.ui > sumcorr_ui.py. This created a class in the sumcorr_ui.py module called SumCorr_ui:
class SumCorr_ui(QtGui.QMainWindow, Ui_SumCorr_ui):
def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
QtGui.QMainWindow.__init__(self, parent, f)
self.setupUi(self)
I then made my app as a custom widget and tried to add a simple signal-slot connection to a button to show it works:
from PyQt4 import QtGui, QtCore
from sumcorr_ui import SumCorr_ui
class SumCorr(SumCorr_ui):
def __init__(self):
SumCorr_ui.__init__(self)
self.save_energies_button.clicked.connect(self.saveEnergyScheme)
def saveEnergyScheme(self):
print 'energyList'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
mySumCorr = QtGui.QMainWindow()
ui = SumCorr()
ui.setupUi(mySumCorr)
mySumCorr.show()
sys.exit(app.exec_())
I expect to get the line 'energy list' when I click the button named save_energies_button, but nothing happens. Could this be because I haven't built the UI as a widget, but as a main window? Why doesn't it print out??
Try to add ui.show() and you'll see that your code is creating two different windows, one should have the signal connected and one doesn't. That's because you are showing only the mySumCorr window, but you call only setupUi on it, which does not connect the signal.
When you create the SumCorr instance, you are creating a window and setting it up, then, by no reason, you do ui.setupUi(mySumCorr), which setups the mySumCorr instance without connecting the signal, and you show this last window.
I believe your code should be like this:
class SumCorr(QtGui.QMainWindow, Ui_SumCorr_ui):
def __init__(self):
SumCorr_ui.__init__(self)
self.setupUi(self)
self.save_energies_button.clicked.connect(self.saveEnergyScheme)
def saveEnergyScheme(self):
print 'energyList'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
mySumCorr = SumCorr()
mySumCorr.show()
sys.exit(app.exec_())
Note that it doesn't make any sense to have a SumCorr_ui class, that's because Qt is a UI library so you are just introducing a worthless level of abstraction. The designer file already gives you an abstraction over the ui layout.
I've created many GUI interfaces in PyQT using QT Designer, but now I'm trying to open an interface from another one, and I don't know how to do it..
Start.py is the file which run the GUI Interface Authentification_1 and Acceuil_start.py is the file which run the GUI interface Acceuil_2.py, now I want from Start.py to lunch Acceuil_start.py.
Do you have any idea about that ? Thank you.
Here's my code :
Start.py :
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow #??? Acceuil_2.py is the file which I want to open
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Fenetre_auth()
self.ui.setupUi(self)
def authentifier(val): #Slot method
self.Acceuil = Acceuil() #???
self.Acceuil.show() #???
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
Acceuil_start.py
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
First, you should to name your GUI classes so they have a different name, and not the generic one, so you could distinct them.
Why you would need to do that? Well - simply, because it makes sense - if every class is representing different type of dialog, so it is the different type - and it should be named differently. Some of the names are/may be: QMessageBox, AboutBox, AddUserDialog, and so on.
In Acceuil_start.py (you should rename class in other module, too).
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow
class Acceuil(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = Acceuil()
myapp.show()
sys.exit(app.exec_())
in the parent class, when you want to create the window, you are close (but it should work in any case):
def authentifier(val): #Slot method
self.Acceuil = Acceuil(self) # You should always pass the parent to the child control
self.Acceuil.show() #???
About parent issue: If your widget/window is creating another widget, setting creator object to be parent is always a good idea (apart from some singular cases), and you should read this to see why is that so:
QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is. It turns out that this approach fits the needs of GUI objects very well. For example, a QShortcut (keyboard shortcut) is a child of the relevant window, so when the user closes that window, the shorcut is deleted too.
Edit - Minimal Working Sample
To see what I am trying to tell you, I've built a simple example. You have two classes - MainWindow and
ChildWindow. Every class can work without other class by creating separate QApplication objects. But, if you import ChildWindow in MainWindow, you will create ChildWindow in slot connected to singleshot timer which will trigger in 5 seconds.
MainWindow.py:
import sys
from PyQt4 import QtCore, QtGui
from ChildWindow import ChildWindow
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
QtCore.QTimer.singleShot(5000, self.showChildWindow)
def showChildWindow(self):
self.child_win = ChildWindow(self)
self.child_win.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())
ChildWindow.py:
import sys
from PyQt4 import QtCore, QtGui
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = ChildWindow()
myapp.show()
sys.exit(app.exec_())
To reference the other dialog from Start.py, you must prefix it by the module name, which in this case is Acceuil_start. As such, it is OK if there are duplicated function names in each module. So, you would have:
def authentifier(val): #Slot method
dlg = Acceuil_start.StartQT4()
dlg.exec_()
However, if you want these to run from the same process, keep in mind that you can't have two app objects. You would probably want to structure Acceuil_start.py to act like a dialog, rather than a main window. If these are two distinct main windows, you might find it easier to just invoke another Python interpreter with the Acceuil_start.py as a parameter.
I am very new to this and have used the Qt Designer to make a very simple main window ui. The first functionality I want in my project is for a button to open a different window when clicked.
So basically I have the file autoGenUI.py that is generated using pyside-uic which includes
from PySide import QtCore, QtGui
class AutoGeneratedUI(object):
def setupUi(self, MainWindow):
#Auto generated code
def retranslateUi(self, MainWindow):
#Auto generated code
This all works fine of course because the Qt designer made it. I then have my own .py file that is basically my application stuff.
It looks like this:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from autoGenUI import *
class MyMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.ui = AutoGeneratedUI()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
myMainWindow = MyMainWindow()
myMainWindow.show()
sys.exit(app.exec_())
My button is called self.pushButton in the auto generated python UI. I would like to design another window and then call that window but for now anything will do. I just don't know where to put the code to make my button do something.
I tried to follow the docs but couldn't get anything to work.
Any help is greatly appreciated.
Thanks
You need to connect the clicked signal of pushButton to a method such as on_button_clicked():
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.ui = AutoGeneratedUI()
self.ui.setupUi(self)
# connect the clicked signal to on_button_clicked() method
self.pushButton.clicked.connect(self.on_button_clicked)
def on_button_clicked(self):
print "button clicked"
# here is the code to open a new window