Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Грамотная отрисовка рельефа
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Система рисования. Печать
AD
Запутался, не знаю как решить следующую проблему. Необходимо под графиком, который уже нарисован нарисовать рельеф. Отрисовка рельефа должна происходить всего один раз. Т.е. при рисовании в методе paintEvent() естественно эта штуковина нещадно грузит систему. Делаю вызов этой функции в другом месте, но тогда вообще ничего не рисуется (возможно, потому что использую QPainter для получения цвета "кисти" и "карандаша"). Помогите, пожалуйста.
Код самого рисования правилен, вопрос в том, как заставить рисовать не вызывая данную функцию в paintEvent()?
/// Отрисовка рельефа
void ReliefGraphics::drawTrackRelief()
{
    for(QVector<QPointF>::iterator rlfPnt=relief_vec.begin(), i_prev=relief_vec.begin(); rlfPnt!=relief_vec.end();
        ++rlfPnt)
    {
        QPointF cur(*rlfPnt), prev(*i_prev);
        drawReliefNature(&painter, cur, prev);
        if(rlfPnt != relief_vec.begin()) ++i_prev;
    }
}

/// Настройка цвета рельефа (естественный цвет)
void ReliefGraphics::drawReliefNature(QPainter* painter, QPointF cur, QPointF prev)
{
    double distance = cur.x(), delta_height = cur.y();
    QPointF scrPnt(initXY(distance, delta_height));
    if(delta_height <= 0 || scrPnt.y() >= settings -> maxY)
        return;

    QColor color(demGetColor(demCalcColor(delta_height)));
    double delta_height0;
    int div = delta_height > 1000 ? 50 : 5;
    int i = (int)(delta_height / div);
    if(!((int)delta_height % div)) --i;
    delta_height0 = div * i;
    double prev_dist = prev.x(), prev_height = prev.y();
    QPointF screenPoint(initXY(distance, delta_height0)), scrPrev(initXY(prev_dist, prev_height));

    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setBrush(QBrush(color));
    painter -> setPen(QPen(color));
    painter -> drawLine(scrPrev, screenPoint);
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
    QPointF cur0(distance, delta_height0);
    drawReliefNature(painter, cur0, cur);
}


В итоге получается картинка, подобная этой (такая картинка и должна получаться):Нажмите для просмотра прикрепленного файла
AD
Кто-нибудь сможет помочь? Вопрос состоит в том, где правильно использовать функцию drawTrackRilief() или же как сделать так, чтобы не использовать QPainter и отрисовывать другими средствами. Буду благодарен за любую помощь.
AD
Тут почитал многое и понял, что эту функцию я могу использовать только в paintEvent()! Но еще кое-что заметил и понял, что по сути ее следует вызывать, только при изменении размеров окна. Вопрос такой можно ли сделать так, чтобы один и тот же QPainter painter в одних функциях рисовал сразу на экран, а в других рисовал бы в битмап, который бы перерисовывался при изменении размеров. Кто хочет помочь, прошу помогите пожалуйста.
Вот код отрисовки:
source
/// Настройка цвета рельефа (естественный цвет)
void ReliefGraphics::drawReliefNature(QPainter* painter, QPointF cur, QPointF prev)
{
    double distance = cur.x(), delta_height = cur.y();
    QPointF scrPnt(initXY(distance, delta_height));
    if(delta_height <= 0 || scrPnt.y() >= settings -> maxY)
        return;

    QColor color(demGetColor(demCalcColor(delta_height)));
    double delta_height0;
    int div = delta_height > 1000 ? 50 : 5;
    int i = (int)(delta_height / div);
    if(!((int)delta_height % div)) --i;
    delta_height0 = div * i;
    double prev_dist = prev.x(), prev_height = prev.y();
    QPointF screenPoint(initXY(distance, delta_height0)), scrPrev(initXY(prev_dist, prev_height));

    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setBrush(QBrush(color));
    painter -> setPen(QPen(color));
    painter -> drawLine(scrPrev, screenPoint);
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
    QPointF cur0(distance, delta_height0);
    drawReliefNature(painter, cur0, cur);
}

/// Отрисовка черной линии рельефа для лучшей видимости его изгибов
void ReliefGraphics::drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine)
{
    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setPen(Qt::black);
    painter -> setBrush(Qt::black);
    for(int i=vecBLine.size()-1, j=vecBLine.size()-1; i>=0; --i)
    {
        painter -> drawLine(vecBLine[i], vecBLine[j]);
        if(i != vecBLine.size() - 1) --j;
    }
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
}

