一、获取txt中的数据并保存在缓冲区
//打开并读取相应文件,将所有数据保存在buffer中
unsigned int buffer[10000];
QFile file("D:/Qt/work/readtxt/test_8192.txt");//打开txt文件
if(file.open(QIODevice::ReadOnly))
{
int j=0;
QTextStream in(&file);//QTextStream 可以逐行读取
while(!in.atEnd())
{
QString line=in.readLine();//从文本流中读取一行文本,下一次就读取下一行数据,并将其作为QString返回。
//QString hexstr("0x");
//line=line.remove(hexstr);//删除0x
//SkipEmptyParts--->如果字段为空,则不要将其包含在结果中
//QStringList items=line.split(",",QString::SkipEmptyParts);
QStringList items=line.split(" ",QString::SkipEmptyParts);//以空格作为分隔符,且不包含空格
qDebug()<<"txt文件中第"<<j+1<<"行的数据个数为:"<<items.count()<<endl;//打印每行数据的个数
bool OK;
//每items.count()个数据存入一组,将文件中的数据存入buffer中
for(int i=0;i<items.count();i++)
{
//注意文件中是什么类型的数据,需要合理改变进制!!!!!!!!!!
buffer[i+count]=items[i].toUInt(&OK,10);//将QString类型转换为unsigned int类型;以10进制方式读取字符串;OK为判断时是否转换成功
// qDebug()<<"第"<<i+count<<"个数据为:"<<buffer[i+count];
}
qDebug()<<endl;
j++;
count+=items.count();
}
qDebug()<<"txt文件中数据的总数为:"<<count<<endl;//打印文件中数据的总数
}
else
qDebug()<<"files open error!"<<endl;
二、按照所需要求将buffer中的数据存入drawdata
//将buffer中符合要求的数据保存在drawdata中
for(int i=0;i<count/2048;i++)
{
flag=2048*i+flag8+flag9;
if(buffer[flag]==9999999&&buffer[flag+1]==8888888&&buffer[2050+flag]==9999999)
{
flag8+=1;//含有8888888的标志位
for(int j=0;j<2048;j++)
{
drawdata[j+2048*valid]=buffer[flag+2+j];
}
valid++;//记录有效的2024个数据有多少组
}
if(buffer[flag]==9999999)
{
flag9+=1;//含有9999999的标志位
}
}
drawdata_count=2048*valid;
三、绘制坐标轴并将获取的数据显示
//绘画事件
void myDialog::paintEvent(QPaintEvent *event)
{
QPainter painter(this);//相当于QPainter *painter=new QPainter(this);实例化对象写法
//定义一个(60,40)点-->由w和h去画矩形(大小由窗口大小去控制)
QRect rect(3*Margin, 2*Margin,width() - 8 * Margin, height() - 4 * Margin);//Margin = 20
if (!rect.isValid())//矩形有效返回真
return;
QPen quiteDark = palette().dark().color().light();
QPen light = palette().light().color();
//画竖直方向的垂直线和x轴坐标值
for (int i = 0; i <= (width() - 8 * Margin)/50; ++i)//0到numXticks
{
//间隔为(rect.width() - 1)/ numXticks时为平均间隔
//此处间隔为50
int x = rect.left() +50*i;// (i * (rect.width() - 1)/ numXticks);
painter.setPen(Qt::black);
painter.drawLine(rect.left(), rect.top(), rect.left(), rect.bottom());
painter.setPen(Qt::DotLine);//虚线
painter.drawLine(x, rect.top(), x, rect.bottom());//所有y轴方向线
painter.setPen(Qt::blue);
painter.drawLine(x, rect.bottom(), x, rect.bottom() + 5);//x轴的折线和坐标值
if(i!=0)
{
/*flags: Qt::AlignHCenter | Qt::AlignTop-->靠上垂直居中
在具有原点(x, y)、宽度和高度的矩形内绘制给定文本。
void QPainter::drawText(int x, int y, int width, int height,
int flags, const QString &text,
QRect *boundingRect = Q_NULLPTR)*/
painter.drawText(x, rect.bottom() + 5, 30, 30,
Qt::AlignHCenter | Qt::AlignTop,
QString::number(i*50));
}
}
//画水平方向的水平线和y轴坐标值
int y;
for (int j = 0; j <= (height() - 4 * Margin)/50; ++j)
{
y = rect.bottom() -50*j;// (j * (rect.height() - 1)/ numYticks);
painter.setPen(Qt::black);
painter.drawLine(rect.left(), rect.bottom(), rect.right(), rect.bottom());
painter.setPen(Qt::DotLine);
painter.drawLine(rect.left(), y, rect.right(), y);//所有x轴方向线
painter.setPen(Qt::blue);
painter.drawLine(rect.left() - 5, y, rect.left(), y);//y轴的折线和坐标值
if(j!=0)
{
//AlignRight | Qt::AlignVCenter-->靠右水平居中
painter.drawText(rect.left() - 2.5*Margin, y - 10, 60, 30,
Qt::AlignLeft | Qt::AlignVCenter,
QString::number(j*50000));
}
}
painter.drawText(rect.left()-10,rect.top()-10,"ADC值");//Y轴
painter.drawText(rect.right()+5,rect.bottom()+5,"500M");//水平轴
painter.drawText(rect.left()-8,rect.bottom()+15,"O");//原点
//将每个数据用点表示
QPoint points[2048];//设置drawdata_count个点去表示drawdata的drawdata_count个数据
for(int i=0;i<2048;i++)
{
//两点的间隔为500M/2048个点
float M=500;
float point=2048;
float interval=M/point;
points[i].setX(i*interval+rect.left());
//points[i].setY(drawdata[i]*(rect.height())/maxY+rect.top()+y*2);//sin函数时
float proportion=1000;
float Y=drawdata[i]/proportion;//将Y值根据坐标值比例缩小
points[i].setY(rect.bottom()-Y);//从原点开始画
}
painter.setPen(Qt::red);
painter.drawPoints(points, 2048);//绘制这些点
//将每个点连接起来画折线图
int x1,y1,x2,y2;
x1=points[0].x();
y1=points[0].y();
for(int i=1;i<2048;i++)
{
x2=points[i].x();
y2=points[i].y();
painter.setPen(Qt::red);
painter.drawLine(x1,y1,x2,y2);
x1=x2;y1=y2;//进行交换,让折线图能够连接起来
}
}
四、实时动态更新波形
//利用定时器实时刷新图片
/*定时器是用来处理周期性事件的一种对象,类似于硬件定时器。例如设置一个定时器的定时周期为1000毫秒,
那么每1000毫秒就会发射定时器的timeout()信号,在信号关联的槽函数里就可以做相应的处理。*/
timer = new QTimer(this);
connect( timer, SIGNAL(timeout()), this, SLOT(flushBuff()));
timer->start(2000);//启动或者重启服务器,msec(10000)为时间间隔,表示10s,没有参数时,时间间隔为0.
//实时刷新图片的槽函数
void myDialog::flushBuff()
{
/*滚动刷新*/
// unsigned int tmp = drawdata[0];
// for(int i=0; i<count-1; i++ )
// {
// drawdata[i] = drawdata[i+1];
// }
// drawdata[count-1] = tmp;//保留数据
/*全屏替代刷新*/
slot=0;//清空计数
for(int i=0; i<2048; i++ )//将第一组2048个数据存入一个缓冲器内部
{
drawdata_buffer[i] = drawdata[i];
}
for(int j=0;j<valid-1;j++)
{
for(int i=0; i<2048; i++ )
{
drawdata[i+2048*slot] = drawdata[i+2048*(slot+1)];
}
slot++;
}
for(int i=0; i<2048; i++ )//将缓冲器内部的数据给最后一个组,进行交替
{
drawdata[i+2048*slot] = drawdata_buffer[i];
}
update();//update()调用绘图事件来实现画面更新,更新界面
}