QTreeView:列是从列调整大小而不是从标题调整大小?

时间:2015-08-30 22:57:31

标签: qt qt4 qt5

有什么方法可以让用户在隐藏标题时以交互方式调整列的大小?

1 个答案:

答案 0 :(得分:3)

您可以在表格的视口中安装事件过滤器,并手动实现所需的行为。以下是一个示例实现。

部首:

#include <QTableView>

class Table_cell_resizer : public QObject {
  Q_OBJECT
public:
  explicit Table_cell_resizer(QTableView *view = 0);

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

private:
  QTableView* m_view;

  //max distance between mouse and a cell, small enough to trigger resize
  int m_sensibility;

  //variables for saving state while dragging
  bool m_drag_in_progress;
  Qt::Orientation m_drag_orientation;
  int m_drag_section;
  int m_drag_previous_pos;

  // check if mouse_pos is around right or bottom side of a cell 
  // (depending on orientation)
  // and return the index of that cell if found
  QModelIndex index_resizable(QPoint mouse_pos, Qt::Orientation orientation);
};

来源:

#include "Table_cell_resizer.h"
#include <QMouseEvent>
#include <QHeaderView>

Table_cell_resizer::Table_cell_resizer(QTableView* view) :
  QObject(view), m_view(view)
{
  m_view->viewport()->installEventFilter(this);
  m_view->viewport()->setMouseTracking(true);
  m_sensibility = 5;
  m_drag_in_progress = false;
}

bool Table_cell_resizer::eventFilter(QObject* object, QEvent* event) {
  if (object == m_view->viewport()) {
    QMouseEvent* mouse_event = dynamic_cast<QMouseEvent*>(event);
    if (mouse_event) {
      if (mouse_event->type() == QEvent::MouseMove) {
        if (m_drag_in_progress) { // apply dragging
          int delta;
          QHeaderView* header_view;
          if (m_drag_orientation == Qt::Vertical) {
            delta = mouse_event->pos().y() - m_drag_previous_pos;
            header_view = m_view->verticalHeader();
            m_drag_previous_pos = mouse_event->pos().y();
          } else if (m_drag_orientation == Qt::Horizontal) {
            delta = mouse_event->pos().x() - m_drag_previous_pos;
            header_view = m_view->horizontalHeader();
            m_drag_previous_pos = mouse_event->pos().x();
          }
          //using minimal size = m_sensibility * 2 to prevent collapsing
          header_view->resizeSection(m_drag_section,
             qMax(m_sensibility * 2, header_view->sectionSize(m_drag_section) + delta));
          return true;
        } else { // set mouse cursor shape
          if (index_resizable(mouse_event->pos(), Qt::Vertical).isValid()) {
            m_view->viewport()->setCursor(Qt::SplitVCursor);
          } else if (index_resizable(mouse_event->pos(), Qt::Horizontal).isValid()) {
            m_view->viewport()->setCursor(Qt::SplitHCursor);
          } else {
            m_view->viewport()->setCursor(QCursor());
          }
        }
      } else if (mouse_event->type() == QEvent::MouseButtonPress &&
                 mouse_event->button() == Qt::LeftButton &&
                 !m_drag_in_progress) { // start dragging
        if (index_resizable(mouse_event->pos(), Qt::Vertical).isValid()) {
          m_drag_in_progress = true;
          m_drag_orientation = Qt::Vertical;
          m_drag_previous_pos = mouse_event->y();
          m_drag_section = index_resizable(mouse_event->pos(), Qt::Vertical).row();
          return true;
        } else if (index_resizable(mouse_event->pos(), Qt::Horizontal).isValid()) {
          m_drag_in_progress = true;
          m_drag_orientation = Qt::Horizontal;
          m_drag_previous_pos = mouse_event->x();
          m_drag_section = index_resizable(mouse_event->pos(), Qt::Horizontal).column();
          return true;
        }
      } else if (mouse_event->type() == QEvent::MouseButtonRelease &&
                 mouse_event->button() == Qt::LeftButton &&
                 m_drag_in_progress) { // stop dragging
        m_drag_in_progress = false;
        return true;
      }
    }
  }
  return false;
}

QModelIndex Table_cell_resizer::index_resizable(QPoint mouse_pos, Qt::Orientation orientation) {
  QModelIndex index = m_view->indexAt(mouse_pos - QPoint(m_sensibility + 1, m_sensibility + 1));
  if (index.isValid()) {
    if (orientation == Qt::Horizontal) {
      if (qAbs(m_view->visualRect(index).right() - mouse_pos.x()) < m_sensibility &&
          m_view->horizontalHeader()->sectionResizeMode(index.column()) == QHeaderView::Interactive) {
        return index;
      }
    } else {
      if (qAbs(m_view->visualRect(index).bottom() - mouse_pos.y()) < m_sensibility &&
          m_view->verticalHeader()->sectionResizeMode(index.row()) == QHeaderView::Interactive) {
        return index;
      }
    }
  }
  return QModelIndex();
}

用法:

new Table_cell_resizer(ui->table);

除了标题区域之外,用户现在可以使用单元格区域调整行和列的大小。如果您愿意,可以隐藏标题。此实现遵循标头大小调整模式,因此请确保将调整大小模式设置为QHeaderView::Interactive,以用于要调整大小的标头。例如,您可以将水平标题模式设置为Interactive,将垂直标题模式设置为Fixed,从而生成可调整大小的列和固定行。