Russian Qt Forum
Ноябрь 25, 2024, 23:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Рисование на форме из потока  (Прочитано 10387 раз)
soalvi
Гость
« : Май 08, 2010, 07:27 »

Для рисования на форме приложения используется метод ::paintEvent(QPaintEvent*) - из других мест отрисовки не получается Грустный Как можно рисовать на форме из потока, используя QPainter или какой-нибудь другой путь?
 
Записан
marbius
Гость
« Ответ #1 : Май 08, 2010, 08:37 »

В Qt не получится рисовать вне paintEvent без установки Qt::WA_PaintOutsidePaintEvent.
Цитировать
Qt::WA_PaintOutsidePaintEvent Makes it possible to use QPainter to paint on the widget outside paintEvent(). This flag is not supported on Windows, Mac OS X or Embedded Linux. We recommend that you use it only when porting Qt 3 code to Qt 4.

Как вариант можно рисовать на QPixmap, в необходимом месте вызывать QWidget::update(), который инициирует вызов paintEvent, а в paintEvent уже выводить содержимое QPixmap (самому очень не нравится такой подход, но похоже, что это единственное решение, которое вписывается в концепцию кроссплатформенного программирования Qt)
« Последнее редактирование: Май 08, 2010, 08:58 от µarbius » Записан
Sancho_s_rancho
Гость
« Ответ #2 : Май 08, 2010, 09:59 »

1) Вы не должны хотеть рисовать на виджете вне PaintEvent().
2) Создавать QPixmap или QImage или что-то еще подобное вы можете где угодно. Где угодно на них вы можете "рисовать" что угодно. Например: в другом потоке перерисовывать сложный график на QPixmap.
3) Рисовать на виджете вы должны в главном потоке. Но если вы в соседнем все вычислили и нанесли на QPixmap, то в paintEvente вам остается только сказать: рисовальщик, нарисуй готовую пиксельную карту.
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #3 : Май 08, 2010, 11:09 »

QImage специально заточен для рисования на нём в любом потоке.
Записан

Юра.
soalvi
Гость
« Ответ #4 : Май 12, 2010, 22:11 »

Простой вызов QWidget::update() результата не даёт!
Может кто нибудь приведёт пример вызова метода ::paintEvent(QPaintEvent*)? Или разъяснит немного подробнее механизм вызова?
Записан
Sancho_s_rancho
Гость
« Ответ #5 : Май 13, 2010, 10:29 »

Простой вызов QWidget::update() результата не даёт!
Может кто нибудь приведёт пример вызова метода ::paintEvent(QPaintEvent*)? Или разъяснит немного подробнее механизм вызова?
В каталоге examples Qt лежит целая куча примеров, где происходит рисование на виджете. update() все необходимые результаты дает.
Записан
ритт
Гость
« Ответ #6 : Май 15, 2010, 17:11 »

я год не заглядывал в данный раздел, а заглянув, увидел те же темы, что неоднократно обсасывались ранее.
товарищи топикстартеры, вы что, дебилы?! неужели поиск интересующего материала по форуму займёт больше времени и/или усилий, чем выдумывание проблемы, описание её, ожидание ответов, переспрашивание и уточнение и др., и пр.?
или вы всё-таки дебилы?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Май 15, 2010, 19:47 »

или вы всё-таки дебилы?
Это не работает. Чем меньше Вы покажете своих субъективных эмоций - тем лучше $. Не давайте никому повода кричать "меня оскорбили!!!". Спокойно, корректно и кратко изложите почему нитка будет удалена и/или автор будет забанен, это несложно.
Записан
ритт
Гость
« Ответ #8 : Май 15, 2010, 21:39 »

ветка не будет удалена и автор не будет забанен - нет причин.
лучше пусть докажет мне и себе, что я ошибаюсь...
Записан
marbius
Гость
« Ответ #9 : Май 16, 2010, 06:43 »

Вот Вам, уважаемый, небольшой пример.
Написан на скорую руку (причем одну и левую  Подмигивающий ), не без изъянов, но работоспособный.

Код:
#include <QtGui>
#include <QThread>

#define WIDTH 800
#define HEIGHT 600

// отделный поток для рисования
// каждую секунду рисует по прямоугольнику, пока не заполнится окно
class myThread : public QThread
{
    private:
        QPixmap *where2Draw;
        QWidget *what2Update;

    public:
        myThread(QWidget *aWidget, QPixmap *aPixmap) : QThread()
        {   this->what2Update=aWidget;
            this->where2Draw=aPixmap;
        }

        void run()
        {   // "цикл" потока
            QPainter p(this->where2Draw);
            for (int i=0;i<WIDTH;i+=10)
            {   // определяем очередно прямоугольник
                QRect r=QRect::QRect(i,30,5,30);
                // рисуем прямоугольник в буфер
                p.drawRect(r);

                // далее идет "вывод на экран":
                // 1. определяем область, которая изменилась. в нашем случае это
                //    область, куда мы только что "нарисовали" наш прямоугольник
                //    ajust () необходим, чтобы немного расширить область, чтобы
                //    нарисованный прямоугольник гарантированно отобразился на
                //    экране целиком
                // 2. вызываем QWidget::update(QRect), которая инициирует
                //    вызов paintEvent, где мы уже и выведем содержимое измененной
                //    области на экран
                r.adjust(0,0,1,1);
                this->what2Update->update(r);

                this->sleep(1);
            }
        }
};

class myWidget : public QWidget
{
    public:
        // это графический буфер, на котором мы будем "рисовать"
        QPixmap *buffer;

        myWidget (QWidget *parent=0) : QWidget(parent)
        {   // установка "габаритов"
            this->setMaximumWidth(WIDTH);
            this->setMaximumHeight(HEIGHT);
            this->resize(WIDTH,HEIGHT);

            // создаем буфер QPixmap
            buffer=new QPixmap(WIDTH,HEIGHT);

            // просто ради примера выводим произвольную графику
            // лишь бы за пределами paintEvent
            QPainter p(buffer);
            p.fillRect(QRect::QRect(0,0,WIDTH,HEIGHT),Qt::green);
            p.drawText(10,10,"Hi, man!");
            p.drawLine(0,0,WIDTH,HEIGHT);
            // "выводим" содержимое буфера на экран
            this->update();
        }

        ~myWidget ()
        {   delete (buffer);
        }

        // переопределяем paintEvent, чтобы он выводил на экран содержимое нашего буфера
        void paintEvent(QPaintEvent *p)
        {
            QPainter painter(this);
            // следующий метод копирует содержимое QPixmap из области,
            // определенной в QRect "на экран"
            painter.drawPixmap(p->rect(),*buffer,p->rect());
        }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    myWidget w;
    w.show();
    myThread t(&w,w.buffer);
    t.start();
    return a.exec();
}

« Последнее редактирование: Май 16, 2010, 10:05 от µarbius » Записан
marbius
Гость
« Ответ #10 : Май 16, 2010, 10:19 »

или вы всё-таки дебилы?
Это не работает. Чем меньше Вы покажете своих субъективных эмоций - тем лучше $. Не давайте никому повода кричать "меня оскорбили!!!". Спокойно, корректно и кратко изложите почему нитка будет удалена и/или автор будет забанен, это несложно.

Зря Вы так, Igors. Админу дозволено все (по определению): на то он и власть, и правосудие...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.164 секунд. Запросов: 23.