Не могу переопределить event переключения фокуса между QMainWindow и любым другим приложением PyQt6
Есть такой класс на QWidget
, который должен открываться именно не как второе окно, поэтому использую Qt.WindowType.Popup
.
Все работает корректно до нажатия мимо окна приложения. Event
сообщает,
что было совершено нажатие мимо окна приложения, но при смене фокуса на другое приложение или рабочий стол, мой виджет закрывается, чего мне не нужно. Поэтому пытался переопределить event
смены фокуса, но
print("The focus is lost, but the window remains open.")
вовсе не срабатывает.
class AddFriendWidget(QWidget):
def __init__(self, main_window):
super().__init__()
self.main_window = main_window
self.init_ui()
def init_ui(self):
# Layout and widgets
self.setFixedSize(300, 150)
add_friend_layout = QVBoxLayout(self)
self.info_label = QLabel("Enter friend's username:")
add_friend_layout.addWidget(self.info_label)
self.friend_input = QLineEdit()
self.friend_input.setPlaceholderText("Friend's username")
add_friend_layout.addWidget(self.friend_input)
self.add_button = QPushButton("Add Friend")
self.add_button.clicked.connect(self.add_friend)
add_friend_layout.addWidget(self.add_button)
self.cancel_button = QPushButton("Cancel")
self.cancel_button.clicked.connect(self.close) # Закрываем виджет
add_friend_layout.addWidget(self.cancel_button)
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Popup)
self.installEventFilter(self)
return self
def add_friend(self):
"""Handle adding friend logic here."""
friend_name = self.friend_input.text().strip()
if friend_name:
print(f"Friend '{friend_name}' added.")
else:
self.info_label.setText("Please enter a valid username.")
def eventFilter(self, source, event):
if event.type() == QEvent.Type.MouseButtonPress:
global_pos = event.globalPosition().toPoint() # Получаем координаты клика в глобальном пространстве
if not self.main_window.geometry().contains(global_pos):
print("Clicked OUTSIDE the entire application!")
elif not self.geometry().contains(global_pos):
print("Clicked outside the widget, but inside the main window.")
else:
print("Clicked inside the widget!")
print(self.isVisible())
return True
# Проверяем, является ли событие фокусировки QFocusEvent, прежде чем обращаться к `reason()`
if event.type() == QEvent.Type.FocusOut and isinstance(event, QEvent.FocusOut):
if event.reason() == Qt.FocusReason.ActiveWindowFocusReason:
print("The focus is lost, but the window remains open.")
event.ignore()
return True
return super().eventFilter(source, event)
Ответы (1 шт):
Вы не предоставили минимально-воспроизводимый пример.
Я не уверен, что правильно понял вас, но мне кажется, что вам достаточно
- void QWidget::mousePressEvent(QMouseEvent *event)
и
- void QApplication::focusChanged(QWidget *old, QWidget *now)
чтобы выполнить задуманное.
Поменяйте импорты на PyQt6 и попробуйте.
import sys
from PyQt5.Qt import *
class AddFriendWidget(QFrame): # QWidget QFrame
def __init__(self, i, main_window=None):
super(AddFriendWidget, self).__init__(main_window)
self.i = i + 1
self.main_window = main_window
self.setObjectName('friendwidget')
self.init_ui()
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 0, 10, 10)
layout.addWidget(self.qgroupbox)
def init_ui(self):
self.qgroupbox = QGroupBox(f'Widget_{self.i}', self)
# Layout and widgets
self.setFixedSize(300, 150)
add_friend_layout = QVBoxLayout(self.qgroupbox)
self.info_label = QLabel("Enter friend's username:")
add_friend_layout.addWidget(self.info_label)
self.friend_input = QLineEdit()
self.friend_input.setPlaceholderText("Friend's username")
add_friend_layout.addWidget(self.friend_input)
self.add_button = QPushButton("Add Friend")
self.add_button.clicked.connect(self.add_friend)
add_friend_layout.addWidget(self.add_button)
self.cancel_button = QPushButton("Cancel")
self.cancel_button.clicked.connect(self.close) #Закрываем виджет
add_friend_layout.addWidget(self.cancel_button)
#? self.setWindowFlags(
#? Qt.WindowType.FramelessWindowHint | Qt.WindowType.Popup)
#? self.installEventFilter(self)
#? return self
# +++
def mousePressEvent(self, event): # +++
#print(f"Clicked внутри виджета ->`Widget_{self.i}`")
self.main_window.statusBar().showMessage(
f"Clicked внутри виджета ->`Widget_{self.i}`")
def add_friend(self):
""" Handle adding friend logic here. """
friend_name = self.friend_input.text().strip()
if friend_name:
self.info_label.setText(friend_name)
else:
self.info_label.setText("Please enter a valid username.")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.i = 0
self.scrollArea = QScrollArea(widgetResizable=True) # +++
self.setCentralWidget(self.scrollArea)
self.content_widget = QWidget()
self.scrollArea.setWidget(self.content_widget)
self.add_button_widget = QPushButton("Add Widget")
self.add_button_widget.clicked.connect(self.add_widget)
self.layout = QVBoxLayout(self.content_widget)
self.layout.addWidget(self.add_button_widget,
alignment=Qt.AlignBottom)
self.setFocus()
app.focusChanged.connect(self.onFocusChanged)
self.statusBar().showMessage("bla-bla bla")
def add_widget(self):
addFriendWidget = AddFriendWidget(self.i, self)
self.layout.insertWidget(self.i, addFriendWidget)
self.i += 1
self.window().statusBar().showMessage(
f"Создали виджет `Widget_{self.i}`!")
def mousePressEvent(self, event):
#print(f"Нажал за пределы виджетов, но внутри главного окна.")
self.statusBar().showMessage("Нажал за пределы виджетов, но внутри главного окна.")
def onFocusChanged(self):
if not self.isActiveWindow():
#print(f'Щелкнул за пределы всего приложения!')
self.statusBar().showMessage(
"Щелкнул за пределы всего приложения!")
else:
self.statusBar().showMessage(
"Окно в фокусе, делайте что-нибудь!")
QSS = '''
#friendwidget {
background-color: #8EDEB1;
}
QGroupBox {
background-color: white;
border: 2px solid #f00;
border-radius: 10px;
margin-top: 12px;
font-size: 18px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center;
color: #f00;
}
'''
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(QSS)
window = MainWindow()
window.resize(320, 550)
window.show()
sys.exit(app.exec())