crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V  < 1 2 3 >  
Ответить в данную темуНачать новую тему
> Грамотная отрисовка рельефа, что-то не получается
AD
  опции профиля:
сообщение 5.12.2008, 17:16
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


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

А почему нельзя? Или как тогда сделать? ;) :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.12.2008, 17:48
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Рельеф не рисуется, хоть лопни, блин. Кто может попробовать разобраться в представленном коде и помочь?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuler
  опции профиля:
сообщение 5.12.2008, 17:57
Сообщение #13


Танцор диско
***

Группа: Участник
Сообщений: 441
Регистрация: 11.9.2008
Из: Москва
Пользователь №: 289

Спасибо сказали: 6 раз(а)




Репутация:   -1  


потому что по крайней мере контролы надо юзать только в потоке в котором они были созданы, а паинтер по идее взаимодействует с контролом на котором рисуется, соответственно наверно лучше не юзать в другом потоке.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 7.12.2008, 18:01
Сообщение #14


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


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

У тебя есть идея как это правильно сделать? Я буду рад выслушать ее.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 8.12.2008, 10:23
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Ну хоть кто-нибудь подскажите, можно ли использовать 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
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Вот блин. Спросил Бланшета на счет отрисовки, вот его ответ:
Цитата
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
  опции профиля:
сообщение 8.12.2008, 16:46
Сообщение #17


Танцор диско
***

Группа: Участник
Сообщений: 441
Регистрация: 11.9.2008
Из: Москва
Пользователь №: 289

Спасибо сказали: 6 раз(а)




Репутация:   -1  


нужен либо маршалинг (я не знаю как его сделать). А вообще к примеру 3Д графику рисуют в главном потоке - и ничего, летает. А там посложнее будет
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 8.12.2008, 17:27
Сообщение #18


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(kuler @ 8.12.2008, 19:46) *
рисуют в главном потоке - и ничего, летает.
я вот тоже думаю, что нужно в главном потоке. Надо просто хорошенько подумать, в чем проблема.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 8.12.2008, 18:47
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


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

Да я и не спорю. Просто уже все мозги сломал, как сделать так, чтобы летало! Избавиться от рекурсии(но что-то не получается догадаться, как это безобразие циклом сделать) :( Убрать лишние проверки (тогда какие?) :unsure:
Сможете помочь? Мозги уже плавятся....
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 8.12.2008, 18:52
Сообщение #20


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


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

3 страниц V  < 1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 2:02