2017-09-23 47 views
0

最近我正在爲自己的硬件編寫調試器。我想添加一個像eclipse或qt創建者或其他IDE的內存查看器小部件。但是,我不知道使用什麼樣的小部件。例如,tableWidget,有沒有一些設置,使其像這樣:怎樣才能實現我自己的內存查看器QT

enter image description here

enter image description here

+0

什麼是你的問題,你想獲得第一或第二圖像? – eyllanesc

+0

兩個問題:1:得到第一個圖像; 2我已經實現了一個像第二個圖像的窗口,但我不知道如何改變文本的顏色,如第二個圖像 –

+0

我建議問一個部分,因爲這些問題是獨立的。 – eyllanesc

回答

2

最好的辦法是創建一個自定義窗口小部件,因爲任務是私人的,沒有部件被容納到任務。

爲此我們將繼承QAbstractScrollArea,從這個類繼承QTableView,QListView,QListWidget和QTableWidget。它旨在顯示QScrollArea內的數據。 另外這個類的documentation告訴我們如何創建一個自定義的類。

當繼承QAbstractScrollArea,你需要做到以下幾點:

  • 控制設定自己的範圍,數值頁一步, 跟蹤他們的行蹤滾動條。
  • 根據滾動條的值在 視口中繪製該區域的內容。
  • 處理事件 由viewportEvent()中的視口接收
  • 明顯調整事件大小。 使用viewport-> update()更新視口的內容,而不是update()的 ,因爲所有的繪畫操作都是在視口上進行的。

以該參考我創建了以下部件:

memoryviewer.h

#ifndef MEMORYVIEWER_H 
#define MEMORYVIEWER_H 

#include <QAbstractScrollArea> 
#include <QBuffer> 

class MemoryViewer : public QAbstractScrollArea 
{ 
    Q_OBJECT 
public: 
    MemoryViewer(QWidget *parent = 0); 
    ~MemoryViewer(); 

    void setData(const QByteArray &ba); 
    bool setData(QIODevice &device); 

protected: 
    void paintEvent(QPaintEvent *); 
    void resizeEvent(QResizeEvent *); 

private: 
    void adjustContent(); 
    void init(); 

    int addressWidth(); 
    int hexWidth(); 
    int asciiWidth(); 

    QByteArray data(qint64 pos=0, qint64 count=-1); 

    int nBlockAddress; 
    int mBytesPerLine; 

    int pxWidth; 
    int pxHeight; 

    qint64 startPos; 
    qint64 endPos; 

    int nRowsVisible; 

    QBuffer buffer; 
    QIODevice *ioDevice; 
    qint64 size; 

    QByteArray dataVisible; 
    QByteArray dataHex; 
}; 

#endif // MEMORYVIEWER_H 

memoryviewer.cpp

#include "memoryviewer.h" 

#include <QPainter> 
#include <QScrollBar> 

MemoryViewer::MemoryViewer(QWidget *parent):QAbstractScrollArea(parent) 
{ 
    ioDevice = new QBuffer(this); 
    init(); 
    connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewer::adjustContent); 
    connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewer::adjustContent); 
} 

MemoryViewer::~MemoryViewer() 
{ 

} 


void MemoryViewer::init() 
{ 
    nBlockAddress = 2; 
    mBytesPerLine = 16; 

    pxWidth = fontMetrics().width(QChar('0')); 
    pxHeight = fontMetrics().height(); 

} 

int MemoryViewer::addressWidth() 
{ 
    return (nBlockAddress*4+ nBlockAddress -1)*pxWidth; 
} 

int MemoryViewer::hexWidth() 
{ 
    return (mBytesPerLine*3+1)*pxWidth; 
} 

int MemoryViewer::asciiWidth() 
{ 
    return (mBytesPerLine*2 +1)*pxWidth; 
} 

QByteArray MemoryViewer::data(qint64 pos, qint64 count) 
{ 
    QByteArray buffer; 

    if (pos >= size) 
     return buffer; 

    if (count < 0) 
     count = size; 
    else 
     if ((pos + count) > size) 
      count = size - pos; 

    if(ioDevice->open(QIODevice::ReadOnly)){ 
     ioDevice->seek(pos); 
     buffer = ioDevice->read(count); 
     ioDevice->close(); 
    } 
    return buffer; 
} 

void MemoryViewer::setData(const QByteArray &ba) 
{ 
    buffer.setData(ba); 
    setData(buffer); 

} 

