Pyside2 second window(QDialog) closes the main one - python

import sys
from PySide2.QtCore import QFile
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtUiTools import QUiLoader
class MyMainWindow(QMainWindow):
def __init__(self):
super().__init__()
loader = QUiLoader()
self.ui = loader.load("mainWindow.ui", self)
self.ui.pushButton_call_dialog.clicked.connect(self.call_dialog)
self.ui.close()
self.ui.show()
def call_dialog(self):
loader = QUiLoader()
self.dialog = loader.load("dialog.ui")
self.dialog.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyMainWindow()
window.show
sys.exit(app.exec_())
Hi everyone,
any idea why the second (dialog) window closes the entire application?
Of course, it is not a crash since i'm getting a message saying:
Process finished with exit code 0
Thanks for your help

You could handle your QDialog on a separate class, and then make them interact only, the structure might change a bit, but you can see if it's a viable answer:
import sys
from PySide2.QtWidgets import *
class MyWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
button = QPushButton("Dialog")
button.clicked.connect(self.open_dialog)
self.setCentralWidget(button)
def open_dialog(self):
dialog = MyDialog()
dialog.show()
dialog.exec_()
class MyDialog(QDialog):
def __init__(self):
QDialog.__init__(self)
button = QPushButton("Close")
button.clicked.connect(self.close_dialog)
layout = QHBoxLayout()
layout.addWidget(button)
self.setLayout(layout)
def close_dialog(self):
self.close()
if __name__ == "__main__":
app = QApplication()
m = MyWindow()
m.show()
sys.exit(app.exec_())
Just notice that you should include the setUp step on each class.
Hope it helps.

To put the dialog into a separate class didn't work for either.
Every time the Dialog.close() event was called, it closes the whole application.
What worked for me, was to use hide() instead

Related

PySide2 display same icon in file dialog as main window

