Qt C++ 在表格之间拖动 QHeaderView。

huangapple go评论138阅读模式
英文:

Qt C++ Drag QHeaderView between tables

问题

我想复制QTableWidget的选定列到另一个表格。

所以我尝试通过添加以下代码使选定列可拖动:

  1. void makeDraggable(QTableWidget *table)
  2. {
  3. table->setDragEnabled(true);
  4. table->setAcceptDrops(true);
  5. table->setSelectionBehavior(QAbstractItemView::SelectColumns);
  6. }

我得到的结果:

Qt C++ 在表格之间拖动 QHeaderView。

但我想要通过仅点击标题来拖动整列(水平和垂直标题),并将其数据复制到另一个表格,包括标题文本。

英文:

I want to copy the selected column of a QTableWidget to another one.

So I tried to make selected columns draggable by adding this code:

  1. void makeDraggable(QTableWidget *table)
  2. {
  3. table->setDragEnabled(true);
  4. table->setAcceptDrops(true);
  5. table->setSelectionBehavior(QAbstractItemView::SelectColumns);
  6. }

Result I got:

Qt C++ 在表格之间拖动 QHeaderView。

But I want to drag a whole column (horizontal and vertical headers) by clicking on headers only, not on cells, and copy its data to another table including the header text.

答案1

得分: 0

在一个应用程序内,可以通过重新实现自定义的 QHeaderViewQTableWidget 来在不同表格之间进行拖动。在我的示例中,我生成了包含表格和列的索引的文本以进行拖动事件。自定义头部:

  1. #include <QHeaderView>
  2. class ITableManager;
  3. class DraggableHeaderView : public QHeaderView
  4. {
  5. Q_OBJECT
  6. public:
  7. explicit DraggableHeaderView(Qt::Orientation orientation, QWidget *parent = 0);
  8. int tag() const;
  9. void setTag(const int tag);
  10. void setTableManager(ITableManager* manager);
  11. protected:
  12. void mouseMoveEvent(QMouseEvent *e);
  13. void dragEnterEvent(QDragEnterEvent *event);
  14. void dragMoveEvent(QDragMoveEvent *event);
  15. void dropEvent(QDropEvent *event);
  16. signals:
  17. public slots:
  18. private:
  19. int m_tag; // 表格的内部索引
  20. ITableManager *m_tableManager; // 管理器将表格索引转换为指针
  21. };

自定义头部 cpp:

  1. #include <QMouseEvent>
  2. #include <QDrag>
  3. #include <QMimeData>
  4. #include <QDebug>
  5. #include <QTableWidget>
  6. #include <ITableManager.h>
  7. DraggableHeaderView::DraggableHeaderView(Qt::Orientation orientation, QWidget *parent) :
  8. QHeaderView(orientation, parent)
  9. {
  10. m_tag = 0;
  11. m_tableManager = 0;
  12. setAcceptDrops(true);
  13. }
  14. void DraggableHeaderView::mouseMoveEvent(QMouseEvent *e)
  15. {
  16. if (e->buttons() & Qt::LeftButton)
  17. {
  18. int index = logicalIndexAt(e->pos());
  19. QDrag *drag = new QDrag(this);
  20. QMimeData *mimeData = new QMimeData;
  21. // 自定义拖动文本,包含索引
  22. QString mimeTxt = "MoveHeader;Table:" + QString::number(m_tag) +
  23. ";Index:" + QString::number(index);
  24. mimeData->setText(mimeTxt);
  25. drag->setMimeData(mimeData);
  26. Qt::DropAction dropAction = drag->exec();
  27. }
  28. }
  29. int DraggableHeaderView::tag() const
  30. {
  31. return m_tag;
  32. }
  33. void DraggableHeaderView::setTag(const int tag)
  34. {
  35. m_tag = tag;
  36. }
  37. void DraggableHeaderView::dragEnterEvent(QDragEnterEvent *event)
  38. {
  39. if (!m_tableManager)
  40. {
  41. event->ignore();
  42. return;
  43. }
  44. QString dragText = event->mimeData()->text();
  45. int index = dragText.indexOf("MoveHeader;");
  46. if (index == 0)
  47. {
  48. event->accept();
  49. }
  50. else
  51. {
  52. event->ignore();
  53. }
  54. }
  55. void DraggableHeaderView::dropEvent(QDropEvent *event)
  56. {
  57. if (!m_tableManager)
  58. {
  59. event->ignore();
  60. return;
  61. }
  62. QStringList dragText = event->mimeData()->text().split(';');
  63. if (dragText.count() < 3 || dragText.at(0) != "MoveHeader")
  64. {
  65. event->ignore();
  66. return;
  67. }
  68. int tableIndex = dragText.at(1).mid(6).toInt(); // 6 - "Table:" 的长度
  69. QTableWidget* tableSrc = m_tableManager->getTableFromIndex(tableIndex);
  70. if (!tableSrc)
  71. {
  72. event->ignore();
  73. return;
  74. }
  75. // 目标表格作为头部视图的父级
  76. QTableWidget *tableDst = qobject_cast<QTableWidget*> (this->parentWidget());
  77. if (!tableDst)
  78. {
  79. event->ignore();
  80. return;
  81. }
  82. // 移动列:根据您的需要进行修改
  83. // 现在只移动项目文本
  84. int columnIndex = logicalIndexAt(event->pos());
  85. int srcColumnIndex = dragText.at(2).mid(6).toInt(); // 6 - "Index:" 的长度
  86. tableDst->insertColumn(columnIndex);
  87. for (int iRow = 0; iRow < tableDst->rowCount() && iRow < tableSrc->rowCount(); ++iRow)
  88. {
  89. if (tableSrc->item(iRow, srcColumnIndex))
  90. {
  91. tableDst->setItem(iRow, columnIndex,
  92. new QTableWidgetItem(tableSrc->item(iRow, srcColumnIndex)->text()));
  93. }
  94. else
  95. {
  96. tableDst->setItem(iRow, columnIndex, new QTableWidgetItem());
  97. }
  98. }
  99. tableSrc->removeColumn(srcColumnIndex);
  100. }
  101. void DraggableHeaderView::setTableManager(ITableManager *manager)
  102. {
  103. m_tableManager = manager;
  104. }

