Qt C ++ Перетащите QHeaderView между таблицами - PullRequest
0 голосов
/ 06 января 2020

Я хочу скопировать выбранный столбец QTableWidget в другой.

Поэтому я попытался сделать выбранные столбцы перетаскиваемыми, добавив этот код:

void makeDraggable(QTableWidget *table)
{
    table->setDragEnabled(true);
    table->setAcceptDrops(true);
    table->setSelectionBehavior(QAbstractItemView::SelectColumns);
}

Результат, который я получил :

image

Но я хочу перетащить целый столбец (горизонтальный и вертикальный заголовки), щелкая только заголовки, но не ячейки, и копировать его данные в другую таблицу, включая заголовок. текст.

1 Ответ

0 голосов
/ 07 января 2020

Перетаскивание между разными таблицами внутри одного приложения может быть выполнено с помощью переопределения пользовательских QHeaderView и QTableWidget. В моем примере я генерирую текст с индексами таблицы и столбца для события перетаскивания. Пользовательский заголовок:

#include <QHeaderView>

class ITableManager;

class DraggableHeaderView : public QHeaderView
{
    Q_OBJECT
public:
    explicit DraggableHeaderView(Qt::Orientation orientation, QWidget *parent = 0);

    int tag() const;
    void setTag(const int tag);
    void setTableManager(ITableManager* manager);

protected:
    void mouseMoveEvent(QMouseEvent *e);

    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);

signals:

public slots:

private:
    int m_tag;  //internal index of table
    ITableManager *m_tableManager;  //manager will convert table index into pointer
};

Пользовательский заголовок cpp

#include <QMouseEvent>
#include <QDrag>
#include <QMimeData>
#include <QDebug>
#include <QTableWidget>

#include <ITableManager.h>

DraggableHeaderView::DraggableHeaderView(Qt::Orientation orientation, QWidget *parent) :
    QHeaderView(orientation, parent)
{
    m_tag = 0;
    m_tableManager = 0;
    setAcceptDrops(true);
}

void DraggableHeaderView::mouseMoveEvent(QMouseEvent *e)
{
    if (e->buttons() & Qt::LeftButton)
    {
        int index = logicalIndexAt(e->pos());
        QDrag *drag = new QDrag(this);
        QMimeData *mimeData = new QMimeData;
        //custom drag text with indecies inside
        QString mimeTxt = "MoveHeader;Table:" + QString::number(m_tag) +
                ";Index:" + QString::number(index);
        mimeData->setText(mimeTxt);
        drag->setMimeData(mimeData);
        Qt::DropAction dropAction = drag->exec();
    }
}

int DraggableHeaderView::tag() const
{
    return m_tag;
}

void DraggableHeaderView::setTag(const int tag)
{
    m_tag = tag;
}

void DraggableHeaderView::dragEnterEvent(QDragEnterEvent *event)
{
    if (!m_tableManager)
    {
        event->ignore();
        return;
    }

    QString dragText = event->mimeData()->text();
    int index = dragText.indexOf("MoveHeader;");
    if (index == 0)
    {
        event->accept();
    }
    else
    {
        event->ignore();
    }
}

void DraggableHeaderView::dropEvent(QDropEvent *event)
{
    if (!m_tableManager)
    {
        event->ignore();
        return;
    }

    QStringList dragText = event->mimeData()->text().split(';');
    if (dragText.count() < 3 || dragText.at(0) != "MoveHeader")
    {
        event->ignore();
        return;
    }

    int tableIndex = dragText.at(1).mid(6).toInt();//6 - length 'Table:'
    QTableWidget* tableSrc = m_tableManager->getTableFromIndex(tableIndex);
    if (!tableSrc)
    {
        event->ignore();
        return;
    }

    //dst table as parent for header view
    QTableWidget *tableDst = qobject_cast<QTableWidget*> (this->parentWidget());
    if (!tableDst)
    {
        event->ignore();
        return;
    }

    //move column: modify for your needs
    //now moves only items text
    int columnIndex = logicalIndexAt(event->pos());
    int srcColumnIndex = dragText.at(2).mid(6).toInt(); //6 - length of 'Index:'
    tableDst->insertColumn(columnIndex);
    for (int iRow = 0; iRow < tableDst->rowCount() && iRow < tableSrc->rowCount(); ++iRow)
    {
        if (tableSrc->item(iRow, srcColumnIndex))
        {
            tableDst->setItem(iRow, columnIndex,
                              new QTableWidgetItem(tableSrc->item(iRow, srcColumnIndex)->text()));
        }
        else
        {
            tableDst->setItem(iRow, columnIndex, new QTableWidgetItem());
        }
    }
    tableSrc->removeColumn(srcColumnIndex);
}

