Displaying pop-up windows in Python (PyQt4) - python

I need to know how to be able to make a dialog pop-up when a user clicks a button.
I'm relatively new to both Python and PyQt/QtDesigner. I've only been using in them for about a month, but I think I have a good grasp.
Here's what I have: A main dialog (which is the main part of the application), which I designed in QtDesigner. I converted the .ui to .py using pyuic4easy.
Here's what I want to do: design a new dialog box in the QtDesigner and somehow make it pop up when a user clicks a button on the first (main) dialog.
Here's the code for my main dialog:
import sys
from PyQt4.QtCore import *
from loginScreen import *
class MyForm(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL('clicked()'), self.popup)
...
... Some functions ...
def popup(self):
#Pop-up the new dialog
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())
So as you can see, I've connected the first button to a method named 'popup', which needs to be filled in with code to make my second window pop up. How do I go about doing this? Remember that I already have designed my second dialog in QtDesigner, and I don't need to create a new one.
Thanks for all the help!

So as you can see, I've connected the first button to a method named
'popup', which needs to be filled in with code to make my second
window pop up. How do I go about doing this?
Pretty much the same way you do it for your main window (MyForm).
As usual, you write a wrapper class for your QtDesigner code for the second dialog (like you did with MyForm). Let's call it MyPopupDialog. Then in your popup method, you create an instance and then show your instance with either exec_() or show() depending whether you want a modal or modeless dialog. (If you are not familiar with Modal/Modeless concept, you might refer to the documentation.)
So the overall thing might look like this (with a couple of modifications):
# Necessary imports
class MyPopupDialog(QtGui.QDialog):
def __init__(self, parent=None):
# Regular init stuff...
# and other things you might want
class MyForm(QtGui.QDialog):
def __init__(self, parent=None):
# Here, you should call the inherited class' init, which is QDialog
QtGui.QDialog.__init__(self, parent)
# Usual setup stuff
self.ui = Ui_Dialog()
self.ui.setupUi(self)
# Use new style signal/slots
self.ui.pushButton.clicked.connect(self.popup)
# Other things...
def popup(self):
self.dialog = MyPopupDialog()
# For Modal dialogs
self.dialog.exec_()
# Or for modeless dialogs
# self.dialog.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())

Related

In python, how do I open a new window by clicking a button in a main window using .py files created from .ui files made in QtDesigner?

I have two .py files created from .ui files made in QtDesigner. One is a main window for the program, and the other is a widget that allows users to input information and I'm calling it the "evaluation" widget.
I have a button in the main window called "btn_StartNew", which is meant to open the widget window to allow the user to start a new evaluation. I'm having troubles with opening the main window, and adding the function to the "btn_StartNew" button that opens the "evaluation" widget.
The code I have right now opens both the main window and the evaluation widget in the same window when I run the code:
import sys
from PyQt4 import QtCore, QtGui
from wid_Main import Ui_wid_Main
from wid_Eval_v2 import Ui_wid_Eval
class Win_Eval(QtGui.QWidget):
def __init__(self, parent=None):
super(Win_Eval, self).__init__(parent)
self.ui=Ui_wid_Eval()
self.ui.setupUi(self)
class Win_Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Win_Main, self).__init__(parent)
self.ui=Ui_wid_Main()
self.ui.setupUi(self)
#RUN "start new eval" button
self.ui.btn_StartNew.clicked.connect(self.btn_StartNew_click)
self.dialog = Win_Eval(self)
def btn_StartNew_click(self):
self.dialog.show()
def main():
app = QtGui.QApplication(sys.argv)
main = Win_Main()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Where wid_Main and Ui_wid_Main are the main window file and the main window class, respectively. And wid_Eval_v2 and Ui_wid_Eval are the evaluation widget file and class, respectively.
Any help would be much appreciated!
You must change:
self.dialog = Win_Eval(self)
to
self.dialog = Win_Eval()

show Qwidget window without MainWindow

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_())

PyQt4 menu acction to add new tab to QTabWidget

