2013-04-29 2 views
0

У меня есть конкретная цель: нарисовать дорожную сеть. Поэтому у меня есть несколько точек (x, y), и я хотел бы их подключить (используя функцию drawLine). Из-за их количества (около 2-3 миллионов) мне нужно сделать это в другом потоке, так что проблема в том, как мне это сделать? У меня есть специальная область для рисования - QLabel. Я попытался сделать это через QPixmap в основном потоке, и все в порядке, но когда я пытаюсь сделать это через сигнал/слот в другом потоке, не появляется изображение :(Как нарисовать на QLabel в другой теме

Фактически, когда я преобразовываю свои координаты в графический интерфейс GUI- координаты становятся дробными, поэтому я не знаю, как их рисовать, потому что функции drawLine имеют целочисленный аргумент: (int x1, int y1, int x2, int y2).

Вот как я создаю другой поток (мне нужно запустить только одну функцию, так что это лучший способом я думаю) QtConcurrent::run(this,&MainWindow::parseXML)

Надеется, что вы мне помочь, потому что я сошел с умом%)

P.S Я читал, что QPixmap не поддерживается в многопоточном чертеже. Так что теперь я понятия не имею, как это сделать.
QPainter can be used in a thread to paint onto QImage, QPrinter, and QPicture paint devices. Painting onto QPixmaps and QWidgets is not supported. On Mac OS X the automatic progress dialog will not be displayed if you are printing from outside the GUI thread.

ответ

1

Вы, видимо, ищет QGraphicsView (или предпочтительно QQuickView, если вы заботитесь о производительности и работе с Qt5). Это решение, которое Qt предлагает именно для этой цели.

На ваш вопрос - есть no путь в Qt, чтобы сделать покраску в отдельной теме; любой класс виджетов не может быть затронут из другого потока. Предложенный вызов invokeMethod фактически представляет собой асинхронный обратный вызов, который ставится в очередь для выполнения в основном потоке. You может сгенерировать QImage, передать его в поток графического интерфейса и позволить графическому интерфейсу использовать его, но я бы серьезно предложил работать с графиком сцены (QGraphicsView), потому что он был спроектирован и оптимизирован именно для этой цели.

5

Если вам нужно сделать вашу картину в потоке, чем нить Qt GUI, сделайте следующее:

  1. В вашей не-GUI потоке, создать объект QImage
  2. Используйте QPainter для рисования в объекте QImage
  3. Использование QApplication :: postEvent или связанное по очереди соединение с сигналом/слотом для передачи объекта QImage в основную нить потокобезопасным способом
  4. Основной поток теперь может преобразовывать QI mage в QPixmap (это будет относительно быстро сделать), а затем отобразить его как обычно.
+4

Очередь сигнала/слот-соединение - это путь –

0

Хотя это действительно плохая практика - обновить GUI нить внутри рабочего потока, и вы действительно должны сделать это с помощью сигнала-слот (с типом подключения -queued), вы можете обновить GUI через QMetaObject::invokeMethod()

You должны запускать каждую функцию в рабочем потоке, обновляя GUI через invokeMethod(). Например, в вашем основном классе добавьте функцию, например, void MainWindow::drawLine(int x1, int y1, int x2, int y2), которая будет нарисовать линию на вашем QImage. И в вашей теме вы можете вызвать эту функцию следующим образом:

QMetaObject::invokeMethod(this,"drawLine", Q_ARG(int,x1), Q_ARG(int,y1), Q_ARG(int,x2), Q_ARG(int,y2)); 
+0

Это похоже на ужасное множество накладных расходов для чего-то, что нужно будет сделать 2-3 миллиона раз ... Я был бы удивлен, если бы производительность была улучшена, отправив 2 -3 миллиона сигналов в поток графического интерфейса пользователя. –

+0

ОК, если вы нарисуете в QLabel, тогда вы можете нарисовать все строки с вашим Художником в QImage в потоке и обновить свой ярлык так часто, как вам кажется (QElapsedTimer и после таймаута передать QImage с помощью invokeMethod для функции " update "или somehing, который установитPixmap (используйте QPixmap :: fromImage()) в QLabel) – Shf