/// Отрисовка рельефа
void ReliefGraphics::drawTrackRelief()
{
    QVector<QPointF> vecBLine;
    for(QVector<QPointF>::iterator rlfPnt=relief_vec.begin(), i_prev=relief_vec.begin(); rlfPnt!=relief_vec.end();
        ++rlfPnt)
    {
        QPointF cur(*rlfPnt), prev(*i_prev);
        double X = cur.x(), Y = cur.y(), prevX = prev.x(), prevY = prev.y();
        QPointF screen(initXY(X, Y));
        drawReliefNature(&painter, cur, prev);
        if(rlfPnt != relief_vec.begin()) ++i_prev;
        vecBLine.append(screen);
    }
    drawBlackLineRelief(&painter, vecBLine);
}

/// Отрисовка графика
void ReliefGraphics::paintEvent(QPaintEvent* events)
{
    painter.begin(this);

    QRect rect(displayRelief -> rect());
    painter.setWindow(displayRelief -> rect());
    painter.setFont(QFont("Tahoma", 6, Qt::SolidLine));
    painter.setPen(Qt::black);

    if(param_vec.size() <= count_logrecords && coords_vec.size() <= count_logrecords && fill_axis <= 3)
    {
        int sz = coords_vec.size(), sz1 = param_vec.size(), sz2 = relief_vec.size();
        setPlotValues();
        initParamVec();
        if(param_vec.size() == count_logrecords && coords_vec.size() == count_logrecords)
            ++fill_axis;
    }
    initCurve();

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

    painter.end();
}


Буду благодарен за любой совет и помощь. Очень прошу хоть кого-нибудь откликнуться и постараться помочь в столь нетривиальной задачке!
Litkevich Yuriy
Цитата(AD @ 3.12.2008, 13:56) *
и тот же QPainter painter
а почему один и тот же?
AD
Цитата(Litkevich Yuriy) *
а почему один и тот же?

Тогда вопрос поставлю по другому, а в одном paintEvent() можно использовать несколько QPainter? Если можно, то можно небольшие примерчики?
Litkevich Yuriy
Цитата(AD @ 3.12.2008, 14:34) *
можно использовать несколько QPainter?
а в любой другой функции можно создавать несколько экземпляров одного и того же типа? ;)
AD
Цитата(Litkevich Yuriy @ 3.12.2008, 12:33) *
а в любой другой функции можно создавать несколько экземпляров
одного и того же типа? ;)

Можно. Ну хорошо, раз мне не доверяешь, можешь привести пример, чтобы 2 или более объектов QPainter, пожалуйста?
AD
Дошло как можно это безобразие организовать - через дополнительный параллельный поток. Ведь в потоке я имею право использовать QPainter? Если что, поможете? Естественно, я буду приводить код...

Один из первых вопрос по потокам такой - можно ли использовать в потоке указатель на QPainter, если он объявлен в главном потоке. Если нельзя, то как сделать можно? Буду благодарен за помощь!
AD
Перенес в доп. поток. Вот так это все выглядит:
relief

#ifndef THREAD_H_055
#define THREAD_H_055

#include <QThread>
#ifdef Q_WS_WIN
    #pragma once
#endif // Q_WS_WIN

#include <QPainter>
#include <QDockWidget>
#include <QPointF>
#include <QVector>

class PlotSettings;

/// Класс параллельного потока для отрисовки рельефа вертикальной проекции
class VThread: public QThread
{
    Q_OBJECT

private:
    QPainter painter;                ///< рисовальщик
    QDockWidget* relief_widget;        ///< указатель на виджет, где будет отрисовываться рельеф
    int count_read;                    ///< количество прочитанных элементов
    PlotSettings* settings;            ///< указатель на настройки для различных масштабов
    QVector<QPointF> relief_vec;    ///< вектор геграфических точек рельефа
    QRect rect;                        ///< прямоугольная область, в которой будет производиться рисование

private:
    QPointF initXY(double& sx, double& sy);
    void drawReliefNature(QPainter* painter, QPointF cur, QPointF prev);
    void drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine);
    void drawCurves(QPainter* painter);
    void drawTrackRelief(QPainter* painter);

protected:
    virtual void run();

