QTreeView:从列而不是 headers 调整列大小?
QTreeView: column resize from columns and not from headers?
当 headers 被隐藏时,是否有任何方法允许用户以交互方式调整列的大小?
您可以在 table 的视口上安装事件过滤器并手动实现所需的行为。下面是一个示例实现。
Header:
#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);
除 header 区域外,用户现在还可以使用单元格区域调整行和列的大小。如果您愿意,可以隐藏 headers。此实现遵循 header 调整大小模式,因此请确保将要调整大小的 header 的调整模式设置为 QHeaderView::Interactive
。例如,您可以将水平 header 模式设置为 Interactive
,将垂直 header 模式设置为 Fixed
,从而产生可调整大小的列和固定的行。
当 headers 被隐藏时,是否有任何方法允许用户以交互方式调整列的大小?
您可以在 table 的视口上安装事件过滤器并手动实现所需的行为。下面是一个示例实现。
Header:
#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);
除 header 区域外,用户现在还可以使用单元格区域调整行和列的大小。如果您愿意,可以隐藏 headers。此实现遵循 header 调整大小模式,因此请确保将要调整大小的 header 的调整模式设置为 QHeaderView::Interactive
。例如,您可以将水平 header 模式设置为 Interactive
,将垂直 header 模式设置为 Fixed
,从而产生可调整大小的列和固定的行。