Python crash when closing qmainwindow with qdialog open - python

I have a QMainWindow that launches a QDialog everytime I click on a button and I can't figure out why the python binary crashes when I close the QMainWindow while one or more dialogs are open.
It's not a complex Qt app and I'm really struggling trying to understand what happens.
Here's the code:
# dependency modules
from PyQt4 import QtGui
import sys
# custom modules
from ui import SingleOrderUI, DashBoardUI
class SingleOrder(QtGui.QDialog, SingleOrderUI.Ui_SingleOrder):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
class DashBoard(QtGui.QMainWindow, DashBoardUI.Ui_DashBoard):
def __init__(self):
QtGui.QMainWindow.__init__(self)
super(DashBoard, self).__init__()
# setup UI
self.setupUi(self)
self.newOrderBtn.clicked.connect(self.newOrder)
def newOrder(self):
print 'New order clicked'
so = SingleOrder(self)
so.show()
app = QtGui.QApplication(sys.argv)
window = DashBoard()
window.show()
sys.exit(app.exec_())
Any help would be appreciated.
EDIT: When launched using ipython, the dialogs are still showing after I close the QMainWindow, so that's maybe where the issue comes from.
I give the QMainWindow as a parent argument to the QDialog, I thought that was enough to have them killed when the QMainWindow is closed.

Okay, I've found a workaround for that but I'm not sure if it's the right way to do it.
On my DashBoard init method, I've added a python list that will store all the opened Dialogs:
def __init__(self):
QtGui.QMainWindow.__init__(self)
super(DashBoard, self).__init__()
# setup UI
self.setupUi(self)
self.newOrderBtn.clicked.connect(self.newOrder)
self.soTab = []
Then, in the same class, I defined a method to handle the closeEvent and close all the dialogs.
def closeEvent(self, event):
for so in self.soTab:
if so:
so.close()
event.accept()

Related

Why does my PyQt new window open minimised? (And how to prevent that?)

