[Python] Display floating popup widget box on the header of a QTableView with Python and PyQt6

Discussão em 'Python' iniciado por Stack, Maio 25, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to make a QTableView with Python and PyQt6 that display a popup message and posibly some tools, like filters, when you click in a header section.

    I'm trying to replace an excel spreadsheet where I'm using autofilters and commentaries and I'm triyng to replicate in a python script.

    I used copilot to generate some basic code that ilustrate my goal:

    from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView, QWidget, QLabel, QVBoxLayout
    from PyQt6.QtCore import Qt, QAbstractTableModel, QPoint, QTimer

    class MyTableModel(QAbstractTableModel):
    def __init__(self, data):
    super().__init__()
    self.data = data

    def rowCount(self, index):
    return len(self.data)

    def columnCount(self, index):
    return len(self.data[0])

    def data(self, index, role):
    if role == Qt.ItemDataRole.DisplayRole:
    return self.data[index.row()][index.column()]

    class FloatingFrame(QWidget):
    def __init__(self):
    super().__init__()
    self.setWindowFlags(Qt.WindowType.Tool | Qt.WindowType.FramelessWindowHint) # Makes it a floating, frameless window
    self.setWindowState(Qt.WindowState.WindowActive)
    self.setStyleSheet("background-color: lightgray; border: 1px solid black;")
    self.setFixedSize(300, 200)
    self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
    self.active = False

    def focusOutEvent(self, event):
    QTimer.singleShot(500, self.close) # Close the window when it loses focus
    super().focusOutEvent(event)

    def close(self):
    self.active = False
    return super().close()

    class MyWindow(QMainWindow):
    def __init__(self):
    super().__init__()
    self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
    self.table = QTableView(self)
    self.table.horizontalHeader()
    self.setCentralWidget(self.table)

    data = [["Apple", "Red"], ["Banana", "Yellow"], ["Cherry", "Red"], ["Grape", "Purple"]]
    self.model = MyTableModel(data)
    self.table.setModel(self.model)

    header = self.table.horizontalHeader()
    header.sectionClicked.connect(self.show_filter_menu)
    self.floating_frame = FloatingFrame()

    def show_filter_menu(self, logicalIndex):
    geom = self.table.horizontalHeader().geometry()
    ypos = geom.bottomLeft().y()
    xpos = self.table.horizontalHeader().sectionViewportPosition(logicalIndex)
    point = QPoint()
    point.setX(xpos +15)
    point.setY(ypos)
    point = self.mapToGlobal(point)
    width = self.table.horizontalHeader().sectionSize(logicalIndex)
    height = self.table.horizontalHeader().size().height()

    if not self.floating_frame.active:
    self.floating_frame = FloatingFrame()
    self.floating_frame.active = True
    self.floating_frame.setFixedSize(width, height*3)
    self.floating_frame.move(point.x(), point.y())

    layout = QVBoxLayout()
    layout.setContentsMargins(0,0,0,0)
    label = QLabel("Extra info on Column " + str(logicalIndex))
    label.setWordWrap(True)
    label.setAlignment(Qt.AlignmentFlag.AlignLeft)
    layout.addWidget(label)

    self.floating_frame.setLayout(layout)
    self.floating_frame.show()
    self.floating_frame.setFocus()

    app = QApplication([])
    window = MyWindow()
    window.show()
    app.exec()


    It works. But I think is not the correct way to make a popup message.

    Continue reading...

Compartilhe esta Página