股票交易系统系统实现

 Qt信号和槽信核心机制

在谈系统的实现时必须先谈一下Qt编程的核心机制——信号和槽机制,要精通Qt编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是Qt的核心特性,简单来说当某个信号比如说click点击,doubleclick双击,当一个widgt绘图有改变,定时器循环到一个周期时,这些所有的事件都可以相当于一个信号发射,只要用一个QObject::connect()函数(具体怎么写,代码里很多很多实例),把对应的SIGNAL(信号)和SLOT(槽)连接,槽是普通的C++成员函数,可以被正常调用,他们可以有很多信号与其相关联,槽函数里写当信号改变时你想让系统完成的功能。这就是我对Qt的信号和槽的初步理解。随着我不断的学习,相信会理解的越来越深刻和准确的。[1]

5.2 系统实现关键代码

5.2.1 大小写转换伪代码

If(价格输入框里面的内容是不是为空)

定义变量分别存储价格输入框的值,整数部分的值;

小数部分的值等于输入的值减去整数部分;

定义一个空的QString字符串,留着存储处理流程完毕的最终结果;

定义一个存有"元", "拾", "佰", "仟", "万", "亿"的char数组;

定义一个存有"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"的char数组;

处理整数部分;

把字符转换为数字,即‘0’到0,‘1’到1,‘2’到2等这样;

添加计数单位;

最后在将处理结果QString传到ui中的价格显示的labline;

5.2.2 生成合同序号的代码

//生成合同序号函数

QString WeituoInput::reffMake()

{

    QSqlQuery query;

    query.exec("SELECT max(reff) from ashare_ordwth ");

    while(query.next())

    {

        //qDebug()<<"录入第"<<query.value(0).toInt()+1<<"条记录";

        int a = query.value(0).toInt();

        ++a;

        QString str = QString("%1").arg(a,10,10,QChar('0'));

        return str;

    }

}

5.2.3 画K线图关键代码

void DayLine::paintEvent(QPaintEvent *)

{

    QPainter painter(this);

    //坐标平移

    painter.translate(40,520);

    painter.drawText(-30,0,"(0,0)");

    QPen pen; //画笔

    //绘制背景各个虚线

    pen.setStyle(Qt::DotLine);   //设置画笔风格 点线

    painter.setPen(pen);

    //横向虚线

    for(int i = 0; i < 18; i++)

    {

        painter.drawLine(0,-30*i,1500,-30*i);

    }

    for(int i = 0; i < 15; i++)

    {

        painter.drawLine(150*i,0,150*i,-510);

    }

    //画日K线图

    float openPrice;//开盘价

    float closePrice;//收盘价

    float maxPrice;//最高价

    float minPrice;//最低价

    int j = 0;

    //    QList<double> open = values.at(3);

    //    qDebug()<<"开盘价"<<open;

    //    QList<double> high = values.at(2);

    //    qDebug()<<"最高价"<<high;

    //    QList<double> low = values.at(1);

    //    qDebug()<<"最低价"<<low;

    //    QList<double> close =values.at(0);

    //    qDebug()<<"收盘价"<<close;

    //新建两个Qlist用于得到所有最高价里的最大值和最低价里的最小值

    QList<double> maxlist =high;

    qDebug()<<"最高价maxlist排序前"<<maxlist;

    qSort(maxlist.begin(), maxlist.end(),qGreater<double>());//将最高价格按照递减排序得到

    QList<double> minlist =low;

    qDebug()<<"最低价minlist排序前"<<minlist;

    qSort(minlist.begin(), minlist.end());//将最高价格按照递增排序得到

    qDebug()<<"maxlist.at(0)"<<maxlist.at(0);

    qDebug()<<"minlist.at(0)"<<minlist.at(0);

    double highestMaxPrice =maxlist.at(0);

    double lowestMinPrice =minlist.at(0);

    for(int a=0;a<60;a++)

    {

        openPrice=open.at(a);

        minPrice=low.at(a);

        maxPrice=high.at(a);

        closePrice=close.at(a);

        j++;

        //开始对得到Qlist数据进行处理,画出K线图

        if(openPrice <= closePrice)

        {

            pen.setStyle(Qt::SolidLine);

            pen.setColor(QColor(255,0,0));

            QBrush brush(QColor(255,0,0)); //画刷

            painter.setPen(pen); //添加画笔

            painter.setBrush(brush); //添加画刷

            painter.drawRect(j*15+1,-350*(closePrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice),

                             13,-350*(closePrice-openPrice)/(highestMaxPrice - lowestMinPrice)); //绘制矩形           painter.drawLine(j*15+8,-350*(maxPrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice),                         j*15+8,-350*(minPrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice));   //绘制直线

        }

        else

        {

            pen.setStyle(Qt::SolidLine);

            pen.setColor(QColor(0,255,0));

            QBrush brush(QColor(0,255,0)); //画刷

            painter.setPen(pen); //添加画笔

            painter.setBrush(brush); //添加画刷          painter.drawRect(j*15+1,-350*(openPrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice),13,-350*(closePrice - openPrice)/(highestMaxPrice - lowestMinPrice)); //绘制矩形          painter.drawLine(j*15+8,-350*(maxPrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice),j*15+8,-350*(minPrice-lowestMinPrice)/(highestMaxPrice - lowestMinPrice));   //绘制直线

        }

    }

}