I have a simple pyside2 application which looks kinda like this:
import sys
from PySide2.QtWidgets import QApplication, QDialog, QPushButton, QFileDialog, QVBoxLayout
from PySide2 import QtGui
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.setWindowTitle("My Form")
self.setWindowIcon(QtGui.QIcon("myicon.png"))
layout = QVBoxLayout()
self.button = QPushButton("Open dialog")
self.button.clicked.connect(self.browse)
layout.addWidget(self.button)
self.setLayout(layout)
def browse(self):
qfd = QFileDialog()
qfd.setWindowIcon(QtGui.QIcon("myicon.png"))
filename, _ = qfd.getOpenFileName(None, "Load Data", ".", "*.txt")
if __name__ == '__main__':
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the form
form = Form()
form.show()
# Run the main Qt loop
sys.exit(app.exec_())
I want to setup the same icon for the QFileDialog as the main window icon but for some reason it does not work. Is there a way to set it like I'm trying above? Thanks for ideas, pointers and help in advance! (I'm using Ubuntu 20.04)
The getOpenFileName method is a static method that creates an internal QFileDialog other than "qfd" so the icon is not applied. One possible option is not to use getOpenFileName but to create the logic only using the QFileDialog class, and another solution is to access the QFileDialog object created inside getOpenFileName using the characteristic that is a toplevel:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class Form(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.setWindowTitle("My Form")
self.setWindowIcon(QtGui.QIcon("myicon.png"))
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Open dialog")
self.button.clicked.connect(self.browse)
layout.addWidget(self.button)
def browse(self):
QtCore.QTimer.singleShot(0, self.handle_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
None,
"Load Data",
".",
"*.txt",
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
def handle_timeout(self):
for w in QtWidgets.QApplication.topLevelWidgets():
if isinstance(w, QtWidgets.QFileDialog):
w.setWindowIcon(QtGui.QIcon("myicon.png"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
form = Form()
form.show()
sys.exit(app.exec_())

how to close a window in pyqt5 and terminate the program? program gets stuck

I want to create a window in pyqt5 and then close it. For some reason the program does not exit after closing the window. It gets stuck. I have been reading several related posts but none give a clear answer.
I have already tried code such as "self.object.close()", "app.quit()", even "self.object.destroy()", but all work in the same way. The only thing that really closes the window is by clicking the x (close) at the window itself. But this is not the behavior I need. I would like to close the window using my code.
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSlot, pyqtSignal
class window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(300, 300, 480, 300)
self.setWindowTitle('Hello World')
self.setWindowLayout()
def setWindowLayout(self):
self.w = QtWidgets.QWidget(self)
self.layout = QtWidgets.QHBoxLayout()
self.label = QtWidgets.QLabel('Hello World Label')
self.layout.addWidget(self.label)
self.w.setLayout(self.layout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = window()
main_window.show()
main_window.close()
sys.exit(app.exec_())
Once I close the window using
main_window.close(). I want my program to exit.
I apologize if this was resolved in a different post. I searched the answer and none solves my problem.
Thanks.
It seems to me that it is a bug since according to the docs the application should be closed if there is no top-level window but it seems that it is not verified if the closing of the window is not after the event-loop starts. A workaround is to use QTimer.singleShot(0, ...) to close the window:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(300, 300, 480, 300)
self.setWindowTitle('Hello World')
self.setWindowLayout()
def setWindowLayout(self):
self.w = QtWidgets.QWidget(self)
self.layout = QtWidgets.QHBoxLayout()
self.label = QtWidgets.QLabel('Hello World Label')
self.layout.addWidget(self.label)
self.w.setLayout(self.layout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = window()
main_window.show()
QtCore.QTimer.singleShot(0, main_window.close) # <---
sys.exit(app.exec_())

Python PySide with Qt Designer

I'm trying to make a PySide application. I've watched some tutorials to try to solve the problem but none worked and i do not have any errors in my code.
Here's the file where i'd do the scripting
main.py
import sys
from PySide import QtGui
from ui import Ui_Form
class Main(QtGui.QMainWindow):
def __init__(self):
super(QtGui.QMainWindow)
self.ui = Ui_Form()
self.ui.setupUi(self)
if __name__ == '__init__':
app = QtGui.QApplication(sys.argv)
wid = QtGui.QWidget()
wid.resize(250, 150)
wid.setWindowTitle('Simple')
wid.show()
sys.exit(app.exec_())
It has to be '__main__'
if __name__ == '__main__':
You have class Main() but you don't use it
wid = Main()
You have to execute super() in correct way
super(Main, self).__init__()
BTW: and you have wrong indentions inside class
Working example - without ui because I don't have it - but it shows window.
from PySide import QtGui
import sys
#from ui import Ui_Form
class Main(QtGui.QMainWindow):
def __init__(self):
super(Main, self).__init__()
#self.ui = Ui_Form()
#self.ui.setupUi(self)
self.resize(250, 150)
self.setWindowTitle('Simple')
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
wid = Main()
sys.exit(app.exec_())
Well i just realized that i never actually ran self.show().
Problem solved

How to show the stackwidget?

I'm trying to use the stackWidget to show different widgets .
However when I pressed the item on the listWdget , stackWidget below will not be displayed.
Here is my code,and I don't know where is wrong.
#!/usr/bin/python
# music_1.py
import sys
from PyQt4 import QtGui, QtCore
from music_ui import Ui_Form
class music(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.listWidget.insertItem(0,("Warm"))
self.ui.listWidget.insertItem(1,("Funny"))
self.ui.listWidget.insertItem(2,("Terror"))
self.ui.stackedWidget=QtGui.QStackedWidget()
warm=Warm()
funny=Funny()
terror=Terror()
self.ui.stackedWidget.addWidget(warm)
self.ui.stackedWidget.addWidget(funny)
self.ui.stackedWidget.addWidget(terror)
self.connect(self.ui.listWidget,QtCore.SIGNAL("currentRowChanged(int)"),self.ui.stackedWidget,QtCore.SLOT("setCurrentIndex(int)"))
class Warm(QtGui.QWidget):
def __init__(self,parent=None):
super(Warm,self).__init__(parent)
w1=QtGui.QPushButton("w1")
w2=QtGui.QPushButton("w2")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(w1)
buttonLayout.addWidget(w2)
class Funny(QtGui.QWidget):
def __init__(self,parent=None):
super(Funny,self).__init__(parent)
f1=QtGui.QPushButton("f1")
f2=QtGui.QPushButton("f2")
f3=QtGui.QPushButton("f3")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(f1)
buttonLayout.addWidget(f2)
buttonLayout.addWidget(f3)
class Terror(QtGui.QWidget):
def __init__(self,parent=None):
super(Terror,self).__init__(parent)
t1=QtGui.QPushButton("t1")
t2=QtGui.QPushButton("t2")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(t1)
buttonLayout.addWidget(t2)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = music()
myapp.show()
sys.exit(app.exec_())
I never worked with UI Files but this is my guess:
self.ui.stackedWidget=QtGui.QStackedWidget()
here you create a QStackedWidget which gets assigned to the class. The problem is that it is not added to the UI that is getting displayed but just to the instance of the Ui_Form. What you have to do is either:
Add the QStackedWidget in the UI Designer and erase the line above
or
Add the QStackedWidget to one of your layouts
which can be done like this:
self.ui.mySuperCoolLayout.addWidget(self.ui.stackedWidget)

PyQt4: how to make undercorated window with reserved space

I'd like to make a panel-like application using PyQt4 for Linux. for this i need the window i created:
to be undecorated
to have reserved space
to appear on all workspaces
From reading the documentation i've got the idea that i should use QtWindowFlags. But i have no clue as to how to do that. Also i believe there should be a Qt.WindowType hint somewhere telling the WM the window's a "dock" application. I have made this with pygtk following this thread, but here with Qt i don't really know how to handle this. (I need Qt for its ability to theme/skin application more easily.)
Below is the current code i made (nothing extraordinary).
import sys
from PyQt4 import QtGui
class Panel(QtGui.QWidget):
def __init__(self, parent=None): ## should the QtWindowFlag be here?
QtGui.QWidget.__init__(self, parent) ## should the QtWindowFlag be there as well?
self.setWindowTitle('QtPanel')
self.resize(QtGui.QDesktopWidget().screenGeometry().width(), 25)
self.move(0,0)
def main():
app = QtGui.QApplication(sys.argv)
panel = Panel()
panel.show()
sys.exit(app.exec_())
return 0
if __name__ == '__main__':
main()
Can anyone help me with this? Thanks :)
Read about the QWidget.windowFlags property: http://doc.qt.nokia.com/4.7/qwidget.html#windowFlags-prop
Example:
>>> from PyQt4 import QtGui, QtCore
>>> app = QtGui.QApplication([])
>>> win = QtGui.QMainWindow()
>>> win.setWindowFlags(win.windowFlags() | QtCore.Qt.FramelessWindowHint)
>>> win.show()
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
qbtn = QtGui.QPushButton('Quit', self)
#qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
qbtn.clicked.connect(self.test)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint)
self.show()
def test(self):
print "test"
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The solution is to use Python-Xlib, and it has been described in an answer on a universal way to reserve screen space on X.

Categories