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.

Reply via email to