Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по функции drawText
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Система рисования. Печать
AD
У объекта painter есть функция отрисовки текста. Каким образом можно заставить ее затирать прежнее значение? При отрисовке значения пересечения визира с графиков значение выводится несколько(а то и несколько сот) раз, из-за чего в итоге не разобрать значения.
И опять же сдвиг точки, что не радует.... :(
Нажмите для просмотра прикрепленного файла
ufna
нужно рисовать в риал-тайме и делать апдейт регионов, где рисовал при перерисовке.

покажи код как рисуешь.
kwisp
AD,
пользуй не просто drawText а
fillRect
затем
drawText() в тотже rect что и затер фоном:)
AD
Цитата(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
Пока ничего не помогло. filRect - не помог.
kwisp
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
Возможно, я и ошибся, возможно, руки кривоваты. А может быть, что при большом масштабе, точки пересечения, находящиеся рядом накладываются друг на друга, или же не точка пересечения, распознать такие ситуации не очень знаю как - чтобы выделять точки начала и конца отрезка. При приближении вырисовывается нормально, но при сильном приближении точка исчезает. Видимо условие
if(fabs(frame_x - graph_x) <= 3.)
дает ложь. Алгоритм не очень хороший, насколько мне видно. Как его изменить на более предсказуемый, пока не знаю!
AD
Основное непонимание, почему есть сдвиг между положением визира и отрисовываемой точкой. Как определить, что имеется пересечение отрезком.
AD
Никак не могу понять, почему есть смещение рисуемой точки от визира? Подскажите, пожалуйста, где возможна ошибка?
AD
kwisp, посмотрел более внимательно, fillRect() действительно помог, я ошибся. Спасибо. Задача разнести текст при большом масштабе, когда точки находятся рядом. Сделать отметку точек ровно в точке пересечения, а не со смещением. Пока что у меня это не получается.
kwisp
AD,
как бы всё для этого есть.
всякие там
QRect QRect::intersected ( const QRect & rectangle ) const
и проч.
Litkevich Yuriy
Тему разделил: Вращение текста в графическом представлении
AD
Получилось сделать корректное отображение пересечение графика с визиром.
Вот что получилось.

График кривой без сглаживания:
Нажмите для просмотра прикрепленного файла

График кривой со сглаживанием:
Нажмите для просмотра прикрепленного файла

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

/// Получение размерностей заданной по 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);
    }
}

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.