- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
最近我正在为我自己的硬件编写一个调试器。我想添加一个内存查看器小部件,如 eclipse 或 qt creator 或其他 IDE。但是,我不知道要使用哪种小部件。比如tableWidget,有没有设置成这样:
最佳答案
最好的选择是创建一个自定义小部件,因为该任务是私有(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你会找到一个例子
关于c++ - QT如何实现自己的内存查看器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46375673/
我之前让 dll 注入(inject)器变得简单,但我有 Windows 7,我用 C# 和 C++ 做了它,它工作得很好!但是现在当我在 Windows 8 中尝试相同的代码时,它似乎没有以正确的方
我正在尝试制作一个名为 core-splitter 的元素,该元素在 1.0 中已弃用,因为它在我们的项目中起着关键作用。 如果您不知道 core-splitter 的作用,我可以提供一个简短的描述。
我有几个不同的蜘蛛,想一次运行所有它们。基于 this和 this ,我可以在同一个进程中运行多个蜘蛛。但是,我不知道如何设计一个信号系统来在所有蜘蛛都完成后停止 react 器。 我试过了: cra
有没有办法在达到特定条件时停止扭曲 react 器。例如,如果一个变量被设置为某个值,那么 react 器应该停止吗? 最佳答案 理想情况下,您不会将变量设置为一个值并停止 react 器,而是调用
https://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js 上面的链接定义了外部js文件,我不知道Angular-1.0.0rc9.js的注入(in
我正在尝试运行一个函数并将服务注入(inject)其中。我认为这可以使用 $injector 轻松完成.所以我尝试了以下(简化示例): angular.injector().invoke( [ "$q
在 google Guice 中,我可以使用函数 createInjector 创建基于多个模块的注入(inject)器。 因为我使用 GWT.create 在 GoogleGin 中实例化注入(in
我在 ASP.NET Core 1.1 解决方案中使用配置绑定(bind)。基本上,我在“ConfigureServices Startup”部分中有一些用于绑定(bind)的简单代码,如下所示: s
我在 Spring MVC 中设置 initBinder 时遇到一些问题。我有一个 ModelAttribute,它有一个有时会显示的字段。 public class Model { privat
我正在尝试通过jquery post发布knockoutjs View 模型 var $form = $('#barcodeTemplate form'); var data = ko.toJS(vm
如何为包含多态对象集合的复杂模型编写自定义模型绑定(bind)程序? 我有下一个模型结构: public class CustomAttributeValueViewModel { publi
您好,我正在尝试实现我在 this article 中找到的扩展方法对于简单的注入(inject)器,因为它不支持开箱即用的特定构造函数的注册。 根据这篇文章,我需要用一个假的委托(delegate)
你好,我想自动注册我的依赖项。 我现在拥有的是: public interface IRepository where T : class public interface IFolderReposi
我正在使用 Jasmine 测试一些 Angular.js 代码。为此,我需要一个 Angular 注入(inject)器: var injector = angular.injector(['ng'
我正在使用 Matlab 代码生成器。不可能包含代码风格指南。这就是为什么我正在寻找一个工具来“ reshape ”、重命名和重新格式化生成的代码,根据我的: 功能横幅约定 文件横幅约定 命名约定 等
这个问题在这里已经有了答案: Where and why do I have to put the "template" and "typename" keywords? (8 个答案) 关闭 8
我开发了一种工具,可以更改某些程序的外观。为此,我需要在某些进程中注入(inject)一个 dll。 现在我基本上使用这个 approach .问题通常是人们无法注入(inject) dll,因为他们
我想使用 swing、spring 和 hibernate 编写一个 java 应用程序。 我想使用数据绑定(bind)器用 bean 的值填充 gui,并且我还希望它反射(reflect) gui
我有这段代码,当两个蜘蛛完成后,程序仍在运行。 #!C:\Python27\python.exe from twisted.internet import reactor from scrapy.cr
要点是 Spring Batch (v2) 测试框架具有带有 @Autowired 注释的 JobLauncherTestUtils.setJob。我们的测试套件有多个 Job 类提供者。因为这个类不
我是一名优秀的程序员,十分优秀!