PyQt: QTableView + QSqlTableModel - Copy and Paste All Selected Rows or Columns into Notepad or Excel

亡梦爱人 提交于 2020-01-25 21:28:12

问题


To start, I've already looked at ekhumoro's code on a nearly similar subject Here. However, when I attempt to implement this code, I am getting a different result. Instead of copying and pasting all the I selected, it only copies the first cell of the selected row or rows respectively. I need users to be able to select multiple rows or columns and paste those values in either excel or notepad. Any ideas?

GUI:

Code:

from PyQt4 import QtCore, QtGui, QtSql
import sys  
import sqlite3
import time
import csv


import Search  # This file holds our MainWindow and all design related things

# it also keeps events etc that we defined in Qt Designer
import os 
try:
    from PyQt4.QtCore import QString
except ImportError:
    QString = str

class TableEditor(QtGui.QMainWindow, Search.Search_MainWindow):
    def __init__(self, tableName, parent=None):
        # Explaining super is out of the scope of this article
        # So please google it if you're not familar with it
        # Simple reason why we use it here is that it allows us to
        # access variables, methods etc in the design.py file
        super(self.__class__, self).__init__()
        self.setupUi(self)  # This is defined in design.py file automatically
        # It sets up layout and widgets that are defined
        self.model = QtSql.QSqlTableModel(self)
        self.model.setTable('CAUTI')
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
        self.model.select()
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, "MRN")
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, "Last Name")
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, "First Name")
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, "Date of Event")
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, "Facility")
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, "Unit")
        self.model.setHeaderData(6, QtCore.Qt.Horizontal, "User")
        #self.tableView.verticalHeader().setVisible(False)
        self.tableView.setModel(self.model)
        self.setWindowTitle("HAI Table")
        self.tableView.setColumnWidth(0,100)
        self.tableView.setColumnWidth(1,100)
        self.tableView.setColumnWidth(2,100)
        self.tableView.setColumnWidth(3,100)
        self.tableView.setColumnWidth(4,100)
        self.tableView.setColumnWidth(5,100)
        self.tableView.setColumnWidth(6,83)
        self.tableView.setSortingEnabled(True)
        self.tableView.setDropIndicatorShown(True)
        self.tableView.setAcceptDrops(True)
        self.tableView.setDragEnabled(True)
        self.tableView.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.tableView.horizontalHeader().setMovable(True)       
        self.tableView.horizontalHeader().setDragEnabled(True)
        self.clip = QtGui.QApplication.clipboard()

     ## Note: ** When I unblock this line of code, I get an error.
        #self.tableView.installEventFilters(self)




        self.tableView.horizontalHeader().setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.tableView.verticalHeader().setMovable(True)
        self.tableView.verticalHeader().setDragEnabled(True)
        self.tableView.verticalHeader().setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.tableView.setSelectionBehavior(QtGui.QTableView.SelectRows)
        self.submitButton.clicked.connect(self.submit)
        self.revertButton.clicked.connect(self.model.revertAll)
        self.quitButton.clicked.connect(self.close)

        self.tableView.horizontalHeader().setSortIndicatorShown(True)
        self.tableView.horizontalHeader().setClickable(True)
    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.KeyPress and
            event.matches(QtGui.QKeySequence.Copy)):
            self.copySelection()
            return True
        return super(Window, self).eventFilter(source, event)

    def copySelection(self):
        selection = self.tableView.selectedIndexes()
        if selection:
            rows = sorted(index.row() for index in selection)
            columns = sorted(index.column() for index in selection)
            rowcount = rows[-1] - rows[0] + 1
            colcount = columns[-1] - columns[0] + 1
            table = [[''] * colcount for _ in range(rowcount)]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                table[row][column] = index.data()
            stream = io.StringIO()
            csv.writer(stream).writerows(table)
            QtGui.qApp.clipboard().setText(stream.getvalue())

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDropEnabled    


def main():
    app = QtGui.QApplication(sys.argv)  
    #app.setStyle( "Plastique" )
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName('HAI.db')

    editor = TableEditor('CAUTI')
    editor.show()
    app.exec_()  


if __name__ == '__main__': 
    main()  

回答1:


Your implementation is broken in several ways, so the code you copied never gets executed. As a result, the table's built-in copy function is used, which does not handle multiple selected items.

My original code for copying multiple table items is here. I think you should be able to get your example working by changing the following lines:

from PyQt4 import QtCore, QtGui, QtSql
# fix imports
import sys, io
...

class TableEditor(QtGui.QMainWindow, Search.Search_MainWindow):
    def __init__(self, tableName, parent=None):
        # do not ever use self.__class__ here
        super(TableEditor, self).__init__()
        ...
        # install event-filter properly
        self.tableView.installEventFilter(self)

    def eventFilter(self, source, event):
        ...
        # call super properly
        return super(TableEditor, self).eventFilter(source, event)

Obviously, I cannot run your actual example code, so there may be other errors that I haven't spotted.




回答2:


This is much faster :

def copySelection(self):
    clipboardString = StringIO()
    selectedIndexes = self.ui.tableView.selectedIndexes()
    if selectedIndexes:
        countList = len(selectedIndexes)         
        for r in range(countList):
            current = selectedIndexes[r]
            displayText = current.data(QtCore.Qt.DisplayRole)
            if r+1 < countList:
                next_ = selectedIndexes[r+1]
                if next_.row() != current.row():
                    displayText += ("\n")
                else:
                    displayText += ("\t")
            clipboardString.write(displayText)
        pyperclip.copy(clipboardString.getvalue())


来源:https://stackoverflow.com/questions/42030309/pyqt-qtableview-qsqltablemodel-copy-and-paste-all-selected-rows-or-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!