QT之——QTableWidget拖拽單元格並替換內容(進階)

LSM0307發表於2021-02-01

所需待重寫函式:

[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event); 
/* 
 * Filters events if this object has been installed as an event filter for the watched object. 
 * In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false. 
 */ 

以上來自官方幫助手冊

說明:

  1. 通過事件過濾器,即上述重寫函式,可通過條件,篩選所需事件
  2. 如果篩選成功,如果此事件後續不再使用,返回true,後續如果再次使用,返回false
  3. 如果篩選不成功,則返回給父類,防止父類處於內部目的重新實現了 eventFilter()

程式碼示例:

  1. MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTableWidget>

#define STANDFLDCOL		0
#define LAYERFLDCOL		1

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

protected:
    bool eventFilter(QObject *watched, QEvent *event);

private:
    /* init table widget cell data */
    void InitCellData();

    /* mouse press event */
    void MousesPressEvent(QMouseEvent *event);

    /* mouse move event */
    void MousesMoveEvent();

    /* mouse release event */
    void MousesReleaseEvent(QMouseEvent *event);

    /* exchange cell data between drag cell and drop cell */
    void ExchangeData(int oldRow, int oldCol, int newRow, int newCol, QTableWidget *focusTable);

private:
    Ui::MainWindow *ui;
    int 	m_selectRow;	// drag row
    bool 	m_isPress;		// mouse press
    bool 	m_isDrag;		// mouse is drag
};

#endif // MAINWINDOW_H

說明:

void InitCellData() : 初始化表格內容
void MousesPressEvent() : 如果事件過濾器中篩選了滑鼠左鍵按下事件,則呼叫該函式
void MousesMoveEvent() : 如果事件過濾器篩選了滑鼠移動事件,則呼叫該函式
void MousesReleaseEvent() : 如果事件過濾器篩選了滑鼠釋放事件,則呼叫該函式
void ExchangeData() : 交換拖拽起始單元格和最終單元格item

  1. MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMouseEvent>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_isPress 	= false;
    m_isDrag 	= false;

    InitCellData();
}

MainWindow::~MainWindow()
{
    ui->tableWidget->clear();
    delete ui;
}

void MainWindow::InitCellData()
{
    ui->tableWidget->viewport()->installEventFilter(this);
    ui->tableWidget->horizontalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->setRowCount(15);

    for (int i = 0; i < 15; i++)
    {
        QTableWidgetItem *aitem = new QTableWidgetItem(QString("%1ATime").arg(i));
        aitem->setFlags(aitem->flags()&(~Qt::ItemIsEditable));
        ui->tableWidget->setItem(i, STANDFLDCOL, aitem);

        QTableWidgetItem *bitem = new QTableWidgetItem(QString("%1BTime").arg(i));
        bitem->setFlags(bitem->flags()&(~Qt::ItemIsEditable));
        ui->tableWidget->setItem(i, LAYERFLDCOL, bitem);
    }
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == ui->tableWidget->viewport())
    {
        QMouseEvent *pEvent = static_cast<QMouseEvent*>(event);
        if (event->type() == QEvent::MouseButtonPress)
        {
            MousesPressEvent(pEvent);
            return true;
        }
        else if (event->type() == QEvent::MouseMove)
        {
            MousesMoveEvent();
            return true;
        }
        else if (event->type() == QEvent::MouseButtonRelease)
        {
            MousesReleaseEvent(pEvent);
            return true;
        }
        else return false;
    }
    return QMainWindow::eventFilter(watched, event);
}

void MainWindow::MousesPressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if (STANDFLDCOL == ui->tableWidget->columnAt(event->x()))
        {
            return;
        }
        m_isPress 	= true;
        m_isDrag 	= false;
        m_selectRow = ui->tableWidget->rowAt(event->y());
        ui->tableWidget->clearFocus();
    }
}

void MainWindow::MousesMoveEvent()
{
    if (m_isPress && !m_isDrag)
    {
        m_isDrag 	= true;
    }
}

void MainWindow::MousesReleaseEvent(QMouseEvent *event)
{
    if (m_isPress && m_isDrag)
    {
        m_isPress 	= false;
        m_isDrag 	= false;

        if (STANDFLDCOL == ui->tableWidget->columnAt(event->x()))
        {
            return;
        }
        ExchangeData(m_selectRow, LAYERFLDCOL, ui->tableWidget->rowAt(event->y()), LAYERFLDCOL, ui->tableWidget);
    }
}

void MainWindow::ExchangeData(int oldRow, int oldCol, int newRow, int newCol, QTableWidget *focusTable)
{
    QTableWidgetItem *oldItem = focusTable->takeItem(oldRow, oldCol);
    QTableWidgetItem *newItem = focusTable->takeItem(newRow, newCol);
    focusTable->setItem(oldRow, oldCol, newItem);
    focusTable->setItem(newRow, newCol, oldItem);
}

說明:

限制拖拽列只能為第2列(可進行修改)
限值不同列之間不能進行拖拽(可進行修改)

相關文章