4

I have a PyQt4 program where I'm trying to get notified when a window gets focus, following the advice in the QUndoGroup docs:

It is the programmer's responsibility to specify which stack is active by calling QUndoStack::setActive(), usually when the associated document window receives focus.

But I have a weird problem where only one window actually gets the focusIn and focusOut events, while the others either receive only one at their creation, or else never receive them at all. Here is an example program:



    #!/usr/bin/env python
    
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    import sys
    
    class MyWindow(QMainWindow):
        def __init__(self):
            super(MyWindow, self).__init__()
            self.label = QLabel('Window')
            self.setCentralWidget(self.label)
            self.setFocusPolicy(Qt.StrongFocus)
    
        def focusInEvent(self, event):
            self.label.setText('Got focus')
    
        def focusOutEvent(self, event):
            self.label.setText('Lost focus')
    
    def main():
        app = QApplication(sys.argv)
        win1 = MyWindow()
        win2 = MyWindow()
        win1.show()
        win2.show()
        sys.exit(app.exec_())
    
    if __name__ == '__main__':
        main()

Community
  • 1
  • 1
J.C.
  • 208
  • 1
  • 2
  • 5
  • Works here, but this depends on how your window manager handles keyboard focus. Simply moving the mouse over one or the other won't necessarily give it keyboard focus. Clicking inside usually does. Whether or not keyboard focus is lost on mouse out depends on the window manager. – Mat Sep 11 '11 at 09:52
  • 1
    Narrowed this down a bit. I don't know why I didn't notice this before, but this does work when you click inside the window, but not when you click the window title bar or when you alt tab to the windows. Then it works like described where one window correctly receives all the events and the other receives none. – J.C. Sep 11 '11 at 19:24

1 Answers1

9

I'm actually not quite sure why it doesn't work, might be an issue in how qt handles focus transition between windows. Anyways, below is how you might fix this, I've changed your code a bit

from PyQt4.QtCore import *
from PyQt4.QtGui import *

import sys

class MyWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__()
        self.label = QLabel('Window')
        self.setCentralWidget(self.label)
        self.setFocusPolicy(Qt.StrongFocus)

    def focusInEvent(self, event):
        self.label.setText('Got focus')

    def focusOutEvent(self, event):
        self.label.setText('Lost focus')

def changedFocusSlot(old, now):
    if (now==None and QApplication.activeWindow()!=None):
        print "set focus to the active window"
        QApplication.activeWindow().setFocus()

def main():
    app = QApplication(sys.argv)
    QObject.connect(app, SIGNAL("focusChanged(QWidget *, QWidget *)"), changedFocusSlot)

    win1 = MyWindow()
    win2 = MyWindow()
    win1.show()
    win2.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main() 

hope this helps, regards

serge_gubenko
  • 20,186
  • 2
  • 61
  • 64