【问题标题】:How to get the right table row index in pyQt5 contextMenuEvent如何在pyQt5 contextMenuEvent中获取正确的表行索引
【发布时间】:2019-10-06 03:09:31
【问题描述】:

我需要在 pyQt5 中的 contextMenuEvent 期间获取表行索引,但我不断得到奇怪的行偏移量。由于这是我的第一个 pyQt 项目,我很迷茫。我有以下代码。

def contextMenuEvent(self, event):

    menu = QMenu(self)
    openAction = menu.addAction('Open in browser')
    action = menu.exec_(event.globalPos())

    if action == openAction:
        row = self.tableWidget.rowAt(event.y())  # Should this be event.globalY? 
        self.so_something(row)

编辑:添加代码示例。您可以看到,当执行到右键单击一行时产生的事件时,打印的数字不是正确的行号。通常它有一个偏移量,最后一行产生-1。

import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel, QLineEdit, QWidget, \
                            QPushButton, QVBoxLayout, QHBoxLayout, QComboBox, \
                            QTableWidget, QHeaderView, QTableWidgetItem, \
                            QMenu, QApplication


class MainWindow(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Window size and title
        self.setWindowTitle('Test')
        self.resize(700, 700)
        self.setMinimumWidth(700)

        # Label
        addressLabel = QLabel('Testing')
        addressLabel.setAlignment(Qt.AlignCenter)

        # Dropdown
        self.addressDropdown = QComboBox(self)
        self.addressDropdown.addItem('A')
        self.addressDropdown.addItem('B')

        # Refresh button
        refreshButton = QPushButton()
        refreshButton.setMaximumSize(40, 40)

        # Address layout
        addressayout = QHBoxLayout()
        addressayout.addWidget(addressLabel, 1)
        addressayout.addWidget(self.addressDropdown, 7)
        addressayout.addWidget(refreshButton)

        # Balance label
        balaceLabel = QLabel()
        balaceLabel.setText('Testing')
        balaceLabel.setAlignment(Qt.AlignCenter)

        # Balance amount label
        self.balaceAmountLabel = QLabel()
        self.balaceAmountLabel.setText('Testing')
        self.balaceAmountLabel.setAlignment(Qt.AlignCenter)

        # Balance layout
        balanceLayout = QVBoxLayout()
        balanceLayout.addWidget(balaceLabel)
        balanceLayout.addWidget(self.balaceAmountLabel)

        # Transactions label
        transactionsLabel = QLabel('Testing')
        transactionsLabel.setAlignment(Qt.AlignCenter)

        # Transactions table
        self.tableWidget = QTableWidget()
        self.tableWidget.setRowCount(10)
        self.tableWidget.setColumnCount(1)
        self.tableWidget.verticalHeader().setVisible(False)
        self.tableWidget.horizontalHeader().setVisible(False)
        self.tableWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        item = QTableWidgetItem('Testing')
        item.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
        self.tableWidget.setItem(0, 0, item)

        # Transactions layout
        transactionsLayout = QVBoxLayout()
        transactionsLayout.addWidget(transactionsLabel)
        transactionsLayout.addWidget(self.tableWidget)

        # Send label A
        sendLabelA = QLabel('Send')
        sendLabelA.setAlignment(Qt.AlignCenter)

        # Send amount
        self.sendAmount = QLineEdit()
        self.sendAmount.setAlignment(Qt.AlignCenter)

        # Send label B
        sendLabelB = QLabel('to')
        sendLabelB.setAlignment(Qt.AlignCenter)

        # Send address
        self.sendAddress = QLineEdit()
        self.sendAddress.setAlignment(Qt.AlignCenter)

        # Send button
        sendButton = QPushButton()
        sendButton.setMaximumSize(40, 40)
        sendIcon = QIcon.fromTheme("mail-send")
        sendButton.setIcon(sendIcon)
        sendButton.setIconSize(QSize(24,24))

        # Send layout
        sendLayout = QHBoxLayout()
        sendLayout.addWidget(sendLabelA)
        sendLayout.addWidget(self.sendAmount, 2)
        sendLayout.addWidget(sendLabelB)
        sendLayout.addWidget(self.sendAddress, 4)
        sendLayout.addWidget(sendButton)

        # Window layout
        layout = QVBoxLayout()
        layout.addLayout(addressayout)
        layout.addLayout(balanceLayout)
        layout.addLayout(transactionsLayout)
        layout.addLayout(sendLayout)
        self.setLayout(layout)

    def contextMenuEvent(self, event):
        menu = QMenu(self)
        openAction = menu.addAction('Open in browser')
        action = menu.exec_(event.globalPos())
        row = self.tableWidget.rowAt(event.y())

        if action == openAction:
            print(row)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec_()

【问题讨论】:

    标签: python python-3.x pyqt pyqt5


    【解决方案1】:

    rowAt() 方法所需的坐标必须是相对于 QTableWidget 的视口的,因此您必须使用mapFromGlobal() 方法将全局位置转换为本地位置:

    def contextMenuEvent(self, event):
        gp = event.globalPos()
        menu = QMenu(self)
        openAction = menu.addAction("Open in browser")
        action = menu.exec_(gp)
        vp_pos = self.tableWidget.viewport().mapFromGlobal(gp)
        row = self.tableWidget.rowAt(vp_pos.y())
    
        if action == openAction:
            print(row)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      相关资源
      最近更新 更多