So, basically I have a main window, with a bunch of buttons, which open different windows. On startup, I would like to open up all of them. The problem I am facing is, they are opening up minimised for some reason. I cannot figure out why?
class mainwinActions(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
...
self.open_all_win()
def open_all_win(self):
self.open_exp()
self.open_lick()
self.open_door()
def open_exp(self):
self.expwin = fooWin()
self.expwin.show()
# The same for self.open_lick/self.open_door
Also, I have a button attached to the function.
self.openAllButton.clicked.connect(lambda: self.open_all_win())
And the button does NOT have the same problem. It opens up the windows normally (non-minimised/windowed).
What I tried:
class fooWin(QtWidgets.QWidget, Ui_fooWin):
def __init__(self):
super().__init__()
self.setupUi(self)
...
if self.windowState() == QtCore.Qt.WindowState.WindowMinimized:
# Window is minimised. Restore it.
self.setWindowState(QtCore.Qt.WindowState.WindowActive)
I also tried replacing self.open_all_win() with
self.openAllButton.click()
Edit: Reproducible code
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
import sys
class AnotherWindow(QWidget):
def __init__(self):
super().__init__()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.button = QPushButton("Push for Window")
self.button.clicked.connect(self.show_new_window)
self.setCentralWidget(self.button)
self.show_new_window()
def show_new_window(self):
self.w = AnotherWindow()
self.w.show()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
Edit2: Just to clarify, the problem is only on startup. When I run the code, I want all the windows up without clicking on any button. The windows should be visible when I run the file.
QtCore.QT_VERSION_STR = 6.2.3
OS:MacOS Monterey and Windows 10

My new python gui window opened from another window exits as soon as it opens.How do I fix this

I have written python pyqt code to open a new window with a label from another window on a button click. The issue is ,new window exits as soon as it opens.How do i fix this.
The code I wrote is
import sys
from PyQt4 import QtGui,QtCore
class Window(QtGui.QWidget):
def __init__(self):
super(Window,self).__init__()
self.btn=QtGui.QPushButton('button',self)
self.btn.clicked.connect(display)
self.show()
class display(QtGui.QWidget):
def __init__(self):
super(display,self).__init__()
self.lab=QtGui.QLabel()
self.lab.setText("hi")
self.show()
def main():
App=QtGui.QApplication(sys.argv)
Gui=Window()
sys.exit(App.exec_())
main()
You need to keep a reference to the QWidget object for your second window. Currently when you click the button, the clicked signal is fired and it calls disp1. That creates the widget, but then it is immediately garbage collected.
Instead do this to keep a reference:
import sys
from PyQt4 import QtGui,QtCore
class Window(QtGui.QWidget):
def __init__(self):
super(Window,self).__init__()
self.btn=QtGui.QPushButton('button',self)
self.btn.clicked.connect(self.open_new_window)
self.show()
def open_new_window(self):
# creates the window and saves a reference to it in self.second_window
self.second_window = disp1()
class displ(QtGui.QWidget):
def __init__(self):
super(displ,self).__init__()
self.lab=QtGui.QLabel()
self.lab.setText("hello")
self.show()
def main():
App=QtGui.QApplication(sys.argv)
Gui=Window()
sys.exit(App.exec_())
main()
When passing a function as parameter, maybe it's better not to include the parentheses? Try
sys.exit(App.exec_)
Instead of
sys.exit(App.exec_())

PySide make QDialog appear in main window

I've created an app which has an main window and the possibility to open an dialog (question, error and so on). I'm not using QMessageBox.warning() or QMessageBox.question() and so on because I wanted to customize the dialogs a bit.
But every time I open a new Dialog, in the Windows task bar (I'm working on Windows 10) a new 'tab' is opened, which is a little bit annoying.
My code (shortened):
from PySide import QtCore, QtGui
import sys
class MessageBox:
def __init__(self, title, message):
msg = QtGui.QMessageBox()
flags = QtCore.Qt.Dialog
flags |= QtCore.Qt.CustomizeWindowHint
flags |= QtCore.Qt.WindowTitleHint
msg.setWindowFlags(flags)
msg.setWindowTitle(title)
msg.setText(message)
msg.exec_()
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.show()
MessageBox("Title", "My message here")
if __name__ == "__main__":
app = QtGui.QApplication([])
window = MainWindow()
sys.exit(app.exec_())
Note: Normally, the dialog is called from an menu or button.
Question: How can I make the dialog appear in the main window without creating a new 'task bar tab'?
The solution was quite simple: Passing an reference of QMainWindow to the constructor of QDialog will do the job, e.g:
class MessageBox(QtGui.QDialog):
def __init__(self, parent, title, message, icon="info"):
super(MessageBox, self).__init__(parent)
...
and then calling the dialog from an class that inherits from QMainWindow:
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
#connect button with function, e.g.:
mybutton.clicked.connect(self.open_dialog)
def open_dialog(self):
MessageBox(self)
Maybe this helps anyone!
If you set the parent of the QDialog to the window, it will only show as one item on the task bar. This is generally the first argument to QMessageBox.
class MessageBox:
def __init__(self, parent, title, message):
msg = QtGui.QMessageBox(parent)
Also, if you really want to create a custom dialog, you might as well just subclass from QDialog.

How to accept close event of MainWindow when loading it with QUiLoader()?

How to receive close event in following code?
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.view = QUiLoader().load("sample.ui", self)
self.view.show()
def closeEvent(self, e):
print "close event recieved"
def main():
app = QApplication(sys.argv)
a=Main()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
If I convert sample.ui to sample.py using pyside-uic and importing this into main.py then I was able to receive close event.
from sample import Ui_MainWindow
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
def closeEvent(self, e):
print "close event recieved"
app = QApplication(sys.argv)
a=Main()
a.show()
sys.exit(app.exec_())
The second example works because it effectively becomes a subclass of the top-level class from Qt Designer. By contrast, the first example uses composition rather than subclassing, which puts all the gui elements inside an internal namespace. The Main class is just a container that acts as the parent of the view widget, and is never actually shown (which in turn means it doesn't receive any close events).
In PyQt, the uic module has several funtions which allow you to work around these issues, but there is currently nothing like that in PySide. Instead, you have to roll your own function. See this answer for an explanation of how to do that.
Alternatively, you could change the top-level class in Qt Designer to a QWidget, and then make view the central widget of your Main class. This is a lot less flexible than the above method, though.

How do I open sub window after I click on button on main screen in PyQt4

HI I am trying to make a simple converter.
I have used PyQt4 designed to make the Gui
I want to know how launch a new window after I click on the individual button.
This is the interface I have created using PyQt4 Designer.
Here is the Image link :
and I want to launch this windows when I click on currency button.
Here is the Image Link:
Here is my code for main.py
from PyQt4 import QtGui
from main_screen import mainscreen
def main():
import sys
qApp = QtGui.QApplication(sys.argv)
aw = mainscreen()
aw.show()
sys.exit(qApp.exec_())
if __name__ == '__main__':
main()
and code for mainscreen.py
from PyQt4 import QtCore, QtGui
from window_main import Ui_MainWindow
class mainscreen(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(mainscreen,self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
How can I open new window after I click on currency button (object name for currency button is "currency_bt")
and do I have to write the code for currency in same window or I have to write in new window.
How do I do it.
I am new to Python Gui programming.
Each GUI form that you create in Qt Designer needs to be converted into a python module using pyuic. So, to start with, you need to do the same for currency.ui that you did for window_main.
Now you can import your currency window class into mainscreen.py, and connect a button to handler so you can display it.
The code would look something like this:
from PyQt4 import QtCore, QtGui
from window_main import Ui_MainWindow
from currency import Ui_CurrencyWindow
class CurrencyWindow(QtGui.QMainWindow, Ui_CurrencyWindow):
def __init__(self, parent=None):
super(CurrencyWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setupUi(self)
class MainScreen(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainScreen, self).__init__(parent)
self.setupUi(self)
self.currencyButton.clicked.connect(self.handleCurrencyButton)
def handleCurrencyButton(self):
window = CurrencyWindow(self)
window.show()
After looking at this example code, it will probably occur to you that you are going to end up importing a lot of modules, and have a lot of boiler-plate code to write for each one of them (which is not much fun).
So I would advise you to consider changing your GUI design, so that you have one main window containing a tabwidget, and then have a separate tab for each of your converters. This will not only make your application much easier to write, but it should also make it a lot nicer to use.
I'm making my bachelor thesis in PyQt4. First I also wanted to use the designer (generating code is nice), but afterall I was not using it during my work. Maybe it's a matter of taste.
But for your question (I did this without the QtDesigner):
Let's say we have a main window class:
import sys
from PyQt4 import QtCore, QtGui
class mainscreen(QtGui.QMainWindow):
def __init__(self, parent=None):
super(mainscreen,self).__init__(parent)
self.button = QtGui.QPushButton("push")
self.button.clicked.connect(self.pushed)
#pyqtSlot()
def pushed(self):
# in this section here you can create the new window and show it
qApp = QtGui.QApplication(sys.argv)
aw = mainscreen()
aw.show()
sys.exit(qApp.exec_())
There are some good tutorials (http://zetcode.com/gui/pyqt4/ helped me getting started).
Make two programs: main_win.py and second_win.py, then in main_win.py put this lines:
from os import system as sh //In the begin
def openewin(self): //In the class main_win
sh("python second_win.py")
Ready, just connect the push button to function openewin!

Categories

Resources