Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: neversleep от Август 09, 2011, 08:35



Название: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 08:35
Создаю наследника от QTreeView, задаю модель с двумя колонками, и пытаюсь нарисовать разделительные линии между полями, а также вертикальную линию между колонками.

Cтолкнулся с такой проблемой, скриншот: http://savepic.net/1825769.png

Т.е получается какая-то смазанность линий... Это происходит при изменении размеров колонок, и перемотки по горизонтали (scroll).

И ещё иногда возникает такой глюк: http://savepic.net/1815529.png

Код:
class MyTreeView : public QTreeView
{
public:
    MyTreeView(QWidget *parent = 0) :
        QTreeView(parent)
    {
    }

protected:
    void paintEvent(QPaintEvent *event)
    {
        QTreeView::paintEvent(event);

        QPainter painter;
        painter.begin(viewport());
        painter.save();

        QPen pen(Qt::lightGray);
        pen.setStyle(Qt::DotLine);
        pen.setWidth(2);
        painter.setPen(pen);


        // рисуем вертикальную линию между столбцами
        QLine line(columnWidth(0), 0, columnWidth(0), height());

        painter.drawLine(line);

        painter.restore();
        painter.end();
    }

    void drawRow(QPainter *painter,
                 const QStyleOptionViewItem &options,
                 const QModelIndex &index) const
    {
        QTreeView::drawRow(painter, options, index);

        painter->save();

        QPen pen(Qt::lightGray);
        pen.setStyle(Qt::DotLine);
        pen.setWidth(2);
        painter->setPen(pen);


        // горизонтальная линия между полями
        QLine line(options.rect.left(), options.rect.bottom(),
                   options.rect.right(), options.rect.bottom());

        painter->drawLine(line);

        painter->restore();
    }
};

Помогите разобраться.

ps
Сначала пробовал рисовать из делегата, возникла эта же проблема..


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: AnubiSAD от Август 09, 2011, 09:21
Возможно paintEvent каждый раз тебе перерисовывает линии не удаляя старые. У меня так было как-то. Рисуй линии не в PaintEvent, я делал это в конструкторе.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 09:28
Рисуй линии не в PaintEvent, я делал это в конструкторе.
Вот с этого места по подробней если можно.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 11:00
2 neversleep:
вот так взял и грубо дал ниже пояса троллям) И ещё удивляется откуда глюки)
Для таких вещей нужно задействовать делегаты:
Код
C++ (Qt)
void QStyledItemDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const [virtual]


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: AnubiSAD от Август 09, 2011, 11:05
Да, согласен, не рисовал, конечно, извиняюсь. У меня немного другая ситуация была.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 11:29
2 neversleep:
вот так взял и грубо дал ниже пояса троллям) И ещё удивляется откуда глюки)
Для таких вещей нужно задействовать делегаты:
Код
C++ (Qt)
void QStyledItemDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const [virtual]
Я только начал осваевать Qt :)

Делаю:
Код:
void MyDelegate::paint(QPainter *painter,
  const QStyleOptionViewItem &option,
  const QModelIndex &index) const
{
    QStyledItemDelegate::paint(painter, option, index);

    painter->save();

    QPen pen(Qt::lightGray);
    pen.setStyle(Qt::DotLine);
    pen.setWidth(2);
    painter->setPen(pen);

    QRect rc(option.rect);
    if (index.column() == 0)
        rc.setLeft(0);

    QLine lines[2] = {
        QLine(rc.left(), rc.bottom(), rc.right(), rc.bottom()), // горизонтальная линия снизу
        QLine(rc.right(), rc.top(), rc.right(), rc.bottom())    // верт. линия справа
    };
    painter->drawLines(&lines[0], index.column() == 0 ? 2 : 1);
    painter->restore();
}

Глюк со смазыванием справа снимается, и этот вопрос тоже:
Цитировать
И ещё иногда возникает такой глюк: http://savepic.net/1815529.png

Но с левой стороны все по-прежнему, а если убрать:
Код:
    QRect rc(option.rect);
    if (index.column() == 0)
        rc.setLeft(0);
То всё нормально, только лини рисуются не "от начала" (с лева остаётся пустошь) :)


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 11:45
Цитировать
То всё нормально, только лини рисуются не "от начала" (с лева остаётся пустошь)
Ну и рисуй тогда для первой колонки от 0.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 11:59
Цитировать
То всё нормально, только лини рисуются не "от начала" (с лева остаётся пустошь)
Ну и рисуй тогда для первой колонки от 0.
Заменить "if (index.column() == 0) rc.setLeft(0);" на "if (index.column() == 1) rc.setLeft(0);" Ты это имел ввиду ?  ::)


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 12:03
Да нет не это. Посмотрел внимательно код - ты так и делал.
Покажи скриншот.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 12:18
С глюком: http://savepic.net/1821693.png
Без глюка: http://savepic.net/1824765.png // если убрать ...rc.setLeft(0);


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 12:29
Цитировать
если убрать ...rc.setLeft(0);
А зачем убирать?


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 12:35
Да в том то и дело что не зачем, мне как раз так и надо чтобы линия рисовалась от самого края, с нуля, но тогда происходит размазывание линии если прокручивать по горизонтали, т.е если ширина колонок больше чем ширина дерева. А когда убираю setLeft(0), то смазывания не происходит, и всё в порядке.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 13:03
С не SolidLine всегда сплошные проблемы. Кстати у троллей в QTableView тоже.
Забей и рисуй сплошной линией.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 14:33
Вариант с сплошной линией я тоже рассматривал, как черновой...

Я нашёл решение, нужно устанавливать rc.left относительно позиции горизонтальной полосы прокрутки, т.е rc.setLeft(-horizontalScrollBarPos); Вот только tree->horizontalScrollBar().pos() всегда почему то возвращает QPoint(0,0), т.е нужно самому соединяться с сигналом valueChanged(int) скроллбара и запоминать позицию.

В итоге получилось:
Код:
    ...
    MyTreeView *tree = dynamic_cast<MyTreeView*>(parent());

    QRect rc(option.rect);
    if (index.column() == 0)
        rc.setLeft(-tree->m_hScrollPos);

    ...

Всем спасибо за помощь, вопрос решён.


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 14:49
Так по-проще будет:
Код
C++ (Qt)
MyTreeView *tree = dynamic_cast<MyTreeView*>(parent());
 
   QRect rc(option.rect);
   if (index.column() == 0)
       rc.setLeft(-tree->horizontalScrollBar()->value());


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: neversleep от Август 09, 2011, 14:55
Воо! Спасибо, а я то думал, неужели в Qt всё так плохо :D


Название: Re: QTreeView проблемы с отрисовкой "GridLines"
Отправлено: GreatSnake от Август 09, 2011, 15:01
Воо! Спасибо, а я то думал, неужели в Qt всё так плохо :D
На самом деле могло бы быть и по-лучше.