public:
    VThread(): relief_widget(0), count_read(0), settings(0) {}
    VThread(QDockWidget* rlf_widget): painter(rlf_widget), relief_widget(rlf_widget), count_read(0), settings(0) {}
    ~VThread() {}
    void widget(QDockWidget* rlf_widget) { relief_widget = rlf_widget; }
    QDockWidget* widget() { return relief_widget; }
    void count(const int r) { count_read = r; }
    const int count() { return count_read; }
    void init(PlotSettings* s, QRect& rct) { settings = s; rect = rct; }
    void init(PlotSettings* s) { settings = s; }
    void init(QRect& rct) { rect = rct; }
    void initVec(QVector<QPointF>& rv) { relief_vec = rv; }
    void stop(const int size) { if(count_read == size) quit(); }
};

#endif // THREAD_H_055


#include "Thread.h"
#include <QtGui>

/// Инициализация координат - преобразование из координат графика (sx,sy) в экранные (x,y)
QPointF VThread::initXY(double& sx, double& sy)
{
    const int shift_x = 30;
    if(!rect.isValid()) return QPointF();
    QRect rect_shift(rect);        rect_shift.setLeft(rect_shift.left() + shift_x);
    double dx, dy;

    dx = sx - settings -> minX;
    dy = sy - settings -> minY;
    double x = rect_shift.left() + (dx * (rect_shift.width() - 1) / settings -> spanX());;
    double y = rect.bottom() - (dy * (rect.height() - 1) / settings -> spanY());

    return QPointF(x, y);
}

/// Настройка цвета рельефа (естественный цвет)
void VThread::drawReliefNature(QPainter* painter, QPointF cur, QPointF prev)
{
    double distance = cur.x(), delta_height = cur.y();
    QPointF scrPnt(initXY(distance, delta_height));
    if(delta_height <= 0 || scrPnt.y() >= settings -> maxY)
        return;

    QColor color(demGetColor(demCalcColor(delta_height)));
    double delta_height0;
    int div = delta_height > 1000 ? 50 : 5;
    int i = (int)(delta_height / div);
    if(!((int)delta_height % div)) --i;
    delta_height0 = div * i;
    double prev_dist = prev.x(), prev_height = prev.y();
    QPointF screenPoint(initXY(distance, delta_height0)), scrPrev(initXY(prev_dist, prev_height));

    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setBrush(QBrush(color));
    painter -> setPen(QPen(color));
    painter -> drawLine(scrPrev, screenPoint);
    for(int ix=scrPrev.x()+1; ix<screenPoint.x(); ++ix)
        painter -> drawLine(QPointF(ix, scrPrev.y()), screenPoint);
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
    QPointF cur0(distance, delta_height0);
    drawReliefNature(painter, cur0, cur);
}

/// Отрисовка черной линии рельефа для лучшей видимости его изгибов
void VThread::drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine)
{
    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setPen(Qt::black);
    painter -> setBrush(Qt::black);
    for(int i=vecBLine.size()-1, j=vecBLine.size()-1; i>=0; --i)
    {
        painter -> drawLine(vecBLine[i], vecBLine[j]);
        if(i != vecBLine.size() - 1) --j;
    }
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
}

/// Отрисовка рельефа
void VThread::drawTrackRelief(QPainter* painter)
{
    QVector<QPointF> vecBLine;
    int size = relief_vec.size();
    for(QVector<QPointF>::iterator rlfPnt=relief_vec.begin(), i_prev=relief_vec.begin(); rlfPnt!=relief_vec.end();
        ++rlfPnt, ++count_read)
    {
        usedRlfSpace.acquire();
        QPointF cur(*rlfPnt), prev(*i_prev);
        double X = cur.x(), Y = cur.y(), prevX = prev.x(), prevY = prev.y();
        QPointF screen(initXY(X, Y));
        drawReliefNature(painter, cur, prev);
        if(rlfPnt != relief_vec.begin()) ++i_prev;
        usedRlfSpace.release();
        vecBLine.append(screen);
    }
    drawBlackLineRelief(painter, vecBLine);
}

/// Запуск дополницельного потока
void VThread::run()
{
    drawTrackRelief(&painter);
}

ReliefGraphics::ReliefGraphics(QWidget *parent): settings(0), main_window(0), fill_axis(0), count_logrecords(0),
                maxValY(-1.0e23), minValY(1.0e23), is_resizing(false), fin_init(false)
{

    int r_width = displayRelief -> rect().width() - 1.5 * toolBar -> rect().width();
    int r_height = displayRelief -> rect().height() - 2.5 * VerticalGraphicClass::scroll -> rect().height();
    QRect rect(displayRelief -> rect().x() + toolBar -> rect().width(), displayRelief -> rect().y() +
        VerticalGraphicClass::scroll -> rect().height(), r_width, r_height);
    settings = new PlotSettings();
    vrt_thread = new VThread(this);
    vrt_thread -> init(settings, rect);
}

