我需要在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_()
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)