user3030327
user3030327

Reputation: 451

How to create contextmenu to delete row for inside of qtableview python

below is the code i am using: How to create contextmenu to delete row for inside of qtableview python.

It is showing menu even i clicked on Qpushbutton also but i need to show the delete menu on only inside of qtableview. and let me know the way to delete the row of qtableview data. Please let me know the solution.

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import uic
import sys
import sqlite3


class UI(QMainWindow):
    def __init__(self):
        super(UI, self).__init__()
        uic.loadUi("tableview.ui", self)
        self.show()

        self.view_msa()

        self.pushButton.clicked.connect(self.view_msa)

                
    def view_msa(self):
        self.model = QtGui.QStandardItemModel(self)
        self.tableView.setModel(self.model)

        conn = sqlite3.connect('book.db')
        cur = conn.cursor()
        cur.execute("SELECT * FROM card")
        db_data = cur.fetchall()
        print(db_data)
        for line in db_data:
            row = []
            for item in line:
                cell = QStandardItem(str(item))
                row.append(cell)

            self.model.setHorizontalHeaderLabels(["Name","Age","Gender"])
            self.model.appendRow(row)

    def contextMenuEvent(self, event):
        self.click_menu = QtWidgets.QMenu()
        renameAction = QtWidgets.QAction('Delete', self)
        renameAction.triggered.connect(lambda: self.renameSlot(event))
        self.click_menu.addAction(renameAction)

        self.click_menu.popup(QtGui.QCursor.pos())

    def renameSlot(self, event):
        print("Renameing slot called")

app = QApplication(sys.argv)
window = UI()
app.exec_()

Upvotes: 1

Views: 627

Answers (1)

musicamante
musicamante

Reputation: 48489

All widget have the contextMenuPolicy property, which if set to QtCore.Qt.CustomContextMenu allows to connect to the customContextMenuRequested(pos) signal (note that the pos is in widget coordinates). From there you can access the index that is at the mouse position through indexAt or, better, get the selectedIndexes (which is useful if you have multiple selection enabled).

class UI(QMainWindow):
    def __init__(self):
        super(UI, self).__init__()
        # ...

        self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tableView.customContextMenuRequested.connect(self.tableMenu)

    def tableMenu(self, pos):
        selected = self.tableView.selectedIndexes()
        if not selected:
            return
        menu = QtWidgets.QMenu()
        deleteAction = menu.addAction('Delete rows')
        deleteAction.triggered.connect(lambda: self.removeRows(selected))
        menu.exec_(QtGui.QCursor.pos())

    def removeRows(self, indexes):
        # get unique row numbers
        rows = set(index.row() for index in indexes)
        # remove rows in *REVERSE* order!
        for row in sorted(rows, reverse=True):
            self.model.removeRow(row)

Note that in this case you have to use menu.exec() (which is usually the preferred method), not popup(), otherwise the function will return instantly and the menu won't probably shown up because of internal processing of the mouse events: exec blocks until it returns (whether any of its actions are triggered or it's closed), popup returns immediately.

Upvotes: 2

Related Questions