gpt4 book ai didi

c++ - QT如何实现自己的内存查看器

转载 作者:行者123 更新时间:2023-11-28 01:43:08 26 4
gpt4 key购买 nike

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

enter image description here

enter image description here

最佳答案

最好的选择是创建一个自定义小部件,因为该任务是私有(private)的,并且没有任何小部件适合该任务。

为此我们将从QAbstractScrollArea继承,从这个类继承QTableView、QListView、QListWidget和QTableWidget。它旨在显示 QScrollArea 内的数据。另外documentation这个类告诉我们如何创建自定义类。

When inheriting QAbstractScrollArea, you need to do the following:

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

根据该引用,我创建了以下小部件:

内存查看器.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

内存查看器.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();
}

该实现的一个优点是您不必直接加载所有字节,因为您可以传递一个继承自 QIODevice 的对象,例如 QFile 并读取通过消除内存开销,在 View 需要数据时调用数据。另外你可以传递一个QByteArray

在下面link你会找到一个例子

enter image description here

关于c++ - QT如何实现自己的内存查看器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46375673/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com