Qt C++ 在表之间拖动 QHeaderView
Posted
技术标签:
【中文标题】Qt C++ 在表之间拖动 QHeaderView【英文标题】:Qt C++ Drag QHeaderView between tables 【发布时间】:2020-01-06 15:18:05 【问题描述】:我想将QTableWidget
的选定列复制到另一个。
所以我尝试通过添加以下代码使选定的列可拖动:
void makeDraggable(QTableWidget *table)
table->setDragEnabled(true);
table->setAcceptDrops(true);
table->setSelectionBehavior(QAbstractItemView::SelectColumns);
我得到的结果:
但我想通过仅单击标题而不是单元格来拖动整个列(水平和垂直标题),并将其数据复制到另一个表中,包括标题文本。
【问题讨论】:
让我们假设你想要的工作但qtableview的行数不一样,例如如果第一行有3行,第二个100然后将列从第一个tableview拖到第二个并将其放在第 15 行。应该粘贴这些项目的行吗?或者使用你的例子,如果鼠标在最后一行被释放,信息应该粘贴到哪里? 因为我们想通过拖动标题(而不是单元格)来粘贴一整列,我们只能将数据插入到另一个表的另一个 QHeaderView 中。如果当前行 啊,好吧,现在我明白了。 【参考方案1】:可以通过重新实现自定义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;
不要忘记表的设置标签(indecies)和表管理器(在主窗口构造函数中)
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;
【讨论】:
谢谢!但是我如何才能看到我当前正在拖动的一整列? (如第二张桌子上的屏幕截图所示)。现在我只看到光标。 感谢您很好地解决了我的问题! 如果可能的话,我怎样才能改变所选部分的背景? QHeaderView:section:hover 不起作用。 @user362316 如果您要求定期更改选择背景,请查看qss
或创建另一个问题,因为它与当前问题无关。但是,如果您问如何仅为拖动像素图更改背景,那么我可以建议您在像素图渲染之前更改背景并在之后恢复。以上是关于Qt C++ 在表之间拖动 QHeaderView的主要内容,如果未能解决你的问题,请参考以下文章
在 QHeaderView 和 QListWidget 之间拖放列
No member named 'setResizeMode' in 'QHeaderView' - Convert Qt 4.7 to Qt 5.8