问题
When Windows focus-follows-mouse-without-raising-the-window is enabled by either of the two methods linked to below, I consistently get PyQt5 GUI 'freezes' where you have to type any character in the terminal that you ran python from in order to unfreeze the GUI; complete description and test case (Windows 10, Python 3.6.1, PyQt5) is here: pyqt5 click in terminal causes GUI freeze
To enable the focus-follows-mouse-without-raise behavior, try either of these - they both work in Windows 10:
- downloadable program ('X-Mouse' though that name is used by other programs): https://joelpurra.com/projects/X-Mouse_Controls/
- registry hack description: https://sinewalker.wordpress.com/2010/03/10/ms-windows-focus-follows-mouse-registry-hacks/
So - a few questions:
- can anyone reproduce the issue? It seems 100% reproducible for me, but it would be great to hear the same from someone else.
- is there a way to change the python code to detect-and-circumvent focus-follows-mouse, or just to be immune to it, i.e. maybe by ensuring the GUI application always takes focus back again when you - for example - click in a dialog or qmessagebox owned by the main GUI window, or by some other means? (Is the object hierarchy set up optimally, and if not, maybe this could all be resolved by correcting the ownership structure?)
回答1:
The brute-force solution seems to work, though I'd like to leave this question open to see if someone knows of a more optimal solution; it took a fair amount of searching to figure out the right way; mainly by taking a look a the open-source code for X-Mouse. Basically, this method takes effect immediately, whereas the registry hack doesn't take effect until reboot.
New version of pyqt_freeze_testcase.py (the file from the referenced stackoverflow question); the changes are only additions, noted between lines of hash marks:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
####################### added begin:
import win32gui
import win32con
####################### added end
# import the UI file created with pyuic5
from minimal_ui import Ui_Dialog
class MyWindow(QDialog,Ui_Dialog):
def __init__(self,parent):
QDialog.__init__(self)
self.parent=parent
self.ui=Ui_Dialog()
self.ui.setupUi(self)
################################# added begin:
self.initialWindowTracking=False
try:
self.initialWindowTracking=win32gui.SystemParametersInfo(win32con.SPI_GETACTIVEWINDOWTRACKING)
except:
pass
if self.initialWindowTracking:
print("Window Tracking was initially enabled. Disabling it for now; will re-enable on exit.")
win32gui.SystemParametersInfo(win32con.SPI_SETACTIVEWINDOWTRACKING,False)
################################# added end
def showMsg(self):
self.really1=QMessageBox(QMessageBox.Warning,"Really?","Really do stuff?",
QMessageBox.Yes|QMessageBox.No,self,Qt.WindowTitleHint|Qt.WindowCloseButtonHint|Qt.Dialog|Qt.MSWindowsFixedSizeDialogHint|Qt.WindowStaysOnTopHint)
self.really1.show()
self.really1.raise_()
if self.really1.exec_()==QMessageBox.No:
print("nope")
return
print("yep")
################################## added begin:
def closeEvent(self,event):
if self.initialWindowTracking:
print("restoring initial window tracking behavior ("+str(self.initialWindowTracking)+")")
win32gui.SystemParametersInfo(win32con.SPI_SETACTIVEWINDOWTRACKING,self.initialWindowTracking)
################################## added end
def main():
app = QApplication(sys.argv)
w = MyWindow(app)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
来源:https://stackoverflow.com/questions/44838462/pyqt5-gui-freeze-caused-by-windows-focus-follows-mouse