5.2.4 解析导入的.csv表格文件关键代码

处理导入的csv数据文件函数

QMultiMap <int,QList<double> >StockInfo::importData(QString PATH)

{

    QFile csvFile(PATH);

    QStringList CSVList;

    CSVList.clear();

    if (csvFile.open(QIODevice::ReadWrite))

    {

        QTextStream stream(&csvFile);

        while (!stream.atEnd())

        {

            CSVList.push_back(stream.readLine());//push_back作用为在list尾部加入一个数据

        }

        csvFile.close();

    }

    //处理之前先声明四个Qlist分别用来存储开收高低四个价格

    QList<double> open;

    QList<double> high;

    QList<double> low;

    QList<double> close;

    int i;

    for(i=0;i<60;i++)

    {

        QStringList stockList = CSVList[i+1].split(",");

        //使用Inseert而不用append是因为这样可以把本来读取到的今天的数据在最前面转换到最后去

        open.insert(0,stockList[1].toDouble());

        high.insert(0,stockList[2].toDouble());

        low.insert(0,stockList[3].toDouble());

        close.insert(0,stockList[4].toDouble());

    }

    qDebug()<<"stockinfo中开盘价"<<open;

    qDebug()<<"stockinfo中最高价"<<high;

    qDebug()<<"stockinfo中最低价"<<low;

    qDebug()<<"stockinfo中收盘价"<<close;

    //然后把这个四个list用多值QMap存储返回待用

    QMultiMap <int,QList<double> > multimap;

    multimap.insert(0,open);

    multimap.insert(0,high);

    multimap.insert(0,low);

    multimap.insert(0,close);

    return multimap;

}

5.2.5 “价格优先,时间优先”撮合原则关键代码

第一步:首先分别用两个函数将委托表中的委托记录按照买卖标志’B’或者’s’来排序

1.买的记录按照价格从高到低排序

void PanKou::getB_record()

{

    //过滤出买入的记录

    B_model->setFilter(QObject::tr("bs= '%1'").arg("B"));

    //根据价格属性,即第7列,按价格降序排列保证买入队列价格高的在最前面

    B_model->setSort(7,Qt::DescendingOrder);

}

2.卖的记录按照价格从低到高排序

void PanKou::getS_record()

{

    //过滤出卖出的记录

    S_model->setFilter(QObject::tr("bs= '%1'").arg("S"));

    //根据价格属性,即第7列,按价格升序排列保证卖出队列价格低的在最前面

    S_model->setSort(7,Qt::AscendingOrder);

}

第二步:

  if(买的记录的股票代码==卖的记录的股票代码)