现在创建带有 DraggableHeaderView 的自定义 QTableWidget

  1. class CustomTableWidget : public QTableWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit CustomTableWidget(QWidget *parent = 0);
  6. void setTag(const int tag);
  7. void setTableManager(ITableManager* manager);
  8. };
  9. CustomTableWidget::CustomTableWidget(QWidget *parent) :
  10. QTableWidget(parent)
  11. {
  12. DraggableHeaderView *headerView = new DraggableHeaderView(Qt::Horizontal, this);
  13. setHorizontalHeader(headerView);
  14. setAcceptDrops(true);
  15. }
  16. void CustomTableWidget::setTag(const int tag)
  17. {
  18. DraggableHeaderView *header = qobject_cast<DraggableHeaderView*> (horizontalHeader());
  19. if (header)
  20. {
  21. header->setTag(tag);
  22. }
  23. }
  24. void CustomTableWidget::setTableManager(ITableManager *manager)
  25. {
  26. DraggableHeaderView *header = qobject_cast<DraggableHeaderView*> (horizontalHeader());
  27. if (header)
  28. {
  29. header->setTableManager(manager);
  30. }
  31. }

为了将表格索引转换为指针,我使用了 ITableManager

  1. class ITableManager
  2. {
  3. public:
  4. virtual QTableWidget* getTableFromIndex(const int index) = 0;
  5. };

并在 QMainWindow 中实现它:

  1. class MainWindow : public QMainWindow, ITableManager
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit MainWindow(QWidget *parent = 0);
  6. ~MainWindow();
  7. QTableWidget* getTableFromIndex(const int index);
  8. }
  9. QTableWidget *MainWindow::getTableFromIndex(const int index)
  10. {
  11. switch (index)
  12. {
  13. case 1:
  14. return ui->tableWidget;
  15. case 2:
  16. return ui->tableWidget_2;
  17. default:
  18. return nullptr;
  19. }
  20. }

不要忘记在表格(在主窗口构造函数中)中设置标签(索引)和表格管理器:

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

