Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Visario от Июль 23, 2008, 15:16



Название: QSplitter, QListView и их ресайз.
Отправлено: Visario от Июль 23, 2008, 15:16
Есть QSplitter и он контролирует кастомного QListView.
При этом gridSize подстраивается под высоту этого view в resizeEvent(), и если сделать view->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded), то иногда возникает бесконечный цикл:
0. убирается скроллбар, так как все элементы влезают
1. gridSize увеличивается, т.к. места стало больше
2. контент перестает влезать и пояляется скроллбар
3. gridSize уменьшается и возвращаемся к пункту 0.

Пробовал делать setSizes() сплиттеру, когда размер оказывался в "опасной зоне", но это выглядело ужасно, так как сплиттер все еще в движении и курсор мыши все еще над "опасной зоной".
Перегрузка moveSplitter и closestLegalPosition тоже не помогла, так как они не виртуальны =(

Как лучше разрулить эти ситуацию?


Название: Re: QSplitter, QAbstractItemView и их ресайз.
Отправлено: pastor от Июль 23, 2008, 22:21
Былобы неплохо увидеть код, и воспроизвесть все это у себя


Название: Re: QSplitter, QAbstractItemView и их ресайз.
Отправлено: ритт от Июль 23, 2008, 23:15
а имеет ли смысл менять gridSize сразу по изменении размеров? может сделать это отложенным методом (по таймеру, например) ? - и циклить тогда не будет


Название: Re: QSplitter, QAbstractItemView и их ресайз.
Отправлено: Visario от Июль 24, 2008, 08:13
Былобы неплохо увидеть код, и воспроизвесть все это у себя


Код:
#include <QtCore>
#include <QtGui>

class ItemDelegate: public QAbstractItemDelegate {
public:
ItemDelegate(QListView *view): QAbstractItemDelegate(view) {
mView = view;
}

protected:
virtual QSize sizeHint( const QStyleOptionViewItem &, const QModelIndex &) const {
return mView->gridSize();
}

virtual void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
QRect rect = option.rect;
painter->setPen(Qt::white);
int v = (index.column() + 1) * (index.row() + 1) * 1.5;
painter->setBrush(QColor(qMin(255, v*v/2), qMin(255, v*v), qMin(255, v*2)));
painter->drawRect(rect);
}

private:
QListView *mView;
};

class ListView : public QListView {
public:
ListView(QWidget *parent = 0)
: QListView(parent) {
setViewMode(QListView::IconMode);
setResizeMode(QListView::Adjust);
setUniformItemSizes(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setWrapping(false);
setItemDelegate(mDelegate = new ItemDelegate(this));
}

~ListView() {
delete mDelegate;
}

protected:
virtual void resizeEvent(QResizeEvent * event) {
QListView::resizeEvent(event);

int sbExt = horizontalScrollBar()->isVisible() ? horizontalScrollBar()->sizeHint().height() : 0;
int gridSize = height() - sbExt;
setGridSize(QSize(gridSize, gridSize));
qDebug() << "resizeEvent" << gridSize;
}

private:
ItemDelegate *mDelegate;
};


int main(int argc, char *argv[]) {
QApplication app(argc, argv);

QStringListModel *model = new QStringListModel();
QStringList list = QString("abcdefg1234567").split("");
model->setStringList(list);

ListView *view = new ListView();
view->setModel(model);
view->resize(800, 80);
view->show();
return app.exec();
 }

После запуска, нужно немного уменьшить высоту, чтобы все элементы влезли.


Название: Re: QSplitter, QAbstractItemView и их ресайз.
Отправлено: Visario от Июль 24, 2008, 08:28
а имеет ли смысл менять gridSize сразу по изменении размеров? может сделать это отложенным методом (по таймеру, например) ? - и циклить тогда не будет

Смысл менять gridSize сразу есть.
Не пробовал с таймером, но думаю, что это не поможет, т.к. размер будет скакать по таймеру.

Тут нужно как-то избежать определенных размеров (optSize = width() / rowCount() < height() < optSize + sbExt). В примере сверху можно было бы просто вызвать resize() с безопасным размером, но со сплиттером это не поможет.

Пофиксенная версия main функции:
Код:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);

QStringListModel *model = new QStringListModel();
QStringList list = QString("abc1234567").split("");
model->setStringList(list);

ListView *view = new ListView();
view->setModel(model);

QSplitter splitter(Qt::Vertical);
splitter.addWidget(new QWidget());
splitter.addWidget(view);
splitter.resize(800, 140);
splitter.show();
return app.exec();
 }