Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ Вопрос по функции drawText

Автор: AD 28.7.2009, 14:42

У объекта painter есть функция отрисовки текста. Каким образом можно заставить ее затирать прежнее значение? При отрисовке значения пересечения визира с графиков значение выводится несколько(а то и несколько сот) раз, из-за чего в итоге не разобрать значения.
И опять же сдвиг точки, что не радует.... :(
[attachment=724:test1.JPG]

Автор: ufna 28.7.2009, 15:22

нужно рисовать в риал-тайме и делать апдейт регионов, где рисовал при перерисовке.

покажи код как рисуешь.

Автор: kwisp 28.7.2009, 15:28

AD,
пользуй не просто drawText а
fillRect
затем
drawText() в тотже rect что и затер фоном:)

Автор: AD 28.7.2009, 15:32

Цитата(ufna @ 28.7.2009, 16:22) *
нужно рисовать в риал-тайме и делать апдейт регионов, где рисовал при перерисовке.

покажи код как рисуешь.

:) Ну реальное время в данном контексте немного странно звучит. Конечно, перерисовку делаю.
/// Отрисовка графика
void GraphicDisplay::paintEvent(QPaintEvent* events)
{
    painter.begin(this);

    painter.setWindow(paramsDisplay -> rect());
    painter.setFont(QFont("Tahoma", 8, Qt::SolidLine));
    painter.setPen(Qt::black);

    drawGrid(&painter);
    drawCurves(&painter);

    painter.end();
}

/// Отрисовка графика
void GraphicDisplay::drawCurves(QPainter* painter)
{
// .....
                    painter -> drawLine(polyline.last(), pnt),
                    viewCoordViewfinder(painter, data, j, pnt);
// ......
}

/// Отображение координат пересечения с визиром
void GraphicDisplay::viewCoordViewfinder(QPainter* painter, const QVector<SpecPointF>& data, int index,
                                        const QPointF& pnt)
{
    if(!v_viewfinderAction -> isChecked() && !h_viewfinderAction -> isChecked())
        return;
    double graphic_x = data[index].x(), graphic_y = data[index].y();
    foreach(VFFrame* pf, viewfinderList)
    {
        int frame_x = pf -> x(), frame_y = pf -> y();
        double graph_x = pnt.x(), graph_y = pnt.y();
        if(pf -> frameShape() == QFrame::VLine && v_viewfinderAction -> isChecked())
            if(fabs(frame_x - graph_x) <= 3.)
            {
                QPointF coord(pnt.x() + 40., pnt.y() - 1.);
                QPen oldPen(painter -> pen());
                painter -> setPen(Qt::black);
                painter -> setBrush(oldPen.color());
                QRect cycle_rect(QPoint(pnt.x() - 1, pnt.y() - 1),
                                 QPoint(pnt.x() + 1, pnt.y() + 1));
                painter -> drawEllipse(cycle_rect);
                painter -> drawText(coord, QString::number(graphic_y));
                painter -> setPen(oldPen);
            }
        // ..................
    }    
}

Автор: AD 28.7.2009, 17:15

Пока ничего не помогло. filRect - не помог.

Автор: kwisp 29.7.2009, 9:09

AD,
как так не помогло.
???

m_painter->begin(this);
m_painter->fillRect(CSKMain::cellRects[CSKSession::e_TIME],CSKConf::colorByStation(pointState));
m_painter->setFont(CSKConf::time_font());
m_painter->drawText(CSKMain::cellRects[CSKSession::e_TIME],Qt::AlignCenter,point->Time().toString(CSKConf::timeFormat));
m_painter->end();

где
CSKMain::cellRects[CSKSession::e_TIME] - QRect области рисования текста
CSKConf::colorByStation(pointState) - цвет фона (у тебя это может быть кусок картинки фона)
CSKConf::time_font() - цвет времени
point->Time().toString(CSKConf::timeFormat) - QString времени

Автор: AD 30.7.2009, 11:18

