1

Currently I'm having trouble with the focus of tabified QDockWidgets. Working with this small example using two tabified QDockWidgets:

from PyQt5.QtWidgets import QApplication, QMainWindow, QDockWidget, QTextEdit
from PyQt5.Qt import Qt

app = QApplication( [] )
main = QMainWindow(None, Qt.Window)
main.show()

dock1 = QDockWidget( "D1", main )
dock1.setWidget( QTextEdit( dock1 ) )
main.addDockWidget( Qt.TopDockWidgetArea, dock1 )

dock2 = QDockWidget( "D2", main )
dock2.setWidget( QTextEdit( dock2 ) )
main.tabifyDockWidget( dock1, dock2 )

exit( app.exec() )

I experienced that the QTextEdits are not losing focus when switching to an other tab of the tabified widgets.

  1. write Text in one of the fields
  2. click on the other Tab on the QTabBar
  3. continue with your keyboard-input

The second text you were writen was still in focus of the first Widget.


So, in general:
Is there a way to lose the focus of the tabified widgets, regardless if it is a QTextEdit or some other Widget(s) (maybe even with a complex child-layout structure)?

I tried clearFocus() on the QDockWidget, but this just seems to work if the QDockWidget itselfe is containing the focus (not it's child).
Using setFocus() before also doesn't seems like a good option, because the widget (or it's childs) might doesn't contain the focus in every case. So it would be unappropriate to might steal it from some other widget.


I think the best anchors to react on would be:

and if you would somehow locate the dynamicly create QTabBar:

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Skandix
  • 1,916
  • 6
  • 27
  • 36

1 Answers1

1

One quite simple way to do this is to check to see if the current focus widget is a descendant of a QDockWidget whenever the tab changes, and then reset the focus if necessary:

from PyQt5.QtWidgets import QApplication, QMainWindow, QDockWidget, QTextEdit
from PyQt5.QtCore import Qt

class DockWidget(QDockWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWidget(QTextEdit(self))
        self.visibilityChanged.connect(self.updateFocus)

    def updateFocus(self, visible):
        if visible:
            widget = QApplication.instance().focusWidget()
            while widget is not None:
                if isinstance(widget, QDockWidget):
                    widget = None
                elif widget.parentWidget() is not None:
                    widget = widget.parentWidget()
                else:
                    break
            if widget is None:
                self.setFocus()
                self.focusNextChild()

app = QApplication([''])
main = QMainWindow()
main.setCentralWidget(QTextEdit(main))

dock1 = DockWidget("D1", main)
main.addDockWidget(Qt.TopDockWidgetArea, dock1)

dock2 = DockWidget("D2", main)
main.tabifyDockWidget(dock1, dock2)

main.show()
app.exec()
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • 1
    ok, found one little edge-case: have two groups of tabified dockwidgets, then it migth steal the focus away from the other group. Fix: in line `if isinstance(widget, QDockWidget):` add `and self in widget.parent().tabifiedDockWidgets(widget):`. This checks if the focused QDockWidget is tabified with the currently selected one. – Skandix May 03 '18 at 12:05