Issue
I have a main window that's a normal window (not set on top or anything). There's an option in one of the menus that opens a secondary window (again a regular window) that has a text field where I need to display the filename I get from a file dialog. My problem is that when the file dialog is opened, the secondary window gets hidden behind the main window. I've tried to pin this secondary window on top, but then it gets on top of the file dialog as well. Since my application is big, I've provided code that has the same behavior and shares the same problem. I'm using Python 3.10, PyQt5 on Windows 11.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget, QVBoxLayout, QFileDialog, QLabel
app = QApplication(sys.argv)
app.setStyle('Fusion')
class SecondWindow(QWidget):
def __init__(self):
super().__init__()
self.a_button = QPushButton('Press for file dialog')
mylabel = QLabel("I'll be hidden behind main window")
layout = QVBoxLayout()
layout.addWidget(self.a_button)
layout.addWidget(mylabel)
self.setLayout(layout)
# self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
button = QPushButton("Open")
button.clicked.connect(self.my_window)
self.setCentralWidget(button)
self.win2 = SecondWindow()
self.win2.a_button.clicked.connect(self.open_select)
def open_select(self):
options = QFileDialog.Options()
# options |= QtWidgets.QFileDialog.DontUseNativeDialog
fileName, _ = QFileDialog.getSaveFileName(self,
"New",
"",
"QText(*.qtext)",
options=options)
if not fileName:
return
def my_window(self):
if self.win2.isVisible():
self.win2.hide()
else:
self.win2.show()
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
Solution
In any case, the self
argument of widgets represents the parent widget, which, for dialogs, indicates the window for which the dialog is modal. Since you're using self
, and open_select
is a member of MainWindow
, the result is that you're making it modal to that.
The easy solution would be to change that to the actual window:
QFileDialog.getSaveFileName(self.win2, ...)
In reality, that open_select
should theoretically be part of the SecondWindow
class, at least from the perspective of object structure; this would automatically make the modality work as expected (since in that case self
will be the instance of SecondWindow
):
fileName, _ = QFileDialog.getSaveFileName(self.sender(), ...)
If, for some reason, you mean to use that common function across different window classes, the possible solutions could be:
- use
self.sender()
as the parent; while the sender would be the button, the modality will automatically look up for the top level widget; - send the actual parent window with a further argument, either using a lambda or a custom signal:
def open_select(self, parent):
fileName, _ = QFileDialog.getSaveFileName(parent, ...)
Then, with a direct lambda:
self.win2.a_button.clicked.connect(lambda: self.open_select(self.win2))
Or a custom signal:
class SecondWindow(QWidget):
selectFile = pyqtSignal(object)
def __init__(self):
# ...
self.a_button.clicked.connect(lambda: self.selectFile.emit(self))
class MainWindow(QMainWindow):
def __init__(self):
# ...
self.win2.selectFile.connect(self.open_select)
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.