Вообще, QHeaderView при широких секциях работает криво:
1) Перетаскивание - широкие секции не всегда перетаскиваются
2) Горизонтальный скроллер у QTableView глючит при малой ширине QTableView
По хорошему его надо полностью переписывать.
Вот пример кода с автоскроллингом.
MyTableView->setHorizontalHeader(new THorHeader (MyTableView));
.h C++ (Qt)
class THorHeader : public QHeaderView
{
Q_OBJECT
protected:
static int OffsetIdent;
static int OffsetCount;
static int MinInterval;
protected:
QTableView* TableView;
QTimer Timer;
int OffsetSpeed;
int SpeedCounter;
public:
explicit THorHeader(QTableView* TableView);
virtual ~THorHeader();
protected:
explicit THorHeader(Qt::Orientation orientation, QWidget *parent = 0);
virtual void mouseMoveEvent(QMouseEvent* e);
virtual void mouseReleaseEvent(QMouseEvent* e);
void updateOffset(int offset);
bool canMove(int value);
protected slots:
void onTimeout(void);
};
.cpp C++ (Qt)
int THorHeader::OffsetIdent = 16;
int THorHeader::OffsetCount = 10;
int THorHeader::MinInterval = 100;
THorHeader::THorHeader(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent) {
TableView = NULL;
}
THorHeader::THorHeader(QTableView* TableView) : QHeaderView(Qt::Horizontal, TableView) {
this->TableView = TableView;
OffsetSpeed = 0;
setMovable(true);
setMouseTracking(true);
QObject::connect(&Timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
THorHeader::~THorHeader() {}
void THorHeader::mouseMoveEvent(QMouseEvent* e) {
QHeaderView::mouseMoveEvent(e);
if(!TableView) {return;}
if(e->buttons() != Qt::LeftButton) {return;}
if (e->pos().x() <= -OffsetIdent) {updateOffset(e->pos().x()/OffsetIdent);}
else if(e->pos().x() >= width()+OffsetIdent) {updateOffset((e->pos().x()-width())/OffsetIdent);}
else {updateOffset(0);}
}
void THorHeader::mouseReleaseEvent(QMouseEvent* e) {
if(Timer.isActive()) {Timer.stop();}
QHeaderView::mouseReleaseEvent(e);
}
void THorHeader::updateOffset(int offset) {
int NewOffsetSpeed;
if(offset < -OffsetCount) {offset = -OffsetCount;}
if(offset > OffsetCount) {offset = OffsetCount;}
if (!offset) {NewOffsetSpeed = 0;}
else if(offset > 0) {NewOffsetSpeed = OffsetCount + 1 - offset;}
else {NewOffsetSpeed = -OffsetCount - 1 - offset;}
if(OffsetSpeed == NewOffsetSpeed) {return;}
if(!NewOffsetSpeed) {
if(Timer.isActive()) {Timer.stop();}
OffsetSpeed = 0;
return;
}
if(!Timer.isActive()) {
OffsetSpeed = NewOffsetSpeed;
SpeedCounter = (OffsetSpeed > 0)?OffsetSpeed:-OffsetSpeed;
if(canMove(TableView->horizontalScrollBar()->value())) {
onTimeout();
Timer.start(MinInterval);
}
} else {
int NewSpeedCounter = (NewOffsetSpeed > 0)?NewOffsetSpeed:-NewOffsetSpeed;
int OldSpeedCounter = (OffsetSpeed > 0)?OffsetSpeed:-OffsetSpeed;
OffsetSpeed = NewOffsetSpeed;
SpeedCounter += NewSpeedCounter - OldSpeedCounter;
if(SpeedCounter <= 0) {onTimeout();}
}
}
bool THorHeader::canMove(int value) {
if(OffsetSpeed > 0) {
if(value >= TableView->horizontalScrollBar()->maximum()) {return false;}
} else {
if(value <= TableView->horizontalScrollBar()->minimum()) {return false;}
}
return true;
}
void THorHeader::onTimeout(void) {
QApplication::processEvents();
SpeedCounter--;
if(SpeedCounter > 0) {return;}
SpeedCounter = (OffsetSpeed > 0)?OffsetSpeed:-OffsetSpeed;
int value = TableView->horizontalScrollBar()->value();
if(!canMove(value)) {
Timer.stop();
return;
}
if(OffsetSpeed > 0) {++value;}
else {--value;}
TableView->horizontalScrollBar()->setValue(value);
}