close qt application through program - python

I have written small tool and works well. I would like to system testing where I can open window and close window to run high level flow. But I am not able to figure to close window through program. One silly option is, to kill process to close window but I feel there could be some better way.
Just sharing invoking code
self.logger.info("Running gui mode")
if self.approval:
app = QApplication([])
window = ApprovalWindow(app, self.block, self.mil,
self.vio, self.app,
self.prep, self.logger)
else:
app = QApplication([])
window = ReviewWindow(app, self.block, self.mil,
self.vio,
self.pre, self.logger)
window.create_widget()
window.show()
app.exec_()
Tried method
# app.close()
# for widget in appl.allwidgest():
# widget.close

If you want to terminate the application then you must use the quit() method:
QCoreApplication.quit()
If instead you want to close all the windows then there are the following options:
Close all toplevel widgets:
for tl_widget in QApplication.topLevelWidgets():
tl_widget.close()
Close all QWindows
for window in QGuiApplication.topLevelWindows():
window.close()

Related

PyQt runs button functions on startup

I created a UI using Qt Designer for a python application.
The main function of my application runs when a button is clicked, like this:
self.button.clicked.connect(get_data(arg1, arg2, arg3))
To create the UI when the program begins, here is my main method:
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QDialog()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
However, the function "get_data" runs immediately upon start-up, despite the button not even rendering on my screen.
How can I stop the function from running immediately upon start-up?
It's because you are trying to connect the clicked event to the result of the function get_data. What you want to do is connect it to the actual function, like this:
self.button.clicked.connect(get_data)
You need to find another way to pass args into get_data. A lambda would work, but I'd use other methods (ie making a class)

Displaying a QtGui.QMainWindow object without quiting the script afterwards

I've wrote an object that inherits from QtGui.QMainWindow (python/pyqt). It displays an image and gives me more controls. I want to use this object as additional way to plot figures in the flow of the script (like plt.show())
The problem is that displaying this object involves a code like this:
app = QtGui.QApplication(sys.argv)
mainWin = ImageViewerWindow(result) #ImageViewerWindow inherits from QtGui.QMainWindow
mainWin.show()
app.exec_()
After the "app" was closed, I can't display additional window. Is there a way to display this window, wait for it to close, and then display another window without explicitly using signals?
(signals can be used behind the scenes but I don't want to complicate the user that want to display the image with minimal number of commands)
Probably the easiet way, another way will be catching the closing event in your window.
app = QtGui.QApplication(sys.argv)
mainWin = ImageViewerWindow(result) #ImageViewerWindow inherits from QtGui.QMainWindow
mainWin.show()
differentWindow = dW() # your other window
app.aboutToQuit.connect(lambda: differentWindow.show())
app.exec_()
Another way would be adding the closeEvent method to your window class
class ImageViewerWindow(...): # or QMainWindow
...
def closeEvent(self, event):
differentWindow = dW() # your other window
differentWindow.show()

How to automatically focus QDialog with a Qt.Popup flag set?

Consider the following code snippet using Python 3 and PyQt 5.5:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
d = QDialog()
l = QLineEdit(d)
w.show()
# Comment the following line to gain focus.
d.setWindowFlags(Qt.Popup)
d.show()
app.exec_()
After d.show() is invoked, the dialog is shown but the QLineEdit inside it doesn't have focus. No amount of raise_(), activateWindow() or setFocus() seems to be working. How can I make the dialog automatically gain focus when it's shown? I would like to keep the dialog as Qt.Popup, because I need it to close when I click outside of it.
There is
QWidget::raise();
QWidget::activateWindow();
From the docs:
Sets the top-level widget containing this widget to be the active window.
An active window is a visible top-level window that has the keyboard input focus.
This function performs the same operation as clicking the mouse on the title bar of a top-level window. On X11, the result depends on the Window Manager. If you want to ensure that the window is stacked on top as well you should also call raise(). Note that the window must be visible, otherwise activateWindow() has no effect.
On Windows, if you are calling this when the application is not currently the active one then it will not make it the active window. It will change the color of the taskbar entry to indicate that the window has changed in some way. This is because Microsoft does not allow an application to interrupt what the user is currently doing in another application.
It seems that you need to set focus on the line-edit after the dialog is shown:
l = QLineEdit(d)
w.show()
d.setWindowFlags(Qt.Popup)
d.show()
l.setFocus()
app.exec_()
If that doesn't work, try it with a timer:
QTimer.singleShot(1, l.setFocus)

Using QT (PySide) to get user input with QInputDialog

I did a small script on python to do some stuff, and I want to ask user input first. This is my current code:
import sys
from PySide import QtGui
app = QtGui.QApplication(sys.argv)
gui = QtGui.QWidget()
text, ok = QtGui.QInputDialog.getText(gui, "question",
"""please put the thing I need from you""")
print(text, ok)
if ok:
app.exit()
else:
app.exit()
app.exec_()
print ("I'm aliveeeee'")
The dialog pop-ups exactly as I want, but app.exec_() never ends so the rest of the code is never executed (and the process never finish) I tried to kill it with app.exit(), app.quit(), I also try to show() and close() the QWidget, but nothing is working.
If I do gui.show() before calling the QInputDialog and then close the widget manually, the app closes successfully. However, this is not the behavior I want.
Can you guide me on which is the best way to close the exec loop after I got my data?
PD: This is going to be a windows app (with py2exe) and using the shell is not an option.
Just don't call app.exec_()
The problem here is that this is a toy example. In real life, usually you will show some UI and then call app.exec() to let the user interact with it.

Block and hide QDialog: Alternative to exec_()?

In my Qt-based application (built using PyQt 4.8.6), I have a class that is a subclass of QtGui.QDialog:
class ModelDialog(QtGui.QDialog):
...
When I run the application's user interface, I can display the QDialog like so:
def main():
app = QtGui.QApplication(sys.argv)
dialog = ModelDialog()
dialog.exec_()
According to the Qt docs and the PyQt docs, exec_() is a blocking function for this QDialog, which defaults to a modal window (which by definition prevents the user from interacting with any other windows within the application). This is exactly what happens under normal circumstances.
Recently, however, I've been working on a way to call through the entire QApplication using defaults for all input values, and not asking the user for any input. The application behaves as expected except for one single aspect: calling dialog.exec_() causes the modal dialog to be shown.
The only workaround I've been able to find has been to catch the showEvent function and to promptly hide the window, but this still allows the QDialog object to be shown for a split second:
class ModelDialog(QtGui.QDialog):
...
def showEvent(self, data=None):
self.hide()
Is there a way to prevent the modal window from being shown altogether, while continuing to block the main event loop? I'd love for there to be something like:
def main():
app = QtGui.QApplication(sys.argv)
dialog = ModelDialog()
dialog.setHideNoMatterWhat(True)
dialog.exec_()
(to that end, I tried using QWidget.setVisible(False), but dialog.exec_() sets the dialog to be visible anyways, which is expected according to the Qt docs)
Use app.exec_() instead of dialog.exec_().

Categories