2013-04-29 38 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爲此提供的解決方案。

對於你的問題 - 有沒有方式在Qt做繪畫在一個單獨的線程;任何窗口小部件類不能從被另一個線程觸動。建議的invokeMethod調用實際上是一個異步回調,它在主線程中排隊等待執行。你可能生成一個QImage,將它傳遞給GUI線程,讓GUI使用它,但我會認真建議使用場景圖(QGraphicsView),因爲它是專門爲此目的而設計和優化的。

5

如果你需要做你的畫比Qt的GUI線程以外的線程,這樣做:

  1. 在您的非GUI線程,創建一個QImage的對象
  2. 使用的QPainter繪製成QImage對象
  3. 使用QApplication :: postEvent或排隊信號/槽連接將QImage對象以線程安全方式傳遞到主線程
  4. 主線程現在可以將QI將圖片對象轉換爲QPixmap(這將會相對較快),然後照常顯示。
+4

排隊的信號/插槽連接是要走的路 – 2013-04-29 20:19:56

0

雖然這是非常糟糕的做法 - 從工作線程中更新GUI線程,你真的應該通過信號槽做(與連接類型-queued),你仍然可以通過QMetaObject::invokeMethod()

更新GUI必須在工作線程中運行每個函數,通過invokeMethod()更新GUI。例如 - 在你的主類中,添加像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百萬個信號到GUI線程。 – 2013-04-29 22:31:38

+0

好吧,如果你畫到QLabel中,那麼你可以在線程中的QImage上繪製所有畫線,並根據需要更新你的標籤(QElapsedTimer和超時後通過invokeMethod傳遞你的QImage來「更新「或somehing,這將設置Pixmap(使用QPixmap :: fromImage())到QLabel) – Shf 2013-04-30 09:58:08