bool MemoryViewer::setData(QIODevice &device) 
{ 
    ioDevice = &device; 
    bool ok = ioDevice->open(QIODevice::ReadOnly); 
    if(ok){ 
     size = ioDevice->size(); 
     ioDevice->close(); 
    } 
    else{ 
     QBuffer *buf = new QBuffer(this); 
     ioDevice = buf; 
    } 
    init(); 
    adjustContent(); 
    return ok; 
} 

void MemoryViewer::resizeEvent(QResizeEvent *) 
{ 
    adjustContent(); 
} 


void MemoryViewer::paintEvent(QPaintEvent *) 
{ 
    QPainter painter(viewport()); 

    int offsetX = horizontalScrollBar()->value(); 

    int y = pxHeight; 
    QString address; 

    painter.setPen(viewport()->palette().color(QPalette::WindowText)); 

    for(int row = 0; row <= dataVisible.size()/mBytesPerLine; row++){ 
     QString str = QString("%1").arg(startPos + mBytesPerLine*row, nBlockAddress*4, 16, QChar('0')).toUpper(); 
     int i = 0; 
     address = ""; 
     while(i < nBlockAddress){ 
      address += str.mid(i*4, 4) + ":"; 
      i++; 
     } 
     address.remove(address.size()-1, 1); 

     painter.drawText(pxWidth/2 -offsetX , y, address); 
     y+=pxHeight; 
    } 

    int x; 
    int lx = addressWidth() +pxWidth; 
    painter.drawLine(lx-offsetX, 0, lx-offsetX, height()); 
    lx += pxWidth/2; 
    y = pxHeight; 

    //hex data 
    x = lx-offsetX+3*pxWidth; 
    int w = 3*pxWidth; 
    for(int col =0; col < mBytesPerLine/2; col++){ 
     painter.fillRect(x-pxWidth/2, 0, w, height(), viewport()->palette().color(QPalette::AlternateBase)); 
     x+= 6*pxWidth; 
    } 

    int bPos = 0; 
    for(int row=0; row < nRowsVisible; row++){ 
     x = lx-offsetX; 
     for(int col =0; (col < mBytesPerLine) && (bPos < dataHex.size()) ; col++){ 
      QString str = dataHex.mid(bPos*2,2).toUpper(); 
      painter.drawText(x, y, str); 
      x += 3*pxWidth; 
      bPos += 1; 
     } 
     y+= pxHeight; 
    } 

    lx = addressWidth() + hexWidth(); 
    painter.drawLine(lx-offsetX, 0, lx-offsetX, height()); 

    lx += pxWidth/2; 

    bPos = 0; 
    y = pxHeight ; 
    int ch; 
    for(int row=0; row < nRowsVisible; row++){ 
     x = lx-offsetX; 
     for(int col =0; (col < mBytesPerLine) && (bPos < dataVisible.size()) ; col++){ 
      ch = (uchar)dataVisible.at(bPos); 
      if (ch < 0x20) 
       ch = '.'; 
      painter.drawText(x, y, QChar(ch)); 
      x += 2*pxWidth; 
      bPos += 1; 
     } 
     y+= pxHeight; 
    } 
} 

void MemoryViewer::adjustContent() 
{ 
    int w = addressWidth() + hexWidth() + asciiWidth(); 
    horizontalScrollBar()->setRange(0, w - viewport()->width()); 
    horizontalScrollBar()->setPageStep(viewport()->width()); 

    nRowsVisible = viewport()->height()/pxHeight; 
    int val = verticalScrollBar()->value(); 
    startPos = (qint64)val*mBytesPerLine; 
    endPos = startPos + nRowsVisible*mBytesPerLine -1; 

    int lineCount = size/mBytesPerLine; 
    verticalScrollBar()->setRange(0, lineCount-nRowsVisible); 
    verticalScrollBar()->setPageStep(nRowsVisible); 

    if(endPos >= size){ 
     endPos = size-1; 
    } 
    dataVisible = data(startPos, endPos-startPos + mBytesPerLine +1); 
    dataHex = dataVisible.toHex(); 
    viewport()->update(); 
} 

一種ADVA實施的缺點是您不必直接加載所有字節,因爲您可以傳遞一個從QIODevice繼承的對象,如QFile,並在視圖需要時通過消除內存開銷來讀取數據。此外,您可以通過一個QByteArray

在下面link,你會發現一個例子

enter image description here

+0

我真的很感謝你的幫助。超越我的話〜 –