2017-09-23 1 views
0

Récemment, j'écris un débogueur pour mon propre matériel. Je veux ajouter un widget de visionneuse de mémoire comme le créateur d'éclipse ou de QT ou tout autre IDE. Cependant, je n'ai aucune idée du type de widget à utiliser. Par exemple, tableWidget, est-il un paramètre pour le faire comme ceci:Comment réaliser mon propre visualiseur de mémoire par QT

enter image description here

enter image description here

+0

Quelle est votre question, voulez-vous obtenir la première ou la deuxième image? – eyllanesc

+0

deux question: 1: obtenir la première image; 2 J'ai réalisé une fenêtre comme seconde image, mais je ne sais pas comment changer la couleur du texte comme seconde image –

+0

Je recommande de poser une partie par partie car les questions sont indépendantes. – eyllanesc

Répondre

2

La meilleure option est de créer un widget personnalisé parce que la tâche est privée et aucun des widgets sont logés à la tâche. Pour cela, nous allons hériter de QAbstractScrollArea, de cette classe hériter de QTableView, QListView, QListWidget et QTableWidget. Il est conçu pour afficher des données dans un QScrollArea. En outre documentation de cette classe nous explique comment créer une classe personnalisée.

Quand héritant QAbstractScrollArea, vous devez effectuer les opérations suivantes:

  • contrôle les barres de défilement en définissant leur gamme, la valeur, l'étape de page et le suivi de leurs mouvements.
  • Dessinez le contenu de la zone dans la fenêtre en fonction des valeurs des barres de défilement.
  • Les événements de gestion reçus par la fenêtre dans viewportEvent()
  • redimensionnent notamment les événements. Utilisez viewport-> update() pour mettre à jour le contenu de la fenêtre à la place de update() car toutes les opérations de peinture ont lieu sur la fenêtre.

prenant cette référence I créé le widget suivant:

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(); 
} 

Un adva ntage de l'implémentation est que vous n'avez pas à charger tous les octets directement puisque vous pouvez passer un objet qui hérite de QIODevice tel que QFile et lire les données lorsque la vue en a besoin en supprimant la surcharge mémoire. En outre, vous pouvez passer un QByteArray

Dans ce qui suit link, vous trouverez un exemple

enter image description here

+0

J'apprécie vraiment votre aide. Au-delà de mes mots ~ –