Необходимо ли для Qt :: paintEvent быть реентерабельным? - PullRequest
1 голос
/ 11 октября 2008

Могу ли я поместить художника в переменные класса? :

protected:
QPainter *myPainter;

...

void MyWidget::paintEvent(QPaintEvent *event)
{
    myPainter = new QPainter(this);

Ответы [ 3 ]

3 голосов
/ 24 октября 2008

Новый ансер для более конкретного рассмотрения повторного входа ...

danatel оставил следующий комментарий к этому сообщению (частично):

Под повторным входом я подразумеваю эту конкретную ситуацию: 1) обработчик paintEvent сохраняет QPainter в переменную класса. 2) обработчик paintEvent вызывает подпрограммы для рисования чего-либо 3) одна из подпрограмм вызывает метод Qt 4) этот метод Qt рекурсивно генерирует другой paintEvent

Ответ на этот вопрос заключается в том, что это, вероятно, должно быть приемлемо, если вы не делаете что-то действительно странное. (И если вы сделаете что-то странное, Qt, вероятно, предупредит вас или прервет.) Я думаю, что все еще может быть некоторая путаница в том, что вы подразумеваете под повторным входом, но генерация paintEvent не остановит поток выполнения текущего действия, чтобы немедленно обработать это событие. Вместо этого (как и все события), он будет поставлен в очередь для последующей обработки. Пока вы не выполняете многопоточность или не вызываете processEvents, порядок выполнения кода, когда вы находитесь в одной из ваших собственных функций, должен быть очень простым.

В качестве примера давайте проследим за вашими шагами и рассмотрим их более подробно.

  1. Foo::paintEvent() обработчик создает QPainter и устанавливает Foo::m_painter_p на это.
  2. Foo::paintEvent() звонки Foo::paintAntarticaFlag().
  3. Foo::paintAntarticaFlag(): а) использует Foo::m_painter_p, затем б) вызывает что-то, что вызывает Foo::update(), затем в) использует Foo::m_painter_p еще немного.
  4. Foo::update(), который на самом деле является методом Qt, генерирует paintEvent для Foo.

Вышеприведенная последовательность в порядке, так как обновление создает событие , что означает задержку обработки. Если вместо этого вы вызываете Foo :: repaint (), это приведет к немедленной рекурсии в Foo :: paintEvent (), что приведет к прерыванию Qt, потому что вы создаете более 1 рисовальщика для одного и того же объекта или ваша программа прерывает работу потому что это в конечном счете (вы знаете, через несколько сотен миллисекунд) взорвало стек.

Если вы выполняете несколько потоков и просто хотите инициировать перерисовку, вы все равно можете сделать это из другого потока, поскольку он просто поместит paintEvent в очередь для обработки соответствующим потоком в нужное время. Если вы делаете несколько потоков и хотите нарисовать эти флаги одним и тем же художником, не надо. Просто не надо. В этом случае вы можете рассмотреть возможность рисования каждого флага в общем изображении и рисования этого изображения там, где вы сейчас используете QPainter.

2 голосов
/ 11 октября 2008

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

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    // use painter
    ...
    // paint object automatically closes and paint on desctruction
}
1 голос
/ 12 октября 2008

Если вы пытаетесь избежать передачи виджета живописца нескольким вызовам подпрограмм, вы, вероятно, можете обойтись без указателя на художник в качестве переменной класса. Как уже упоминалось, вы все равно должны создать / уничтожить его в функции paintEvent. Лично я, вероятно, просто передал бы это вспомогательным функциям, но вы могли бы сделать это следующим образом.

Кроме того, я не уверен, как ваш вопрос связан с повторным входом. Вся прорисовка элементов пользовательского интерфейса должна быть только в потоке пользовательского интерфейса, если у вас есть несколько потоков. Вы можете рисовать изображение в другом потоке, но в этом случае вы, вероятно, захотите рисовать только это изображение в этом потоке, а не в нескольких. В любом случае, я не думаю, что у вас возникнут проблемы с повторным входом в функции Qt, которые вы вызываете для художника, пока вы соблюдаете эти условия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...