QTableView中的Qt复制和粘贴不起作用

时间:2018-12-01 20:48:58

标签: c++ qt qt5

我正在设计一个具有多个功能的用户界面。在.ui上,我有一个QTableView。右键单击表格视图后,我将打开一个具有相同QTableView的对话框,因此以这种方式更易于可视化数据。 在尝试将某些值复制并粘贴后,从一个单元格复制到另一个单元格,或从一列复制到另一列,我有一个奇怪的行为,我不知道如何解决。下面,我尝试复制ctrl+C所选单元格:

enter image description here

然后将其粘贴ctrl+V,我得到一个奇怪的行为:

enter image description here

出于某些原因,我将标题“经度”复制到第二行而不是数字24。另外,将数字200压入下面。

此代码还允许从QTableView复制并粘贴到Excel文件,此功能运行良好,但我决定将其包含在说明中,以便您了解如何处理所有循环。

editdialog.h

private:
    Ui::editLeftTableDialog *ui;
    QSqlTableModel *mModel;
    QAction *mActionAppendRow;
    QAction *mActionDeleteRow;

protected:
    void keyPressEvent(QKeyEvent *event);

editdialog.cpp

void editLeftTableDialog::keyPressEvent(QKeyEvent *event)
{
    {
        QAbstractItemModel * modelRemoveAdd = ui->tableViewLeft->model();
        QItemSelectionModel *selectionModel = ui->tableViewLeft->selectionModel();
        QModelIndexList selectedRows = selectionModel->selectedRows();

        QAbstractItemModel * modelNew = ui->tableViewLeft->model();
        QItemSelectionModel *selectedIndexes = ui->tableViewLeft->selectionModel();
        QModelIndexList selectedInd = selectedIndexes->selectedIndexes();

        // Make sure one row is selected
        if(!selectedRows.isEmpty())
        {
            if(event->key() == Qt::Key_Insert)
                mModel->insertRows(selectedRows.at(0).row(),
                                   selectedRows.size());
            else if(event->key() == Qt::Key_Delete)
                mModel->removeRows(selectedRows.at(0).row(),
                                   selectedRows.size());
        }
        // Make sure one cell selected
        if(!selectedInd.isEmpty())
        {
            if(event->key() == Qt::Key_Delete)
                foreach(QModelIndex index, selectedInd)
                    mModel->setData(index, QString());
            else if(event->matches(QKeySequence::Copy))
            {
                QString text;
                QItemSelectionRange range = ui->tableViewLeft->selectionModel()->selection().first();
                for(auto i = range.top(); i <= range.bottom(); ++i)
                {
                    QStringList rowContents;
                    for(auto j = range.left(); j <= range.right(); ++j)
                        rowContents << mModel->index(i,j).data().toString();
                        text += rowContents.join("\t");
                        text += "\n";
                }
                QApplication::clipboard()->setText(text);
            }
            else if(event->matches(QKeySequence::Paste))
            {
                QString text = QApplication::clipboard()->text();
                QStringList rowContents = text.split("\n", QString::SkipEmptyParts);
                QModelIndex initIndex = ui->tableViewLeft->selectionModel()->selectedIndexes().at(0);
                auto initRow = initIndex.row();
                auto initCol = initIndex.column();
                for(auto i = 0; i < rowContents.size(); i++)
                {
                    QStringList columnContents = rowContents.at(i).split("\t");
                    for(auto j = 0; j < columnContents.size(); j++)
                    {
                        mModel->setData(mModel->index(initRow + i, initCol + j), columnContents.at(j));
                    }
                }
            } 
        }
    }
    // Copy from QTableView to an Excel or CSV file happens here and works well
    QAbstractItemModel * model = ui->tableViewLeft->model();
    QItemSelectionModel *selection = ui->tableViewLeft->selectionModel();
    QModelIndexList indices = selection->selectedIndexes();
    if(indices.isEmpty())
        return;
    QMap<int, bool> selectedColumnsMap;
    Q_FOREACH (QModelIndex current, indices)
    {
        selectedColumnsMap[current.column()] = true;
    }
    QList<int> selectedColumns = selectedColumnsMap.uniqueKeys();
    int minCol = selectedColumns.first();
    // prepend headers for selected columns
    QString selectedText;
    Q_FOREACH (int column, selectedColumns)
    {
        selectedText += ui->tableViewLeft->model()->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString();
        if(column != selectedColumns.last())
            selectedText += QLatin1Char('\t');
    }
    selectedText += QLatin1Char('\n');
    qSort(indices);
    int lastRow = indices.first().row();
    int lastColumn = minCol;
    Q_FOREACH(QModelIndex current, indices)
    {
        if(current.row() != lastRow)
        {
            selectedText += QLatin1Char('\n');
            lastColumn = minCol;
            lastRow = current.row();
        }
        if(current.column() != lastColumn)
        {
            for(int i = 0; i < current.column() - lastColumn; ++i)
                selectedText += QLatin1Char('\t');
            lastColumn = current.column();
        }
        selectedText += ui->tableViewLeft->model()->data(current).toString();
    }
    selectedText += QLatin1Char('\n');
    QApplication::clipboard()->setText(selectedText);
}