I'm working on a small application for work w/ python and PyQt4 for the GUI. What I'm trying to accomplish is having a tabbed GUI where when a user clicks on a menu item, the action taken adds a tab to the QTabWidget. I'm currently having trouble getting an action to do such a thing. I've tried creating the GUI by hand and with QT designer, but I cant figure out how, if at all possible, to get an action to add a tab to the QTabWidget. This is my python code:
import sys
from PyQt4 import QtGui, uic
class TestGUI(QtGui.QMainWindow):
def __init__(self):
super(TestGUI, self).__init__()
uic.loadUi('TEST.ui', self)
self.show()
self.actionAdd_Tab.triggered.connect(addTab)
def addTab():
print 'This works'
#Add new tab to GUI
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = TestGUI()
sys.exit(app.exec_())
Pressing the menu item prints 'This works' to the console, so I know that its calling the addTab() function, but how do I get it to add a Tab?
Let me know if you would like to see the .ui file if it will help
The handler for your action needs to create a tab label, and also a widget for the contents of the tab, so that they can be added to the tabwidget.
As a start, try something like this:
import sys
from PyQt4 import QtGui, uic
class TestGUI(QtGui.QMainWindow):
def __init__(self):
super(TestGUI, self).__init__()
uic.loadUi('TEST.ui', self)
self.actionAdd_Tab.triggered.connect(self.handleAddTab)
def handleAddTab(self):
contents = QtGui.QWidget(self.tabWidget)
layout = QtGui.QVBoxLayout(contents)
# add other widgets to the contents layout here
# i.e. layout.addWidget(widget), etc
self.tabWidget.addTab(contents, 'Tab One')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = TestGUI()
window.show()
sys.exit(app.exec_())
QTabWidget's addTab() method, coincidentally named the same, adds a tab.

PyQt4 app button not working

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.

PyQt: Accesing Main Window's Data from a dialog?

So, I'm using Python and PyQt. I have a Main Window that contains a QTableWidget, and a dialog that opens modally and has some QLineEdit widgets... All right so far, but I have 2 problems:
When the dialog opens, my Main Window freezes, and I don't really like that...
What I want, when I finish editing a QLineEdit, is that the program will search the QTableWidget, and if the text from the QLineEdit exists in the table, a dialog will come up and informe about that. That's the general idea. But, so far, I seem to only be able to create a new QTableWidget instance, and I can't use the data from the existing...
What can I do about these?
You wrote:
and a dialog that opens modally
and then:
When the dialog opens, my Main Window freezes
The docs say:
int QDialog::exec () [slot]
Shows the dialog as a modal dialog,
blocking until the user closes it. The function returns a DialogCode
result. If the dialog is application modal, users cannot interact with
any other window in the same application until they close the dialog.
If the dialog is window modal, only interaction with the parent window
is blocked while the dialog is open. By default, the dialog is
application modal.
About modeless dialogs:
A modeless dialog is a dialog that operates independently of other
windows in the same application. Find and replace dialogs in
word-processors are often modeless to allow the user to interact with
both the application's main window and with the dialog.
Modeless
dialogs are displayed using show(), which returns control to the
caller immediately.
An example:
import sys
from PyQt4 import QtCore, QtGui
class SearchDialog(QtGui.QDialog):
def __init__(self, parent = None):
QtGui.QDialog.__init__(self, parent)
self.setWindowTitle('Search')
self.searchEdit = QtGui.QLineEdit()
layout = QtGui.QVBoxLayout()
layout.addWidget(self.searchEdit)
self.setLayout(layout)
class MainWindow(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self, None)
self.resize(QtCore.QSize(320, 240))
self.setWindowTitle('Main window')
self.logText = QtGui.QPlainTextEdit()
searchButton = QtGui.QPushButton('Search')
layout = QtGui.QVBoxLayout()
layout.addWidget(self.logText)
layout.addWidget(searchButton)
self.setLayout(layout)
searchButton.clicked.connect(self.showSearchDialog)
def showSearchDialog(self):
searchDialog = SearchDialog(self)
searchDialog.show()
searchDialog.searchEdit.returnPressed.connect(self.onSearch)
def onSearch(self):
self.logText.appendPlainText(self.sender().text())
def main():
app = QtGui.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
app.exec_()
if __name__ == "__main__":
main()
Click 'Search' to open a search window (you can open several of them). Enter a text to search and press Enter. The text to search will be added to the log in the main window.

Categories