我希望我會盡可能清楚我的問題。我目前正在使用 QML 檔案作為 GUI 開發應用程式。
目標很簡單:我通過 QTcpSocket(來自線性相機的原始資料)成為大量資料,我想顯示影像。重要的是要知道每次我收到一幀,它是一個 1*2048 的顏色陣列。我想在收到資料后盡快顯示出來。
我嘗試設定一個包含顏色的屬性字串和包含位置 (x;y) 的其他 2 個屬性,然后:
Canvas {
id: camera
objectName: "cameradrawer"
x: 1270
y: 30
width: 650
height: 500
renderStrategy: Canvas.Threaded
property string iColor
property int imageX
property int imageY
property var line
property var ctx
onPaint: {
ctx = getContext('2d');
ctx.clearRect(0, 0, width, height);
// draw here
ctx.fillStyle = iColor;
ctx.fillRect(imageY,imageX, 1, 1);
}
}
當我更改屬性然后使用ìnvokeMethod("requestPaint")
時,應用程式不斷崩潰。我做錯了什么還是 QML 沒有用于高速流程?
預先感謝您的幫助!
PS:如有必要,我可以發布更多代碼(C 部分)。
uj5u.com熱心網友回復:
我有一點空閑時間,所以我研究了這個問題,因為我發現它很有趣。所以我猜更快的實作方法是從資料中創建一個影像,然后從中創建一個紋理,可以在基于 QQuickItem 的專案中使用。
自定義項:
自定義項.h
class CustomItem : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
public:
CustomItem(QQuickItem *parent = nullptr);
~CustomItem();
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
void componentComplete() override;
protected:
void createImage();
void timerHandler();
private:
uint32_t m_buffer[BUFFER_SIZE] = {};
QSGTexture *m_texture = nullptr;
QSGTexture *m_newTexture = nullptr;
QTimer m_timer;
};
自定義項.cpp
CustomItem::CustomItem(QQuickItem *parent):
QQuickItem(parent)
{
setFlag( QQuickItem::ItemHasContents, true);
QObject::connect(&m_timer, &QTimer::timeout, this, &CustomItem::timerHandler);
}
CustomItem::~CustomItem()
{
if(m_texture != nullptr)
{
delete m_texture;
m_texture = nullptr;
}
if(m_newTexture != nullptr)
{
delete m_newTexture;
m_newTexture = nullptr;
}
}
QSGNode *CustomItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
if (n == nullptr)
{
if(m_newTexture != nullptr)
{
n = new QSGSimpleTextureNode();
n->setRect(boundingRect());
}
}
if(n != nullptr)
{
if(m_newTexture != nullptr)
{
if(m_texture != nullptr)
{
delete m_texture;
m_texture = nullptr;
}
m_texture = m_newTexture;
m_newTexture = nullptr;
n->setTexture(m_texture);
}
}
return n;
}
void CustomItem::componentComplete()
{
createImage();
m_timer.start(1000);
QQuickItem::componentComplete();
}
void CustomItem::createImage()
{
if(m_newTexture == nullptr)
{
QRandomGenerator::global()->fillRange(m_buffer, BUFFER_SIZE);
QImage img(reinterpret_cast<uchar *>(m_buffer), IMAGE_WIDTH, IMAGE_HEIGHT, QImage::Format_ARGB32);
auto wnd = window();
if(wnd != nullptr)
{
m_newTexture = wnd->createTextureFromImage(img);
}
}
}
void CustomItem::timerHandler()
{
createImage();
update();
}
一些簡短的說明:
該類包含一個大整數陣列。我用計時器模擬周期性資料更新,因此陣列每秒更新一次隨機資料。一旦資料發生變化,我就會創建一個紋理。我使用 2 個指標來避免在渲染時洗掉舊紋理,因此在安全的情況下我會洗掉里面的舊紋理updatePaintNode
。我使用QSGSimpleTextureNode
,因為它允許使用紋理,但我想你可以使用任何其他你想要的類。紋理具有 Alpha 通道,您可以使用它Format_RGB32
來避免這種情況。如果專案更大的紋理將被縮放,您也可以使用它。
用于測驗的 main.qml 可以是這樣的:
import QtQuick
import QtQuick.Window
import CustomItems 1.0
Window {
id: window
visible: true
height: 400
width: 400
Rectangle {
width: 300
height: 300
color: "orange"
anchors.centerIn: parent
CustomItem {
width: 200
height: 200
anchors.centerIn: parent
}
}
}
要在 CMake 的情況下注冊自定義項,應將以下行添加到 CMakeFiles.txt 中:
set(CMAKE_AUTOMOC ON)
qt_add_qml_module(qml_test
URI CustomItems
VERSION 1.0
QML_FILES main.qml
SOURCES CustomItem.h CustomItem.cpp
來源可以在這里找到
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/491173.html