Возможно, я и ошибся, возможно, руки кривоваты. А может быть, что при большом масштабе, точки пересечения, находящиеся рядом накладываются друг на друга, или же не точка пересечения, распознать такие ситуации не очень знаю как - чтобы выделять точки начала и конца отрезка. При приближении вырисовывается нормально, но при сильном приближении точка исчезает. Видимо условие

if(fabs(frame_x - graph_x) <= 3.)
дает ложь. Алгоритм не очень хороший, насколько мне видно. Как его изменить на более предсказуемый, пока не знаю!

Автор: AD 30.7.2009, 12:00

Основное непонимание, почему есть сдвиг между положением визира и отрисовываемой точкой. Как определить, что имеется пересечение отрезком.

Автор: AD 30.7.2009, 14:53

Никак не могу понять, почему есть смещение рисуемой точки от визира? Подскажите, пожалуйста, где возможна ошибка?

Автор: AD 31.7.2009, 11:07

kwisp, посмотрел более внимательно, fillRect() действительно помог, я ошибся. Спасибо. Задача разнести текст при большом масштабе, когда точки находятся рядом. Сделать отметку точек ровно в точке пересечения, а не со смещением. Пока что у меня это не получается.

Автор: kwisp 31.7.2009, 12:25

AD,
как бы всё для этого есть.
всякие там
QRect QRect::intersected ( const QRect & rectangle ) const
и проч.

Автор: Litkevich Yuriy 31.7.2009, 18:12

Тему разделил: http://www.forum.crossplatform.ru/index.php?showtopic=3198

Автор: AD 5.8.2009, 15:00

Получилось сделать корректное отображение пересечение графика с визиром.
Вот что получилось.

График кривой без сглаживания:
[attachment=725:graphic_...moothing.JPG]

График кривой со сглаживанием:
[attachment=726:graphic_...moothing.JPG]

Выложу код, вдруг, все-таки пригодится кому-нибудь. Если что, смогу и объяснить, где что в коде делается!

Пересечение с визиром

/// Получение размерностей заданной по id кривой
QPointF GraphicDisplay::dimensions(int id)
{
    QString x_dimension(fact_prm[id].dimension[language_flag].toLower());
    double x_dim = (metric_map[x_dimension]) ? metric_map[x_dimension] : 1.0;
    QString y_dimension(fact_prm[id].y_dim[language_flag].toLower());
    double y_dim = (metric_map[y_dimension]) ? metric_map[y_dimension] : 1.0;
    return QPointF(x_dim, y_dim);
}

/// Поиск точки пересечения визира с графиком (в реальных координатах - следует переводить в экранные)
QPointF GraphicDisplay::findCrossPoint(const QPointF& pnt, const QPointF& prev_pnt, const QPointF& pnt_vf)
{
    double    curr_x = pnt.x(), curr_y = pnt.y(), prev_x = prev_pnt.x(), prev_y = prev_pnt.y(), y_vf = pnt_vf.y(),
            x_vf = pnt_vf.x();
    double    y = prev_y + (curr_y - prev_y) * (x_vf - prev_x) / (curr_x - prev_x),
            x = prev_x + (curr_x - prev_x) * (y_vf - prev_y) / (curr_y - prev_y);
    if(curr_y - prev_y == 0.) x = curr_x;
    if(curr_x - prev_x == 0.) y = curr_y;

    return QPointF(x, y);
}

/// Отображение текста точки пересечения визира с графиком
void GraphicDisplay::drawViewfinderText(QPainter* painter, const QPointF& coord, const QPen& pen,
                                        double coordinate)
{
    QBrush oldBrush(pen.color());
    QPen oldPen(pen.color());
    painter -> setBrush(pen.color());
    QColor color((pen.color() == QColor(Qt::blue)) ? Qt::darkGreen : Qt::blue);
    painter -> setPen(color);
    painter -> drawText(coord, QString::number(coordinate));
    painter -> setPen(oldPen);
    painter -> setBrush(oldBrush);
}