/// Отрисовка графика
void ReliefGraphics::paintEvent(QPaintEvent* events)
{
    painter.begin(this);
    /// Что-то еще отрисовывается (траектория, например)
    vrt_thread -> stop(count_logrecords);
    painter.end();
}

/// Отображение вертикальной проекции
void TLV::verticProjection(QAction* _sender)
{
    verticPrjAction = _sender;
    if(!verticalProjection) return;

    verticalProjection -> setVisible(verticPrjAction -> isChecked());
    if(verticPrjAction -> isChecked()) verticalProjection -> start();
}


Но рельеф не рисуется. Помогите, пожалуйста. Как заставить отрисовываться? Что я не так делаю?
kuler
а почему painter можно использовать в другом потоке?
AD
Цитата(kuler @ 5.12.2008, 16:25) *
а почему painter можно использовать в другом потоке?

А почему нельзя? Или как тогда сделать? ;) :)
AD
Рельеф не рисуется, хоть лопни, блин. Кто может попробовать разобраться в представленном коде и помочь?
kuler
потому что по крайней мере контролы надо юзать только в потоке в котором они были созданы, а паинтер по идее взаимодействует с контролом на котором рисуется, соответственно наверно лучше не юзать в другом потоке.
AD
Цитата(kuler @ 5.12.2008, 17:57) *
потому что по крайней мере контролы надо юзать только в потоке в котором они были созданы, а паинтер по идее взаимодействует с контролом на котором рисуется, соответственно наверно лучше не юзать в другом потоке.

У тебя есть идея как это правильно сделать? Я буду рад выслушать ее.
AD
Ну хоть кто-нибудь подскажите, можно ли использовать QPainter в доп. потоке или нет? Если нельзя, то как заставить отрисоваться рельеф в доп. потоке?
Вот код:
relief

/// Отрисовка графика
void ReliefGraphics::paintEvent(QPaintEvent* events)
{
    painter.begin(this);

    QRect rect(displayRelief -> rect());
    painter.setWindow(displayRelief -> rect());
    painter.setFont(QFont("Tahoma", 6, Qt::SolidLine));
    painter.setPen(Qt::black);

    if(param_vec.size() <= count_logrecords && coords_vec.size() <= count_logrecords && fill_axis <= 3)
    {
        vrt_thread -> init(settings, winRect());
        setPlotValues();
        initParamVec();
        if(param_vec.size() == count_logrecords && coords_vec.size() == count_logrecords)
            ++fill_axis;
    }
    initCurve();

    vrt_thread -> initVec(relief_vec);
    vrt_thread -> stop(count_logrecords);
    if(fill_axis == 3) fin_init = true;
    if(is_resizing)
    {
        vrt_thread -> init(winRect());
        start();
        is_resizing = false;
    }

    painter.drawPixmap(0, 0, vrt_thread -> pixmap);
    drawGrid(&painter);
    drawCurves(&painter);

    painter.end();
}


/// Класс параллельного потока для отрисовки рельефа вертикальной проекции
class VThread: public QThread
{
    Q_OBJECT

private:
    QPainter painter;                ///< рисовальщик
    QDockWidget* relief_widget;        ///< указатель на виджет, где будет отрисовываться рельеф
    int count_read;                    ///< количество прочитанных элементов
    PlotSettings* settings;            ///< указатель на настройки для различных масштабов
    QVector<QPointF> relief_vec;    ///< вектор геграфических точек рельефа
    QRect rect;                        ///< прямоугольная область, в которой будет производиться рисование

public:
    QPixmap pixmap;                    ///< пиксельная карта рельефа

private:
    QPointF initXY(double& sx, double& sy);
    void drawReliefNature(QPainter* painter, QPointF cur, QPointF prev);
    void drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine);
    void drawCurves(QPainter* painter);
    void drawTrackRelief(QPainter* painter);

protected:
    virtual void run();