1 个答案:

答案 0 :(得分:1)

凌乱的代码总是会带来问题,因此,我将不对其进行分析,但将提出一种适当的方法,在该方法中,我们为每个任务创建一个函数,并且可以使用QShorcut代替使用keyPressEvent:< / p>

editlefttabledialog.h

#ifndef EDITLEFTTABLEDIALOG_H
#define EDITLEFTTABLEDIALOG_H

#include <QDialog>
class QSqlTableModel;

namespace Ui {
class EditLeftTableDialog;
}

class EditLeftTableDialog : public QDialog
{
    Q_OBJECT
public:
    explicit EditLeftTableDialog(QWidget *parent = nullptr);
    ~EditLeftTableDialog();
private slots:
    void copy();
    void paste();
private:
    Ui::EditLeftTableDialog *ui;
    QSqlTableModel *mModel;
};

#endif // EDITLEFTTABLEDIALOG_H

editlefttabledialog.cpp

#include "editlefttabledialog.h"
#include "ui_editlefttabledialog.h"

#include <QShortcut>
#include <QSqlTableModel>
#include <QClipboard>

EditLeftTableDialog::EditLeftTableDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::EditLeftTableDialog)
{
    ui->setupUi(this);
    mModel = new QSqlTableModel(this);
    mModel->setTable("test_table");
    mModel->select();
    ui->tableViewLeft->setModel(mModel);

    QShortcut *shortcut_copy = new QShortcut(QKeySequence::Copy, ui->tableViewLeft);
    connect(shortcut_copy, &QShortcut::activated, this, &EditLeftTableDialog::copy);

    QShortcut *shortcut_paste = new QShortcut(QKeySequence::Paste, ui->tableViewLeft);
    connect(shortcut_paste, &QShortcut::activated, this, &EditLeftTableDialog::paste);
}

EditLeftTableDialog::~EditLeftTableDialog()
{
    delete ui;
}

void EditLeftTableDialog::copy()
{
    QString text;
    QItemSelectionRange selection_range =  ui->tableViewLeft->selectionModel()->selection().first();
    for(int i=selection_range.top(); i <= selection_range.bottom(); i++){
        QStringList row_content;
        for(int j= selection_range.left(); j <= selection_range.right(); j++){
            row_content << mModel->index(i,j).data().toString();
        }
        text += row_content.join(QChar('\t')) + QChar('\n');
    }
    QApplication::clipboard()->setText(text);
}

void EditLeftTableDialog::paste()
{
    QModelIndex start = ui->tableViewLeft->selectionModel()->selectedIndexes().first();
    QString text = QApplication::clipboard()->text();
    int i=0, j=0;
    for(const QString & row_string:  text.split("\n", QString::SkipEmptyParts)){
        j=0;
        for(const QString & col:  row_string.split("\t", QString::SkipEmptyParts)){
            QModelIndex ix = mModel->index(start.row() + i , start.column()+ j);
            if(ix.isValid()){
                ui->tableViewLeft->model()->setData(ix, col);
                mModel->submit();
            }
            j++;
        }
        i++;
    }
}