如何让 QT 弹出窗口在点击外部时关闭?

问题描述 投票:0回答:1

当我打开 PySide6/Qt6 弹出窗口时,用户无法单击弹出窗口外部来关闭它。我发现的唯一方法是按 ESC、单击窗口标题栏或切换到不同的应用程序,恕我直言,这不是很直观且用户友好。 有没有办法通过单击弹出窗口外部来关闭它? 或者我是否需要使用不同的标志、组件或其他东西?

目标是拥有一个文本输入字段,在用户键入时显示一些搜索结果。

我在 python 中做了一个小测试实现,其中通过单击按钮打开弹出窗口,以显示仅当用户按 ESC、单击窗口标题栏或切换到不同的应用程序时弹出窗口如何关闭。

我尝试了 PySide6,如下所示,但也尝试了 Qt6,结果相同。

from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QListView, QVBoxLayout, QWidget, QDialog
from PySide6.QtCore import Qt, QStringListModel
import sys


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Button Example")
        self.setGeometry(100, 100, 600, 600)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        button = QPushButton("Open List View")
        button.clicked.connect(self.show_popup)
        layout.addWidget(button)


    def show_popup(self):
        dialog = QDialog(self)
        dialog.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Popup)
        dialog.setWindowTitle("List View Popup")
        dialog.setModal(True)
        dialog.resize(300, 400)

        layout = QVBoxLayout()
        list_view = QListView()
        
        model = QStringListModel()
        model.setStringList(["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"])
        list_view.setModel(model)
        
        layout.addWidget(list_view)
        dialog.setLayout(layout)
        dialog.show()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
pyside6 qt6
1个回答
0
投票

这是创建一个更像菜单的小部件的更复杂的方法,该小部件在执行后关闭,并且如果存在的项目多于菜单允许的可见区域,则滚动。

from PySide6.QtWidgets import (QApplication, QMainWindow, QPushButton, QListView,
                               QVBoxLayout, QWidget, QDialog, QMenu, QListWidget,
                               QListWidgetItem, QScrollArea, QWidgetAction)
from PySide6.QtCore import Qt, QStringListModel
from PySide6.QtGui import QCursor
import sys


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Button Example")
        self.setGeometry(100, 100, 600, 600)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        button = QPushButton("Open List View")
        button.clicked.connect(self.show_popup)
        layout.addWidget(button)

    def show_popup(self):
        items = [f"Item {i + 1}" for i in range(30)]
        menu = self.get_menu(items)
        menu.exec(QCursor.pos())

    def get_menu(self, items):
        menu = QMenu(self)

        list_widget = QListWidget()  # Create a QListWidget for scrollable content
        for idx, name in enumerate(items):
            item = QListWidgetItem(name)
            list_widget.addItem(item)
            item.setData(Qt.UserRole, name)  # Store the name in the item

        def handle_item_click(clicked_item):
            """Handle the item click event."""
            track_name = clicked_item.data(Qt.UserRole)
            print(track_name)
            menu.close()

        container_widget = QWidget()  # Create a container widget
        layout = QVBoxLayout(container_widget)
        layout.setContentsMargins(0, 0, 0, 0)

        list_widget.itemClicked.connect(handle_item_click)
        layout.addWidget(list_widget)

        scroll_area = QScrollArea()  # Set up the scroll area
        scroll_area.setWidgetResizable(True)
        scroll_area.setWidget(container_widget)

        scroll_menu_action = QWidgetAction(menu)
        scroll_menu_action.setDefaultWidget(scroll_area)
        menu.addAction(scroll_menu_action)

        return menu


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
© www.soinside.com 2019 - 2024. All rights reserved.