Very creative solution (though it's not so nice that such a workaround
needs to be put in place). I'm able to implement it successfully in the
manner below. I just disabled the entire parent window (repainting it to
get around a separate bug: https://bugreports.qt.io/browse/PYSIDE-695),
enabled the dialog window (which was disabled automatically when its parent
was disabled), threw in a Qt.WindowStaysOnTopHint window flag, and
connected the dialog window's close to enable the parent window. This has
almost the same effect as making the dialog modal (the only difference I
can discern is that the parent window is grayed out), but the PyQtGraph
object's context menu is accessible.
Thanks! Solution below.
Efrem Braun
```
import sys
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
import pyqtgraph as pg
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
b = QPushButton()
b.setText("Open dialog")
self.setCentralWidget(b)
b.clicked.connect(self.showdialog)
def showdialog(self):
self.d = CustomDialog(self)
# # not modal
# self.d.setWindowModality(Qt.NonModal)
# self.d.show()
# # location can't be moved
# self.d.setWindowModality(Qt.WindowModal)
# self.d.exec_()
# # blocks context menu
# self.d.setWindowModality(Qt.ApplicationModal)
# self.d.exec_()
if sys.platform == 'darwin':
self.setEnabled(False)
self.repaint()
self.d.setEnabled(True)
self.d.setWindowFlag(Qt.WindowStaysOnTopHint)
self.d.finished.connect(lambda: self.setEnabled(True))
self.d.show() # This dialog is not modal (though we make it
modal manually).
else:
self.d.exec_() # This dialog is modal.
class CustomDialog(QDialog):
def __init__(self, *args, **kwargs):
super(CustomDialog, self).__init__(*args, **kwargs)
buttons = QDialogButtonBox.Cancel
self.buttonBox = QDialogButtonBox(buttons)
self.buttonBox.rejected.connect(self.reject)
self.layout = QVBoxLayout()
self.layout.addWidget(pg.PlotWidget(self))
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
```
On Tuesday, February 9, 2021 at 11:25:19 PM UTC-5 Patrick wrote:
> Hi,
>
> I think the odd behaviour you describe is because MacOS attaches modal
> windows to their parent. On Linux this is an option which can be toggled,
> say in gnome tweak tools. In any case, I think I've got around this in the
> past by manually disabling the UI widgets I don't want the user to interact
> with. This involves a bunch of "somewidget.setEnabled(False)" lines before
> showing the (non-modal) dialog, and hooking the dialog close() to re-enable
> widgets once the dialog is hidden. This can be somewhat simplified if you
> place widgets inside groupboxes/frames/etc, so you can just disable a
> couple of frames which also disables all containing widgets.
> I can't actually find an example of this right now, but I'm pretty sure it
> worked OK.
>
> Patrick
>
> On Wednesday, 10 February 2021 at 4:05:20 am UTC+10:30 [email protected]
> wrote:
>
>> Sorry, that is not a valid solution. That makes the dialog box modeless;
>> it's the same as doing `self.d.setWindowModality(Qt.NonModal)`. The user
>> can then access the MainWindow dialog, which I don't want.
>>
>> Any suggestions?
>>
>> On Tuesday, February 9, 2021 at 12:14:32 PM UTC-5 Efrem Braun wrote:
>>
>>> Solution:
>>>
>>> Replace:
>>> `self.d = CustomDialog(self)`
>>> with:
>>> `self.d = CustomDialog()`
>>>
>>> Then, using Qt.WindowModal won't anchor the dialog to its parent window,
>>> since it doesn't have a parent window.
>>>
>>> Efrem Braun
>>>
>>> On Tuesday, February 9, 2021 at 11:09:28 AM UTC-5 Efrem Braun wrote:
>>>
>>>> Update:
>>>>
>>>> Apparently the pyqtgraph context menu only gets blocked on a Mac. When
>>>> I run the working example using `Qt.ApplicationModal` on my Ubuntu OS, I
>>>> can access the context menu. Still trying to figure out how to fix this
>>>> issue on a Mac...
>>>>
>>>> Efrem Braun
>>>>
>>>> On Monday, February 8, 2021 at 11:56:14 PM UTC-5 Efrem Braun wrote:
>>>>
>>>>> I have an application which has a pyqtgraph instance in a dialog box.
>>>>> I want this dialog box to be modal (I don't want the user to be able to
>>>>> interact with the main window while the dialog box is open), so normally
>>>>> I
>>>>> would set `setWindowModality()` to `Qt.ApplicationModal`. However, this
>>>>> blocks the pyqtgraph's context menu from being accessible (I can right
>>>>> click on the pyqtgraph instance, and it shows me the context menu, but
>>>>> I'm
>>>>> not allowed to click on it).
>>>>>
>>>>> I tried instead to set `setWindowModality()` to `Qt.WindowModal`.
>>>>> However, this locks the dialog box to the main window, which I don't like
>>>>> (I want the user to be able to see the main window while interacting with
>>>>> the dialog box).
>>>>>
>>>>> Is there anyway to either:
>>>>> 1. Use `setWindowModality(Qt.ApplicationModal)` but not block the
>>>>> pyqtgraph context menu?
>>>>> or
>>>>> 2. Use `setWindowModality(Qt.WindowModal)` but be able to undock the
>>>>> dialog box?
>>>>>
>>>>> A minimal working example showing the behavior is below. You can see
>>>>> the 3 behaviors that result when setting the window modality to
>>>>> Qt.ApplicationModal, Qt.WindowModal, and Qt.NonModal.
>>>>>
>>>>> ```
>>>>> from PySide2.QtWidgets import *
>>>>> from PySide2.QtGui import *
>>>>> from PySide2.QtCore import *
>>>>>
>>>>> import pyqtgraph as pg
>>>>>
>>>>> class MainWindow(QMainWindow):
>>>>> def __init__(self, *args, **kwargs):
>>>>> super(MainWindow, self).__init__(*args, **kwargs)
>>>>> b = QPushButton()
>>>>> b.setText("Open dialog")
>>>>> self.setCentralWidget(b)
>>>>> b.clicked.connect(self.showdialog)
>>>>>
>>>>> def showdialog(self):
>>>>> self.d = CustomDialog(self)
>>>>>
>>>>> # # not modal
>>>>> # self.d.setWindowModality(Qt.NonModal)
>>>>> # self.d.show()
>>>>>
>>>>> # location can't be moved
>>>>> self.d.setWindowModality(Qt.WindowModal)
>>>>> self.d.exec_()
>>>>>
>>>>> # # blocks context menu
>>>>> # self.d.setWindowModality(Qt.ApplicationModal)
>>>>> # self.d.exec_()
>>>>>
>>>>>
>>>>> class CustomDialog(QDialog):
>>>>> def __init__(self, *args, **kwargs):
>>>>> super(CustomDialog, self).__init__(*args, **kwargs)
>>>>>
>>>>> buttons = QDialogButtonBox.Cancel
>>>>> self.buttonBox = QDialogButtonBox(buttons)
>>>>> self.buttonBox.rejected.connect(self.reject)
>>>>> self.layout = QVBoxLayout()
>>>>> self.layout.addWidget(pg.PlotWidget(self))
>>>>> self.layout.addWidget(self.buttonBox)
>>>>> self.setLayout(self.layout)
>>>>>
>>>>>
>>>>> if __name__ == '__main__':
>>>>> app = QApplication(sys.argv)
>>>>> window = MainWindow()
>>>>> window.show()
>>>>> sys.exit(app.exec_())
>>>>> ```
>>>>>
>>>>> Thank you.
>>>>>
>>>>> Efrem Braun
>>>>>
>>>>
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/72ede9fb-b012-4564-b7df-4c01d1189a40n%40googlegroups.com.