{

   If(买的记录价格>=卖的记录的价格)

{

取出该价格的所有记录按照时间先后顺序排列

for(a=0;a<B_model->rowCount();a++)

                    {  

                        B=a;//传出买入成功记录的序号

                        int B_Qty = B_model->record(a).value("Qty").toInt();

                        for( b=0;b<S_model->rowCount();b++)

                        {  

                            S=b;//传出卖出成功记录的序号

                            int S_Qty = S_model->record(b).value("Qty").toInt();

                            if(买的数量<卖的数量)

                            {

向成交回报表新增两条记录,一条是买成功的记录,一条是卖成功的记录;

            把委托数据库表中的卖队列数量更新,买队列的记录删除;

}

              if(买的数量==卖的数量)

                            {

向成交回报表新增两条记录,一条是买成功的记录,一条是卖成功的记录;

            把委托数据库表中的买卖队列的记录都删除;

}

              if(买的数量>卖的数量)

                            {

向成交回报表新增两条记录,一条是买成功的记录,一条是卖成功的记录;

            把委托数据库表中的买队列数量更新,卖队列的记录删除;

}

}

}

}

5.3 系统实现遇到问题及关键技术

5.3.1  QString的arg方法

在源码中很多地方需要用到Qstring的arg方法,可以解决很多问题:

  1. 在sql语句中使用变量

QString acc = ui->gddmEdit->text();

        QString stock = ui->zqdmEdit->text();

        //  在SQL语句中使用变量!!!

        //求出买入的总数

        QSqlQuery query1;

        query1.exec(QString("select sum(Qty) from ashare_ordwth where acc=%1 and stock=%2 and bs=%3").arg(acc).arg(stock).arg("'B';"));

第二行代码中由于要查询的acc,stock,bs都是变量,使用arg函数后,就可以用arg后面的acc,stock和‘B’来替换,实现传参的sql查询。[1]

  1. 实现将‘1’变为‘B0001’这样的形式

QString的arg()方法用于填充字符串中的%1,%2...为给定的参数,如

QString m = tr("%1:%2:%3").arg("12").arg("60").arg("60");    // m = "12:60:60:

它还有另外一种重载方法:

QString QString::arg(int a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char( ' ' )) const

这个方法用于填充字符串中的%1,%2...为给定格式的整形数字,其中第一个参数是要填充的数字,第二个参数为最小宽度,第三个参数为进制,第四个参数为当原始数字长度不足最小宽度时用于填充的字符。

例如:

QString text = QString("%1:%2").arg(123, 5, 10, QChar('0')).arg(456, 5, 10, QChar('0'));    // text = "00123:00456"[2]

  1. 实现将科学计数法转换为普通的输出格式

QString QString::arg(double a,int fieldWidth = 0,char format ='g',int precision = -1, QChar fillChar = QLatin1Char(' '))const

多了两个参数:format和precision,一个指明规格,一个指明精度。规格默认为 'g' 或 'G',指示后面的精度为整数和小数部分总和的长度;规格为'e'或 'E' 时,表示为科学记数法形式,精度部分指示的为小数部分的位数长度;

规格为f时,规格为其他字符时,无作用,输出原double数字。如:

doubled = 11.345689;

str = QString("delta: %1").arg(d, 0,'g',4);

//结果为:"delta: 11.35"     ---这里进行了四舍五入

str = QString("delta: %1").arg(d, 0,'G',5);

//结果为:"delta: 11.346"     ---这里进行了四舍五入,也就是format为g或者G结果是一样的

str = QString("delta: %1").arg(d, 0,'e',4);

//结果为:"delta: 1.2346e+01"  

str = QString("delta: %1").arg(d, 0,'E',4);

//结果为:"delta: 1.2346E+01"   --当format为e或者E时,精度表示的是小数点后的位数

str = QString("delta: %1").arg(d, 0,'f',4);

//结果为:"delta: 11.3457"   --四舍五入

str = QString("delta: %1").arg(d, 0,'r',4);

//结果为:"delta: 11.3457"

str = QString("delta: %1").arg(d, 0,'Q',4);

//结果为:"delta: 11.3457"   --当format为f或者其他字符时,以原格式输出,而且精度表示小数点后的位数,而且采取四舍五入[4]

5.3.2  QMultiMap的用法

Map是单值类型的,也就是说,如果一个新的值分配给一个已存在的键,则旧值会被覆盖。如果你需要让一个key可以索引多个值,可以使用QMultiMap<K, T>。这个类允许一个key索引多个value,如:

QMultiMap<int, QString> multiMap;

multiMap.insert(1, "one");

multiMap.insert(1, "eins");

multiMap.insert(1, "uno");

QList<QString> vals = multiMap.values(1)

主要是对value和values的理解:

详情我是参考了博客:http://devbean.blog.51cto.com/448512/248373/的介绍。[4]

5.3.3  Qcustomplot绘图控件的使用

我使用这个控件主要是想利用他来画K线图,但是我研究了这个控件后,知道了里面有一个已经实现了的方法是专门画K线图的,叫作qcpfinancial,我看了这个类里面的所有方法,当看到蜡烛图和ohcl时,很兴奋,但是在我准备把自己的数据传入,希望用这个类画出我想要的图时,发现并不是我要的效果,在很长一段时间里,我不断的看这个类里方法的说明。以为我是用错了。里面的setdata()方法,我知道怎么传值。最后我还是没能画出来。于是我不得不自己写方法去画K线图。

答辩完后,我尝试着翻墙去寻找这个类的用法,我相信一定是我哪里代码写的有问题。终于在我放弃使用这个类,准备回公司去问前辈的,我想我应该学习一下另外一个绘图空间QWT,在这个控件里我也研究了它专门用来画金融行业图像的类。终于我观察代码,发现了我不能画出正确图形的原因,是因为我没有把样式设置为蜡烛图,而默认的画图样式是另外一种叫作bar的图形,也许只是因为我对股票图形的了解不多,如果我知道还有这种图像的时候,我肯定会知道我只是设置错了图形样式。

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等天晴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值