QT如何实现我自己的内存查看器 [英] How can realize my own memory viewer by QT

查看:587
本文介绍了QT如何实现我自己的内存查看器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我正在为自己的硬件编写调试器。我想添加一个内存查看器小部件,如eclipse或qt创建者或其他IDE。但是,我不知道要使用哪种小部件。例如,tableWidget,有一些设置可以使它像这样:





解决方案

最好的方法是创建


为此,我们将从QAbstractScrollArea继承,从此类继承QTableView,QListView,QListWidget和QTableWidget。它旨在显示QScrollArea中的数据。
此外,此类的


Recently I am writing a debugger for my own hardware. I want to add a memory viewer widget like the eclipse or qt creator or other IDE. However, I have no idea what kind of widget to use. For example, tableWidget, is there some setting to make it like this:

解决方案

The best option is to create a custom widget because the task is private and none of the widgets are accommodated to the task.

For this we will inherit from QAbstractScrollArea, from this class inherit QTableView, QListView, QListWidget and QTableWidget. It is designed to display data within a QScrollArea. In addition documentation of this class tells us how to create a custom class.

When inheriting QAbstractScrollArea, you need to do the following:

  • Control the scroll bars by setting their range, value, page step, and tracking their movements.
  • Draw the contents of the area in the viewport according to the values of the scroll bars.
  • Handle events received by the viewport in viewportEvent()
  • notably resize events. Use viewport->update() to update the contents of the viewport instead of update() as all painting operations take place on the viewport.

Taking that reference I created the following widget:

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

An advantage of the implementation is that you do not have to load all the bytes directly since you can pass an object that inherits from QIODevice such as QFile and read the data when the view needs it by eliminating the memory overhead. In addition you can pass a QByteArray

In the following link you will find an example

这篇关于QT如何实现我自己的内存查看器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