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

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

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

Автор: AD 2.12.2008, 12:02

Запутался, не знаю как решить следующую проблему. Необходимо под графиком, который уже нарисован нарисовать рельеф. Отрисовка рельефа должна происходить всего один раз. Т.е. при рисовании в методе 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);
}


В итоге получается картинка, подобная этой (такая картинка и должна получаться):[attachment=333:relief.JPG]

Автор: AD 2.12.2008, 13:04

Кто-нибудь сможет помочь? Вопрос состоит в том, где правильно использовать функцию drawTrackRilief() или же как сделать так, чтобы не использовать QPainter и отрисовывать другими средствами. Буду благодарен за любую помощь.

Автор: AD 3.12.2008, 10:56

Тут почитал многое и понял, что эту функцию я могу использовать только в 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 3.12.2008, 11:27

Цитата(AD @ 3.12.2008, 13:56) *
и тот же QPainter painter
а почему один и тот же?

Автор: AD 3.12.2008, 11:34

Цитата(Litkevich Yuriy) *
а почему один и тот же?

Тогда вопрос поставлю по другому, а в одном paintEvent() можно использовать несколько QPainter? Если можно, то можно небольшие примерчики?

Автор: Litkevich Yuriy 3.12.2008, 12:33

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

Автор: AD 3.12.2008, 12:50

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

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

Автор: AD 3.12.2008, 17:26

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

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

Автор: AD 5.12.2008, 12:54

Перенес в доп. поток. Вот так это все выглядит:

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 5.12.2008, 16:25

а почему painter можно использовать в другом потоке?

Автор: AD 5.12.2008, 17:16

Цитата(kuler @ 5.12.2008, 16:25) *
а почему painter можно использовать в другом потоке?

А почему нельзя? Или как тогда сделать? ;) :)

Автор: AD 5.12.2008, 17:48

Рельеф не рисуется, хоть лопни, блин. Кто может попробовать разобраться в представленном коде и помочь?

Автор: kuler 5.12.2008, 17:57

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

Автор: AD 7.12.2008, 18:01

Цитата(kuler @ 5.12.2008, 17:57) *
потому что по крайней мере контролы надо юзать только в потоке в котором они были созданы, а паинтер по идее взаимодействует с контролом на котором рисуется, соответственно наверно лучше не юзать в другом потоке.

У тебя есть идея как это правильно сделать? Я буду рад выслушать ее.

Автор: AD 8.12.2008, 10:23

Ну хоть кто-нибудь подскажите, можно ли использовать 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 8.12.2008, 12:32

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

Цитата
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 (кстати, вот ссылка http://doc.trolltech.com/4.4/threads.html#painting-in-threads). Я же использую QT 4.3.2. commercial. Рисовать рельеф в главном потоке нельзя, слишком ресурсоемкая операция, а как это сделать, не знаю :(

Автор: kuler 8.12.2008, 16:46

нужен либо маршалинг (я не знаю как его сделать). А вообще к примеру 3Д графику рисуют в главном потоке - и ничего, летает. А там посложнее будет

Автор: Litkevich Yuriy 8.12.2008, 17:27

Цитата(kuler @ 8.12.2008, 19:46) *
рисуют в главном потоке - и ничего, летает.
я вот тоже думаю, что нужно в главном потоке. Надо просто хорошенько подумать, в чем проблема.

Автор: AD 8.12.2008, 18:47

Цитата(Litkevich Yuriy @ 8.12.2008, 17:27) *
я вот тоже думаю, что нужно в главном потоке. Надо просто хорошенько подумать, в чем проблема.

Да я и не спорю. Просто уже все мозги сломал, как сделать так, чтобы летало! Избавиться от рекурсии(но что-то не получается догадаться, как это безобразие циклом сделать) :( Убрать лишние проверки (тогда какие?) :unsure:
Сможете помочь? Мозги уже плавятся....

Автор: Litkevich Yuriy 8.12.2008, 18:52

Цитата(AD @ 8.12.2008, 21:47) *
Мозги уже плавятся....
у меня от своей работы так же, конец года надо проект заказчику здать, завтра пол шестого утра выезд на объект. Так, что я не помошник.

Автор: Tonal 15.12.2008, 12:28

Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)

Автор: Litkevich Yuriy 15.12.2008, 12:34

Цитата(Tonal @ 15.12.2008, 15:28) *
На ей нарисовал всё, что нужно (можно в отдельном потоке).
в этом-то и проблема, QImage находится в модуле QtGui, а его компоненты вроде как в отдельный поток совать нельзя.

Автор: AD 15.12.2008, 17:04

Цитата
Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)

Подобный трюк пытался провернуть с QPixmap - не вышло. При этом при изменении размеров почему-то ломался. Почему - отдебажить не удалось. Сможете помочь разобраться? :)))) И как это сделать с QImage?

Автор: Tonal 16.12.2008, 11:45

Цитата
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 19.1.2009, 12:19

Цитата
Ну, я бы сделал примерно так:
1. При изменении размеров окна создал QImage с нужными размерами остальными параметрами.
2. На ей нарисовал всё, что нужно (можно в отдельном потоке).
3. По окончанию её отрисовки пнул перерисовку окна.
4. В paintEvent() выводил енту картинку, ежели она есть. :)

А можно хоть просто наброски куска кода, либо отсылка к примеру, где используется именно QImage! Даже не знаю как рисовать. Буду благодарен за помощь. Просто этот же прием (отрисовку на QImage), как я понял, еще и для другой цели можно использовать. Заранее спасибо!

Автор: kwisp 20.1.2009, 10:23

Цитата(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 реализрвана двойная буферизация автоматически т.к. что думаю особой необходимости рисовать на картинках нет. т.к. получится двойная работа по идее.

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