public:
    VThread(): relief_widget(0), count_read(0), settings(0) {}
    VThread(QDockWidget* rlf_widget): relief_widget(rlf_widget), count_read(0), settings(0) {}
    ~VThread() {}
    void widget(QDockWidget* rlf_widget) { relief_widget = rlf_widget; }
    QDockWidget* widget() { return relief_widget; }
    void count(const int r) { count_read = r; }
    const int count() { return count_read; }
    void init(PlotSettings* s, QRect& rct)
    { settings = s; rect = rct; pixmap = QPixmap(rect.size()); pixmap.fill(relief_widget, 0, 0); }
    void init(PlotSettings* s) { settings = s; }
    void init(QRect& rct) { rect = rct; pixmap = QPixmap(rect.size()); pixmap.fill(relief_widget, 0, 0); }
    void initVec(QVector<QPointF>& rv) { relief_vec = rv; }
    void stop(const int size) { if(count_read == size) quit(); }
};

/// Инициализация координат - преобразование из координат графика (sx,sy) в экранные (x,y)
QPointF VThread::initXY(double& sx, double& sy)
{
    const int shift_x = 30;
    if(!rect.isValid()) return QPointF();
    QRect rect_shift(rect);        rect_shift.setLeft(rect_shift.left() + shift_x);
    double dx, dy;

    dx = sx - settings -> minX;
    dy = sy - settings -> minY;
    double x = rect_shift.left() + (dx * (rect_shift.width() - 1) / settings -> spanX());;
    double y = rect.bottom() - (dy * (rect.height() - 1) / settings -> spanY());

    return QPointF(x, y);
}

/// Настройка цвета рельефа (естественный цвет)
void VThread::drawReliefNature(QPainter* painter, QPointF cur, QPointF prev)
{
    double distance = cur.x(), delta_height = cur.y();
    QPointF scrPnt(initXY(distance, delta_height));
    if(_isnan(settings -> maxX) || _isnan(settings -> minX) || _isnan(settings -> maxY) || _isnan(settings -> minY)
        || settings -> maxX == -999.0 || settings -> minX == -999.0 || settings -> maxX == -999.0)
        return;
    if(delta_height <= 0 || scrPnt.y() >= settings -> maxY)
        return;

    QColor color(demGetColor(demCalcColor(delta_height)));
    double delta_height0;
    int div = delta_height > 1000 ? 50 : 5;
    int i = (int)(delta_height / div);
    if(!((int)delta_height % div)) --i;
    delta_height0 = div * i;
    double prev_dist = prev.x(), prev_height = prev.y();
    QPointF screenPoint(initXY(distance, delta_height0)), scrPrev(initXY(prev_dist, prev_height));

    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setBrush(QBrush(color));
    painter -> setPen(QPen(color));
    painter -> drawLine(scrPrev, screenPoint);
    for(int ix=scrPrev.x()+1; ix<screenPoint.x(); ++ix)
        painter -> drawLine(QPointF(ix, scrPrev.y()), screenPoint);
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
    QPointF cur0(distance, delta_height0);
    drawReliefNature(painter, cur0, cur);
}

/// Отрисовка черной линии рельефа для лучшей видимости его изгибов
void VThread::drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine)
{
    QBrush old_brush(painter -> brush());
    QPen old_pen(painter -> pen());
    painter -> setPen(Qt::black);
    painter -> setBrush(Qt::black);
    for(int i=vecBLine.size()-1, j=vecBLine.size()-1; i>=0; --i)
    {
        painter -> drawLine(vecBLine[i], vecBLine[j]);
        if(i != vecBLine.size() - 1) --j;
    }
    painter -> setPen(old_pen);
    painter -> setBrush(old_brush);
}

/// Отрисовка рельефа
void VThread::drawTrackRelief(QPainter* painter)
{
    QVector<QPointF> vecBLine;
    if(!rect.isValid()) return;
    int size = relief_vec.size();
    for(QVector<QPointF>::iterator rlfPnt=relief_vec.begin(), i_prev=relief_vec.begin(); rlfPnt!=relief_vec.end();
        ++rlfPnt, ++count_read)
    {
        usedRlfSpace.acquire();
        QPointF cur(*rlfPnt), prev(*i_prev);
        double X = cur.x(), Y = cur.y(), prevX = prev.x(), prevY = prev.y();
        QPointF screen(initXY(X, Y));
        drawReliefNature(painter, cur, prev);
        if(rlfPnt != relief_vec.begin()) ++i_prev;
        usedRlfSpace.release();
        vecBLine.append(screen);
    }
    drawBlackLineRelief(painter, vecBLine);
}

/// Запуск дополницельного потока
void VThread::run()
{
    painter.begin(&pixmap);
    painter.initFrom(relief_widget);
    drawTrackRelief(&painter);
    painter.end();
}

