python - 如何通过右键单击 QTableView 获取行号?

标签 python position contextmenu pyqt5 qtableview

我正在使用 PyQt5 开发一个应用程序,但不知道如何将 QTableView 上右键单击的位置转换为行号。我实现它的方式是通过在 QPoint 光标位置上使用 rowAt 方法,我得到的行号看起来与实际行号有一个偏移量。点击。我一直在四处寻找,但找不到任何明确的解决方案。听起来好像与滚动区域有关。我的代码示例如下。

使用Qt Designer生成的UI代码:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowModality(QtCore.Qt.NonModal)
        MainWindow.resize(941, 767)
        MainWindow.setMinimumSize(QtCore.QSize(922, 767))
        MainWindow.setMaximumSize(QtCore.QSize(1900, 1200))
        MainWindow.setAutoFillBackground(False)
        MainWindow.setAnimated(False)
        self.MyWindows = QtWidgets.QWidget(MainWindow)
        self.MyWindows.setEnabled(True)
        self.MyWindows.setMinimumSize(QtCore.QSize(921, 726))
        self.MyWindows.setMaximumSize(QtCore.QSize(1900, 1200))
        self.MyWindows.setObjectName("MyWindows")
        self.layoutWidget = QtWidgets.QWidget(self.MyWindows)
        self.layoutWidget.setGeometry(QtCore.QRect(10, 0, 911, 441))
        self.layoutWidget.setObjectName("layoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.tableView = QtWidgets.QTableView(self.layoutWidget)
        self.tableView.setEnabled(True)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth())
        self.tableView.setSizePolicy(sizePolicy)
        self.tableView.setMinimumSize(QtCore.QSize(900, 400))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.tableView.setFont(font)
        self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        self.tableView.setAlternatingRowColors(True)
        self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.tableView.setGridStyle(QtCore.Qt.NoPen)
        self.tableView.setSortingEnabled(False)
        self.tableView.setObjectName("tableView")
        self.tableView.horizontalHeader().setCascadingSectionResizes(True)
        self.tableView.horizontalHeader().setSortIndicatorShown(False)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.verticalHeader().setVisible(True)
        self.tableView.verticalHeader().setCascadingSectionResizes(True)
        self.tableView.verticalHeader().setHighlightSections(True)
        self.tableView.verticalHeader().setSortIndicatorShown(False)
        self.tableView.verticalHeader().setStretchLastSection(True)
        self.gridLayout.addWidget(self.tableView, 1, 1, 1, 1)
        MainWindow.setCentralWidget(self.MyWindows)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Thib Imave Smoother V0.2"))

主要代码:

from PyQt5.QtCore import *
from PyQt5.QtWidgets import QMainWindow, QSizePolicy, QHeaderView, QFileSystemModel, QMenu, QAction
# QtDesigner generated code imports
from UI import *

class ShowTableView:

    def __init__(self, guiObject):
        self._gui = guiObject  # store QWidget from Gui class
        #initialize fake data for testing
        self.my_data = [["test" for x in range(7)] for x in range(5000)]
        self.tm = MyTableModel(self.my_data)
        self._gui.tableView.setModel(self.tm)
        header = self._gui.tableView.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeToContents)  # have columns width adjusted to content

class MyTableModel(QAbstractTableModel):
    def __init__(self, my_data, parent=None, *args):
        QAbstractTableModel.__init__(self, parent)
        self.my_data = my_data
        self.title_list = ["on","two","three","four","five","six","seven"]

    def rowCount(self, parent):
        return len(self.my_data)

    def columnCount(self, parent):
        return len(self.my_data[0])

    def data(self, index, role):
        if not index.isValid():
            return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()
        else: #
            return QVariant(self.my_data[index.row()][index.column()])

    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return QVariant(self.title_list[col])
        elif orientation == Qt.Vertical and role == Qt.DisplayRole:
            return QVariant(col + 1)

class Gui(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Gui, self).__init__(parent)
        self.setupUi(self)
        self.myTable = ShowTableView(self)

    def contextMenuEvent(self, QContextMenuEvent):
        self.menu = QMenu(self)
        removeAction = QAction('Remove', self)
        self.menu.addAction(removeAction)
        removeAction.triggered.connect(lambda: self.remove_row_from_rigth_click(QtGui.QCursor.pos()))
        self.menu.popup(QtGui.QCursor.pos())

    def remove_row_from_rigth_click(self, event,q_point):
        row = self.tableView.rowAt(q_point.y())
        print("row =" + str(row))  # HERE I GET WRONG VALUE WITH AN "RANDOM" OFFSET - IF I CLICK ROW 10 I GET 16 !

if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    ui = Gui()
    ui.show()
    sys.exit(app.exec_())

最佳答案

rowAt方法使用本地坐标,而您使用全局坐标。所以你必须使用mapFromGlobal获得正确的y值:

class Gui(QMainWindow, Ui_MainWindow):
    ...
    def contextMenuEvent(self, event):
        ...
        pos = event.globalPos()
        removeAction.triggered.connect(
            lambda: self.remove_row_from_rigth_click(pos))
        self.menu.popup(pos)

    def remove_row_from_rigth_click(self, q_point):
        row = self.tableView.rowAt(
            self.tableView.viewport().mapFromGlobal(q_point).y())
        print("row =" + str(row))

请注意,返回的行是从零开始的,与垂直标题标签不同。

关于python - 如何通过右键单击 QTableView 获取行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47849484/

相关文章:

c# - 在 C# WPF 中单击托盘通知后,第一次右键单击时不会打开上下文菜单?

python - 如何在linux中使用crontab删除一些文件

python - 如何获得两个四元数之间的角度?

html - 如何增加 lucene 索引中的位置偏移以对应于 <p> 标签?

c - 我想要位置,但我得到数组的 ncols 和 nrows

.NET Windows Forms 自定义控件,如何创建快捷菜单

python - django celery 如何打印或检查任务的日志记录

python - 使用boto3通过subnet_id查找route_table_id

javascript - 创建 dijit.tooltipdialog 时如何设置位置。

WPF:如何为上下文菜单实现 Blend 的 Dark 主题