如何在pyQt5 contextMenuEvent中获得正确的表行索引

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

我需要在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个回答
0
投票

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)
© www.soinside.com 2019 - 2024. All rights reserved.