/// Отображение координат пересечения с визиром
void GraphicDisplay::viewCoordViewfinder(QPainter* painter, int id, const QVector<SpecPointF>& data, int index)
{
    if(!v_viewfinderAction -> isChecked() && !h_viewfinderAction -> isChecked()) return;
    QPointF dim(dimensions(id));
    double    real_y = data[index].y(), prev_ry = data[index - 1].y(),
            real_x = (settings.win_type != COUNTPARAM) ? data[index].x() * dim.x() : data[index].x(),
            prev_rx = (settings.win_type != COUNTPARAM) ? data[index - 1].x() * dim.x() : data[index - 1].x();
    QPointF pnt(initXY(real_x, real_y)), prev_pnt(initXY(prev_rx, prev_ry)), rl_pnt(real_x, real_y),
            prev_rl_pnt(prev_rx, prev_ry);
    foreach(VFFrame* pf, viewfinderList)
    {
        QPoint screen_pnt_vf(pf -> x(), pf -> y());
        QPointF pnt_vf(initXY(&screen_pnt_vf));
        double prev_x = prev_rl_pnt.x(), prev_y = prev_rl_pnt.y(), curr_x = rl_pnt.x(), curr_y = rl_pnt.y();
        double x_vf = pnt_vf.x(), y_vf = pnt_vf.y();
        QPointF res_point(findCrossPoint(rl_pnt, prev_rl_pnt, pnt_vf));
        double result_x = res_point.x(), result_y = res_point.y();
        QPointF crd_scr(initXY(result_x, result_y));
        if(pf -> frameShape() == QFrame::VLine && v_viewfinderAction -> isChecked() &&
            prev_x <= x_vf && curr_x > x_vf)
        {
            QPointF coord(pf -> x() + 15, crd_scr.y() - 1.);
            drawViewfinderText(painter, coord, painter -> pen(), res_point.y());
        }
        else if(pf -> frameShape() == QFrame::HLine && h_viewfinderAction -> isChecked() &&
            prev_y <= y_vf && curr_y > y_vf)
        {
            QPointF coord(crd_scr.x() - 1., pf -> y() - 15.);
            drawViewfinderText(painter, coord, painter -> pen(), res_point.x());
        }
    }
}

/// Отрисовка графика
void GraphicDisplay::drawCurves(QPainter* painter)
{
    if(!paramsDisplay -> rect().isValid()) return;
    painter -> setClipRect(paramsDisplay -> rect().adjusted(1, 1, -1, -1));

    QMapIterator<int, QVector<SpecPointF>> iter(curveMap);
    int k = 1;
    bool smoothing = valueElement("diagramSmooth", false).toBool();
    while(iter.hasNext())
    {
        iter.next();        int id = iter.key();
        if(fact_prm.size() == 0 || id >= fact_prm.size()) break;
        if(settings.win_type != fact_prm[id].type) continue;
        QPointF dim(dimensions(id));
        setColorPen(painter, id);

        const QVector<SpecPointF>& data = iter.value();
        QPolygonF polyline(0);
        for(int j=0; j<data.size(); ++j)
        {
            if(!isExistPhase(data[j])) continue;

            double x = (settings.win_type != COUNTPARAM) ? data[j].x() * dim.x() : data[j].x();
            double y = data[j].y() * dim.y();
            QPointF pnt(initXY(x, y));
            if(!polyline.isEmpty())
            {
                if(smoothing && pnt.x() <= polyline.last().x()) continue;
                setPenForLine(j);
                painter -> setPen(myPen);
                if(j > 0 && isExistPhase(data[j - 1]))
                    painter -> drawLine(polyline.last(), pnt),
                    viewCoordViewfinder(painter, id, data, j);
                polyline.append(pnt);
            }
            else polyline.append(pnt);
        }
        drawLegend(painter, paramsDisplay -> rect(), k, id);
    }
}


Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)