Saya ingin menghapus baris di widget QTableView dengan menekan tombol QPushButton. Kode berfungsi dengan baik dengan satu baris, namun, ketika saya memilih beberapa baris, satu baris selalu ditinggalkan.

Inilah yang saya miliki sejauh ini:

main.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>350</width>
    <height>239</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QWidget" name="formLayoutWidget">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>341</width>
     <height>231</height>
    </rect>
   </property>
   <layout class="QFormLayout" name="formLayout">
    <item row="0" column="1">
     <widget class="QPushButton" name="btnPopulate">
      <property name="text">
       <string>Populate Table</string>
      </property>
     </widget>
    </item>
    <item row="2" column="1">
     <widget class="QTableView" name="tableView">
      <property name="selectionBehavior">
       <enum>QAbstractItemView::SelectRows</enum>
      </property>
     </widget>
    </item>
    <item row="1" column="1">
     <widget class="QPushButton" name="btnDelete">
      <property name="text">
       <string>Delete Row(s)</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
from PyQt5 import uic, QtWidgets
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QDialog, QComboBox, QApplication, QHeaderView

class GUI(QDialog):

    def __init__(self):
        super(GUI, self).__init__()
        dirname = os.path.dirname(os.path.abspath(__file__))
        uic.loadUi(os.path.join(dirname,'main.ui'), self)
        # buttons
        self.btnPopulate.clicked.connect(self.populate)
        self.btnDelete.clicked.connect(self.delete)
        # table model
        self.header = ['col1', 'col2', 'col3']
        self.QSModel = QStandardItemModel()
        self.QSModel.setColumnCount(3)
        self.QSModel.setHorizontalHeaderLabels(self.header)
        self.tableView.setModel(self.QSModel)
        self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        
    def populate(self):
        row = self.QSModel.rowCount()
        for x in range(7):
            self.QSModel.insertRow(row)
            self.QSModel.setData(self.QSModel.index(row, 0), 'data' + str(x))
            self.QSModel.item(row, 0).setEditable(True)
            self.QSModel.setData(self.QSModel.index(row, 1), 'data' + str(x))
            self.QSModel.item(row, 1).setEditable(True)
            self.QSModel.setData(self.QSModel.index(row, 2), 'data' + str(x))
            self.QSModel.item(row, 1).setEditable(True) 

    def delete(self):
        if self.tableView.selectionModel().hasSelection():
            indexes = self.tableView.selectionModel().selectedRows() 
            for index in sorted(indexes):
                print('Deleting row %d...' % index.row())
                self.QSModel.removeRow(index.row())
        else:
            print('No row selected!')
            
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = GUI()
    window.show()
    sys.exit(app.exec_())

Saya punya pertanyaan berikut:

  1. Mengapa selalu satu baris tidak dihapus ketika saya memilih beberapa baris dan apa yang perlu saya ubah untuk menghapus semua baris yang dipilih?
  2. Bagaimana cara memilih baris berikutnya secara otomatis setelah penghapusan selesai sehingga saya dapat menghapus seluruh tabel dengan mengklik tombol Hapus Baris berulang kali?
  3. Apakah ada metode bawaan yang memungkinkan saya untuk menghubungkan QPushButton atau aksinya ke penekanan tombol DEL/BACKSPACE? Yaitu, saya ingin penekanan tombol DEL/BACKSPACE untuk memicu delete().
0
Nemo XXX 6 Januari 2018, 00:15

1 menjawab

Jawaban Terbaik

Mengapa selalu satu baris tidak dihapus ketika saya memilih beberapa baris dan apa yang perlu saya ubah untuk menghapus semua baris yang dipilih?

Masalahnya disebabkan oleh menghapus baris dengan mengatur ulang posisi, misalnya, katakan Anda menghapus 3,4,5, pertama hapus 3, lalu 4 menjadi 3, dan 5 menjadi 4, lalu Anda hilangkan 4, hilangkan 4 arus jadi bahwa 4 awal tidak dihapus.

QModelIndex adalah indeks sementara yang tidak diberi tahu jika posisinya berubah, sebaliknya QPersistentModelIndex jika diberi tahu jadi Anda harus menggunakannya untuk mendapatkan baris meskipun berubah.

def delete(self):
    if self.tableView.selectionModel().hasSelection():
        indexes =[QPersistentModelIndex(index) for index in self.tableView.selectionModel().selectedRows()]
        for index in indexes:
            print('Deleting row %d...' % index.row())
            self.QSModel.removeRow(index.row())
    else:
        print('No row selected!')

Bagaimana cara memilih baris berikutnya secara otomatis setelah penghapusan selesai sehingga saya dapat menghapus seluruh tabel dengan mengklik tombol Hapus Baris berulang kali?

Untuk memilih baris baru Anda harus mengatur beberapa item dari baris itu sebagai aktif melalui setCurrentIndex() metode QTableView, dalam contoh ini saya menghitung baris terakhir dan dengan itu saya mendapatkan QPersistentModelIndex item dari baris berikutnya, setelah menghapus saya mengubahnya menjadi QModelIndex dan saya menggunakannya dalam metode sebelumnya.

def delete(self):
    if self.tableView.selectionModel().hasSelection():
        indexes =[QPersistentModelIndex(index) for index in self.tableView.selectionModel().selectedRows()]
        maxrow = max(indexes, key=lambda x: x.row()).row()
        next_ix = QPersistentModelIndex(self.QSModel.index(maxrow+1, 0))
        for index in indexes:
            print('Deleting row %d...' % index.row())
            self.QSModel.removeRow(index.row())
        self.tableView.setCurrentIndex(QModelIndex(next_ix))
    else:
        print('No row selected!')

Apakah ada metode bawaan yang memungkinkan saya untuk menghubungkan QPushButton atau aksinya ke penekanan tombol DEL/BACKSPACE? Yaitu, saya ingin penekanan tombol DEL/BACKSPACE untuk memicu delete().

Untuk mendapatkan acara keyboard Anda harus menimpa metode keyPressEvent, acara ini terjadi sebagai objek QKeyEvent yang memiliki metode kunci yang mengembalikan tombol yang ditekan, verifikasi apakah itu kunci yang diinginkan dan jika ya, lalu panggil delete()

def keyPressEvent(self, event):
    if event.key() in (Qt.Key_Backspace, Qt.Key_Delete):
        self.delete()
    QDialog.keyPressEvent(self, event)
4
eyllanesc 5 Januari 2018, 22:08