AD
Вот блин. Спросил Бланшета на счет отрисовки, вот его ответ:
Цитата
Hi Alexander,



Цитата
Sorry to trouble you! Can you help me? I want to request some questions:
1) Can I apply the QPainter in additional (not main) thread? I use the second (additional) thread and try to draw the relief in this thread. But I don't have result. The relief is not drawing in pixmap!



This is correct. As pointed out in our book, the GUI classes (including QPainter) may only be used from the main thread.


Цитата
2) If it is impossible to use QPainter, can I afford to draw relief in second thread?



I don't think so. But this might have changed or might change in the coming versions of Qt. I suggest you write your questions to the Qt mailing list; I'm no longer following the development of Qt, since I've left Trolltech and started a Ph.D.


Как выкрутиться? Есть ли возможность, с помощью сигналов и слотов что-то сделать? Он дал ссылку на кое-какую статью, но там, к сожалению, Qt 4.4 (кстати, вот ссылка Threads in Qt 4.4). Я же использую QT 4.3.2. commercial. Рисовать рельеф в главном потоке нельзя, слишком ресурсоемкая операция, а как это сделать, не знаю :(
kuler
нужен либо маршалинг (я не знаю как его сделать). А вообще к примеру 3Д графику рисуют в главном потоке - и ничего, летает. А там посложнее будет
Litkevich Yuriy
Цитата(kuler @ 8.12.2008, 19:46) *
рисуют в главном потоке - и ничего, летает.
я вот тоже думаю, что нужно в главном потоке. Надо просто хорошенько подумать, в чем проблема.
AD
Цитата(Litkevich Yuriy @ 8.12.2008, 17:27) *
я вот тоже думаю, что нужно в главном потоке. Надо просто хорошенько подумать, в чем проблема.

Да я и не спорю. Просто уже все мозги сломал, как сделать так, чтобы летало! Избавиться от рекурсии(но что-то не получается догадаться, как это безобразие циклом сделать) :( Убрать лишние проверки (тогда какие?) :unsure:
Сможете помочь? Мозги уже плавятся....
Litkevich Yuriy
Цитата(AD @ 8.12.2008, 21:47) *
Мозги уже плавятся....
у меня от своей работы так же, конец года надо проект заказчику здать, завтра пол шестого утра выезд на объект. Так, что я не помошник.
Tonal
Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)
Litkevich Yuriy
Цитата(Tonal @ 15.12.2008, 15:28) *
На ей нарисовал всё, что нужно (можно в отдельном потоке).
в этом-то и проблема, QImage находится в модуле QtGui, а его компоненты вроде как в отдельный поток совать нельзя.
AD
Цитата
Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)

Подобный трюк пытался провернуть с QPixmap - не вышло. При этом при изменении размеров почему-то ломался. Почему - отдебажить не удалось. Сможете помочь разобраться? :)))) И как это сделать с QImage?
Tonal
Цитата
Because QImage is a QPaintDevice subclass, QPainter can be used to draw directly onto images. When using QPainter on a QImage, the painting can be performed in another thread than the current GUI thread.
AD
Цитата
Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)

А можно хоть просто наброски куска кода, либо отсылка к примеру, где используется именно QImage! Даже не знаю как рисовать. Буду благодарен за помощь. Просто этот же прием (отрисовку на QImage), как я понял, еще и для другой цели можно использовать. Заранее спасибо!
kwisp
Цитата(AD @ 3.12.2008, 10:56) *
Тут почитал многое и понял, что эту функцию я могу использовать только в paintEvent()! Но еще кое-что заметил и понял, что по сути ее следует вызывать, только при изменении размеров окна.


её это какую функцию?
вот в примере %QTDIR%examples\painting\painterpaths\ при изменении свойств объектов вызывается update(). в описании слота написано:
Цитата
Updates the widget unless updates are disabled or the widget is hidden.

This function does not cause an immediate repaint; instead it schedules a paint event for processing when Qt returns to the main event loop. This permits Qt to optimize for more speed and less flicker than a call to repaint() does.

Calling update() several times normally results in just one paintEvent() call.


мне тоже скоро предстоит рисовать думаю попробовать этот метод.
Изменение свойств объектов рисования, размеров угла поворота колличества линий и т.д.
потом update() кстати можно лишь того rect() который нужно рисовать заново.

как пишут, в qt4 реализрвана двойная буферизация автоматически т.к. что думаю особой необходимости рисовать на картинках нет. т.к. получится двойная работа по идее.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.