编辑: 如果您想更改拖动的自定义图像,只需设置 QDrag::setPixmap

  1. void
  2. <details>
  3. <summary>英文:</summary>
  4. Dragging between different tables inside one application can be done with reimplementing custom `QHeaderView` and `QTableWidget`. In my example I generate text with indecies of table and column for drag event. **Custom header:**
  5. #include &lt;QHeaderView&gt;
  6. class ITableManager;
  7. class DraggableHeaderView : public QHeaderView
  8. {
  9. Q_OBJECT
  10. public:
  11. explicit DraggableHeaderView(Qt::Orientation orientation, QWidget *parent = 0);
  12. int tag() const;
  13. void setTag(const int tag);
  14. void setTableManager(ITableManager* manager);
  15. protected:
  16. void mouseMoveEvent(QMouseEvent *e);
  17. void dragEnterEvent(QDragEnterEvent *event);
  18. void dragMoveEvent(QDragMoveEvent *event);
  19. void dropEvent(QDropEvent *event);
  20. signals:
  21. public slots:
  22. private:
  23. int m_tag; //internal index of table
  24. ITableManager *m_tableManager; //manager will convert table index into pointer
  25. };
  26. **Custom header cpp**
  27. #include &lt;QMouseEvent&gt;
  28. #include &lt;QDrag&gt;
  29. #include &lt;QMimeData&gt;
  30. #include &lt;QDebug&gt;
  31. #include &lt;QTableWidget&gt;
  32. #include &lt;ITableManager.h&gt;
  33. DraggableHeaderView::DraggableHeaderView(Qt::Orientation orientation, QWidget *parent) :
  34. QHeaderView(orientation, parent)
  35. {
  36. m_tag = 0;
  37. m_tableManager = 0;
  38. setAcceptDrops(true);
  39. }
  40. void DraggableHeaderView::mouseMoveEvent(QMouseEvent *e)
  41. {
  42. if (e-&gt;buttons() &amp; Qt::LeftButton)
  43. {
  44. int index = logicalIndexAt(e-&gt;pos());
  45. QDrag *drag = new QDrag(this);
  46. QMimeData *mimeData = new QMimeData;
  47. //custom drag text with indecies inside
  48. QString mimeTxt = &quot;MoveHeader;Table:&quot; + QString::number(m_tag) +
  49. &quot;;Index:&quot; + QString::number(index);
  50. mimeData-&gt;setText(mimeTxt);
  51. drag-&gt;setMimeData(mimeData);
  52. Qt::DropAction dropAction = drag-&gt;exec();
  53. }
  54. }
  55. int DraggableHeaderView::tag() const
  56. {
  57. return m_tag;
  58. }
  59. void DraggableHeaderView::setTag(const int tag)
  60. {
  61. m_tag = tag;
  62. }
  63. void DraggableHeaderView::dragEnterEvent(QDragEnterEvent *event)
  64. {
  65. if (!m_tableManager)
  66. {
  67. event-&gt;ignore();
  68. return;
  69. }
  70. QString dragText = event-&gt;mimeData()-&gt;text();
  71. int index = dragText.indexOf(&quot;MoveHeader;&quot;);
  72. if (index == 0)
  73. {
  74. event-&gt;accept();
  75. }
  76. else
  77. {
  78. event-&gt;ignore();
  79. }
  80. }
  81. void DraggableHeaderView::dropEvent(QDropEvent *event)
  82. {
  83. if (!m_tableManager)
  84. {
  85. event-&gt;ignore();
  86. return;
  87. }
  88. QStringList dragText = event-&gt;mimeData()-&gt;text().split(&#39;;&#39;);
  89. if (dragText.count() &lt; 3 || dragText.at(0) != &quot;MoveHeader&quot;)
  90. {
  91. event-&gt;ignore();
  92. return;
  93. }
  94. int tableIndex = dragText.at(1).mid(6).toInt();//6 - length &#39;Table:&#39;
  95. QTableWidget* tableSrc = m_tableManager-&gt;getTableFromIndex(tableIndex);
  96. if (!tableSrc)
  97. {
  98. event-&gt;ignore();
  99. return;
  100. }
  101. //dst table as parent for header view
  102. QTableWidget *tableDst = qobject_cast&lt;QTableWidget*&gt; (this-&gt;parentWidget());
  103. if (!tableDst)
  104. {
  105. event-&gt;ignore();
  106. return;
  107. }
  108. //move column: modify for your needs
  109. //now moves only items text
  110. int columnIndex = logicalIndexAt(event-&gt;pos());
  111. int srcColumnIndex = dragText.at(2).mid(6).toInt(); //6 - length of &#39;Index:&#39;
  112. tableDst-&gt;insertColumn(columnIndex);
  113. for (int iRow = 0; iRow &lt; tableDst-&gt;rowCount() &amp;&amp; iRow &lt; tableSrc-&gt;rowCount(); ++iRow)
  114. {
  115. if (tableSrc-&gt;item(iRow, srcColumnIndex))
  116. {
  117. tableDst-&gt;setItem(iRow, columnIndex,
  118. new QTableWidgetItem(tableSrc-&gt;item(iRow, srcColumnIndex)-&gt;text()));
  119. }
  120. else
  121. {
  122. tableDst-&gt;setItem(iRow, columnIndex, new QTableWidgetItem());
  123. }
  124. }
  125. tableSrc-&gt;removeColumn(srcColumnIndex);
  126. }
  127. void DraggableHeaderView::setTableManager(ITableManager *manager)
  128. {
  129. m_tableManager = manager;
  130. }
  131. Now create custom `QTableWidget` with `DraggableHeaderView` inside
  132. class CustomTableWidget : public QTableWidget
  133. {
  134. Q_OBJECT
  135. public:
  136. explicit CustomTableWidget(QWidget *parent = 0);
  137. void setTag(const int tag);
  138. void setTableManager(ITableManager* manager);
  139. };
  140. CustomTableWidget::CustomTableWidget(QWidget *parent) :
  141. QTableWidget(parent)
  142. {
  143. DraggableHeaderView *headerView = new DraggableHeaderView(Qt::Horizontal, this);
  144. setHorizontalHeader(headerView);
  145. setAcceptDrops(true);
  146. }
  147. void CustomTableWidget::setTag(const int tag)
  148. {
  149. DraggableHeaderView *header = qobject_cast&lt;DraggableHeaderView*&gt; (horizontalHeader());
  150. if (header)
  151. {
  152. header-&gt;setTag(tag);
  153. }
  154. }
  155. void CustomTableWidget::setTableManager(ITableManager *manager)
  156. {
  157. DraggableHeaderView *header = qobject_cast&lt;DraggableHeaderView*&gt; (horizontalHeader());
  158. if (header)
  159. {
  160. header-&gt;setTableManager(manager);
  161. }
  162. }
  163. For converting table index to pointer I use `ITableManager`
  164. class ITableManager
  165. {
  166. public:
  167. virtual QTableWidget* getTableFromIndex(const int index) = 0;
  168. };
  169. And implement it in `QMainWindow`
  170. class MainWindow : public QMainWindow, ITableManager
  171. {
  172. Q_OBJECT
  173. public:
  174. explicit MainWindow(QWidget *parent = 0);
  175. ~MainWindow();
  176. QTableWidget* getTableFromIndex(const int index);
  177. }
  178. QTableWidget * MainWindow::getTableFromIndex(const int index)
  179. {
  180. switch (index)
  181. {
  182. case 1:
  183. return ui-&gt;tableWidget;
  184. case 2:
  185. return ui-&gt;tableWidget_2;
  186. default:
  187. return nullptr;
  188. }
  189. }
  190. Dont forget setup tags (indecies) and table manager for tables (in main window constructor)
  191. ui-&gt;tableWidget-&gt;setTag(1);
  192. ui-&gt;tableWidget_2-&gt;setTag(2);
  193. ui-&gt;tableWidget-&gt;setTableManager(this);
  194. ui-&gt;tableWidget_2-&gt;setTableManager(this);
  195. **EDIT:** If you want change custom pixmap for dragging just set `QDrag::setPixmap`
  196. void DraggableHeaderView::mouseMoveEvent(QMouseEvent *e)
  197. {
  198. if (e-&gt;buttons() &amp; Qt::LeftButton)
  199. {
  200. int index = logicalIndexAt(e-&gt;pos());
  201. QDrag *drag = new QDrag(this);
  202. QMimeData *mimeData = new QMimeData;
  203. QString mimeTxt = &quot;MoveHeader;Table:&quot; + QString::number(m_tag) +
  204. &quot;;Index:&quot; + QString::number(index);
  205. mimeData-&gt;setText(mimeTxt);
  206. drag-&gt;setMimeData(mimeData);
  207. drag-&gt;setPixmap(pixmapForDrag(index));
  208. Qt::DropAction dropAction = drag-&gt;exec();
  209. }
  210. }
  211. And method for taking pixmap of column can be like this
  212. QPixmap DraggableHeaderView::pixmapForDrag(const int columnIndex) const
  213. {
  214. QTableWidget *table = qobject_cast&lt;QTableWidget*&gt; (this-&gt;parentWidget());
  215. if (!table)
  216. {
  217. return QPixmap();
  218. }
  219. //image for first 5 row
  220. int height = table-&gt;horizontalHeader()-&gt;height();
  221. for (int iRow = 0; iRow &lt; 5 &amp;&amp; iRow &lt; table-&gt;rowCount(); ++iRow)
  222. {
  223. height += table-&gt;rowHeight(iRow);
  224. }
  225. //clip maximum size
  226. if (height &gt; 200)
  227. {
  228. height = 200;
  229. }
  230. QRect rect(table-&gt;columnViewportPosition(columnIndex) + table-&gt;verticalHeader()-&gt;width(),
  231. table-&gt;rowViewportPosition(0),
  232. table-&gt;columnWidth(columnIndex),
  233. height);
  234. QPixmap pixmap(rect.size());
  235. table-&gt;render(&amp;pixmap, QPoint(), QRegion(rect));
  236. return pixmap;
  237. }
  238. </details>

huangapple
  • 本文由 发表于 2020年1月6日 23:18:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/59614591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定