void DraggableHeaderView::setTableManager(ITableManager *manager)
{
    m_tableManager = manager;
}

Теперь создайте пользовательский QTableWidget с DraggableHeaderView внутри

class CustomTableWidget : public QTableWidget
{
    Q_OBJECT
public:
    explicit CustomTableWidget(QWidget *parent = 0);

    void setTag(const int tag);
    void setTableManager(ITableManager* manager);
};

CustomTableWidget::CustomTableWidget(QWidget *parent) :
    QTableWidget(parent)
{
    DraggableHeaderView *headerView = new DraggableHeaderView(Qt::Horizontal, this);

    setHorizontalHeader(headerView);

    setAcceptDrops(true);
}

void CustomTableWidget::setTag(const int tag)
{
    DraggableHeaderView *header = qobject_cast<DraggableHeaderView*> (horizontalHeader());
    if (header)
    {
        header->setTag(tag);
    }
}

void CustomTableWidget::setTableManager(ITableManager *manager)
{
    DraggableHeaderView *header = qobject_cast<DraggableHeaderView*> (horizontalHeader());
    if (header)
    {
        header->setTableManager(manager);
    }
}

Для преобразования индекса таблицы в указатель я использую ITableManager

class ITableManager
{
public:
    virtual QTableWidget* getTableFromIndex(const int index) = 0;
};

и реализую его в QMainWindow

class MainWindow : public QMainWindow, ITableManager
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QTableWidget* getTableFromIndex(const int index);
}

QTableWidget * MainWindow::getTableFromIndex(const int index)
{
    switch (index)
    {
    case 1:
        return ui->tableWidget;
    case 2:
        return ui->tableWidget_2;
    default:
        return nullptr;
    }
}

Не забывайте теги установки (индексы ) и менеджер таблиц для таблиц (в конструкторе главного окна)

ui->tableWidget->setTag(1);
ui->tableWidget_2->setTag(2);
ui->tableWidget->setTableManager(this);
ui->tableWidget_2->setTableManager(this);

РЕДАКТИРОВАТЬ: Если вы хотите изменить пользовательское растровое изображение для перетаскивания, просто установите QDrag::setPixmap

void DraggableHeaderView::mouseMoveEvent(QMouseEvent *e)
{
    if (e->buttons() & Qt::LeftButton)
    {
        int index = logicalIndexAt(e->pos());
        QDrag *drag = new QDrag(this);
        QMimeData *mimeData = new QMimeData;
        QString mimeTxt = "MoveHeader;Table:" + QString::number(m_tag) +
                ";Index:" + QString::number(index);
        mimeData->setText(mimeTxt);
        drag->setMimeData(mimeData);
        drag->setPixmap(pixmapForDrag(index));
        Qt::DropAction dropAction = drag->exec();
    }
}

И способ получения растрового изображения столбца может быть таким:

QPixmap DraggableHeaderView::pixmapForDrag(const int columnIndex) const
{
    QTableWidget *table = qobject_cast<QTableWidget*> (this->parentWidget());
    if (!table)
    {
        return QPixmap();
    }

    //image for first 5 row
    int height = table->horizontalHeader()->height();
    for (int iRow = 0; iRow < 5 && iRow < table->rowCount(); ++iRow)
    {
        height += table->rowHeight(iRow);
    }

    //clip maximum size
    if (height > 200)
    {
        height = 200;
    }

    QRect rect(table->columnViewportPosition(columnIndex) + table->verticalHeader()->width(),
                 table->rowViewportPosition(0),
                 table->columnWidth(columnIndex),
                 height);
    QPixmap pixmap(rect.size());
    table->render(&pixmap, QPoint(), QRegion(rect));
    return pixmap;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...