Java Applet编制的股票交易软件 发我看看,我也感兴趣[email protected] 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 也给我一份,共同研究研究[email protected] 发我一份[email protected] 发我一份[email protected]谢了! 发我一份,我很感兴趣[email protected]多谢! 是行情呢?还是交易?还是一个整体的解决呢?这些东西以前我都做过,很无聊,如果有时间你来找我好了:[email protected]我现在忙着找工作,无聊的要死了 发我一份[email protected] 因为本人从事java多年、炒股多年??这水平还看不懂代码,applet股票软件不就是做个服务器建以ServerSocket与前Socket时实通信,采样用Java.awt.包或可能的话用Java2D去画点,线晕 各位朋友、你们瞧瞧网上的java 做的股票软件,然后查看其页面的html脚本,由路径down下来即可,然后用jad反编译就行! 发给我看看,一起研究[email protected] 发给我看看,一起研究[email protected] 具体down相应软件反编译在java网络编程书(用个动物图像的)有地址去downdj反编,自己看转---☆ 用Java绘制K线图 ☆ 作者:追风 Java语言中的Applet(Java小程序)和Application(Java应用程序)是在结构和功能上都存在很大差异的两种不同的编程方式。Applet应用于Web页上,可做出多姿多彩的页面特效,给网站增辉添色;Application则与其他编程语言(如VB、VC)一样,可编制各种应用程序。 本文要讨论的是第一种情况,在Web页上用Java Applet绘制K线图。 K线是股市行情分析中的一种参数指标,用股票每日的开盘价、最高价、最低价、收盘价及成交量等数据进行作图,配合五日、十日均线便可反映出一个阶段内该支股票的涨跌走势。 Java Applet所做的K线图多应用于证券类型的网站,以方便网上股民的分析操作。不过由于我国网速的关系,目前有些证券类网站把K线图做成了图片以节省下载的时间。当然,其绘制K线所用的工具(Java Applet)及绘制方法还是相同的。 在编写绘制K线的Java Applet时,有几处关键问题要解决,即:1)多线程的使用;2)布局管理器的选择;3)数据输入、输出流的应用;4)设置、监听鼠标与键盘事件。 下面通过一个实例,来详细阐述整个编程过程和方法。《查看演示》 一、使用多线程 一个完整的Java Applet包含四个方法,Init()、Start()、Stop()、Destroy()(即:初始化、开始、停止、清除),构成一个完整的生命周期,其运行次序也是由上而下顺序执行。 在绘制K线图的过程中,除了要绘制窗体及代表股票升降的阴线、阳线矩形外,还要监听鼠标事件并同时绘制一个自由移动的“十字”游标,来定位显示所检索股票每日的各种价格数值(如开盘价、收盘价等);这时,为了避免闪烁和减少重新计算的等待时间,除了重绘跟随鼠标移动的“十字”游标外,对页面的布局及阴线、阳线矩形等不进行重绘;这就需要应用多线程来完成该项任务。 1.关于多线程的一些基本概念: 多线程实际上就是启动另一个进程,其运行的过程独立于主程序之外,并从主程序的Start()方法载入、由Run()方法调用执行。实现多线程的方法有两种,即:创建Thread类的子类(类的继承)和实现runnable接口。 为便于使用,Java把所有有关线程的功能封装成Java类库中的一个类:Java.lang.Thread。通过这个类,Java可以创建、控制和终止线程,完成有关多线程的所有操作。 在Java语言中,一个子类只能继承一个超类(父类),由于我们所要编写的Java Applet是应用于网页中的,首先必须继承浏览器类(java.applet);因此,在本例中我们通过实现runnable接口的方法来实现多线程,实现的语句如下: public class StockApplet extends java.applet.Applet implements Runnable 2.多线程的应用: 首先,在Init()方法中对要创建的线程(M_pointThread)进行定义及初始化: Thread M_pointThread=null; 然后,在Start()和Stop()方法中加入以下代码: //当打开浏览器页面开始载入Java Applet代码时,执行start()方法 public void start() {if (M_pointThread==null) //如果线程尚未产生{M_pointThread=new Thread(this); //则创建一个新线程M_pointThread.start(); //启动该线程}} //在当前页面关闭或转向其他Web页面时, 调用stop()方法,以释放系统资源public void stop(){if (M_pointThread!=null) //如果线程尚在运行{ M_pointThread.stop(); //停止该线程 M_pointThread=null; //释放线程所占资源}} 3.编写线程运行的代码: public void run() {M_graphics=getGraphics();M_graphics.setXORMode(Color.white); //采用异或方法绘制“十字”游标while(true) { try { if(MouseMove==true) //侦测到鼠标的移动后,执行以下代码{ //当鼠标位于以下区域(Java Applet布局)内时,执行画线操作 if(x0 >50 && x0< 600){M_graphics.drawLine(x0,30,x0,380);} if(y0 >30 && y0 <380){M_graphics.drawLine(50,y0,600,y0);} if(X >50 && X< 600){M_graphics.drawLine(X,30,X,380);} if(Y >30 && Y< 380){M_graphics.drawLine(50,Y,600,Y);} MouseMove=fase; x0=X; //传递当前座标参数 y0=Y; }}catch(NullPointerException npe){} //捕获可能出现的异常 } 二、布局管理器 本例中的Java Applet运行时,要在页面上Java Applet的运行区域内绘制相应的“标签”来显示不同的数值,并要加入一个“文本框”来接收输入的股票代码。对这些“标签”和“文本框”位置及大小的设定,便属于布局管理的应用范畴。 Java语言中提供的布局管理器种类有:边界式布局、卡片式布局、流式布局和网格式布局等,各有不同的特点,可根据实际需要选用;但有最大自由设计空间的是“无布局管理器”——即不使用任何布局格式,而通过手工方式添加组件到页面布局的绝对位置上。本例中使用的便是“无布局管理器”。 在使用“无布局管理器”时,首先要作出声明,即: setLayout(null); 然后用reshape()方法指定组件的具体位置和尺寸, 基本语句如下所示: Label label1=new Label(); //定义标签this.add(label1); //把标签加入布局管理器label1.reshape(10,10,30,30); //在指定位置绘制标签 对于多个标签和文本框,参照此格式添加即可。 三、输入、输出数据流 Java Applet在客户端浏览器上运行时,要从服务器端读取股票的相关数据进行做图,这就涉及到Java数据流的运用。 Java.io包提供了多个用于与各种I/O设备交换信息的类,其最顶层的两个类便是输入流类(InputStream)和输出流类(OutputStream)。 为了便于实现,在本例中我们先在服务器端把股票数据库(如:show128.dbf)中的有关字段写入一文本文件中(其格式为:第一行为股票的汉字名称,以后每一行内包括:开盘日期、开盘价、最高价、最低价、收盘价、成交量),并以该支股票的代码作为文件名(如:600001.txt);然后,再用Java Applet从服务器端的文本文件中读取数据。这样,就把对服务器端数据库的访问转化为对文件的I/O操作,实现的语句如下: URL urlc=new URL("http://127.0.0.1/"+FileName+".txt"); BufferedReader bis=new BufferedReader(new InputStreamReader(urlc.openStream())); 注:第一条语句中的http://127.0.0.1/为在本机执行调试操作的URL地址,在上传到服务器上后要做相应的修改;FileName为要读取的文本文件名。 第二条语句定义了读取输入数据流的方法。 四、监听键盘及鼠标事件 在Java Applet小程序中,单击按钮、键入文本、使用鼠标或执行任何与界面相关的动作时,就发生一个事件,小程序就会作出适当的反应。 在本例中,我们通过使用action()方法来获得Java Applet小程序运行时所发生的事件。语句格式如下: public boolean action(Event evt,Object arg){FileName=text1.getText(); //提取文本框中输入的参数ReadData(); //调用读数据流数据的方法return true; //处理完毕,不需要其他方法再做处理} 上面的action()方法中含有两个参数:一个是Event类的一个对象evt;另一个是Object类的一个对象arg。Event对象告诉我们发生了哪种事件,而Object对象将进一步告诉我们有关该事件的情况。每当有Event监听的事件发生时,Java Applet便自动调用该action()方法。 至此,在掌握了上述编程中的一些要点后,我们便可以成功地编制出一个完整的绘制K线的Java Applet小程序了(完整的源代码下载)。 五、编制HTML文档(Stock.html) 程序编制完成后,另外要做的是设置在Web页面上调用Java Applet的页面,即编制HTML文档。Stock.html文档的示例代码如下: <HTML>< HEAD >< TITLE >股票K线图< /TITLE >< /HEAD ><body bgcolor=#00ffff ><APPLET code=StockApplet.class name=StockApplet HEIGHT=500 WIDTH=400></APPLET >< /body >< /HTML > 在< APPLET >< /APPLET >标签对内,是对Java Applet小程序的调用代码。其中的StockApplet.class是经编译后生成的class文件,codeBase指向的是class文件所存放的路径。如果class文件与HTML文档存放在同一目录下,则可以省略这一项。 至此,编制Java Applet小程序的工作便全部完成。 在个人计算机上进行调试时,首先要安装个人Web服务,然后,把StockApplet.class与HTML文档一起拷贝到本机的WWW服务目录下(如:C:\Inetpub\wwwroot\),打开浏览器,在地址栏内输入http://127.0.0.1/Stock.html,回车,进行测试操作。 调试通过后,便可上传至服务器投入运行了。 [email protected]本人正在尝试做一个个人股票管理系统 import java.applet.*; import java.awt.*; import java.io.*; import java.net.*;public class StockApplet extends java.applet.Applet implements Runnable{ //以下是公用变量的声明部分 int Move_Length=0,Move_Sum=0; String FileName,Name_Str,Content_Date; int SP[]=new int[2000]; int KP[]=new int[2000]; int JD[]=new int[2000]; int JG[]=new int[2000]; int Mid_Worth[]=new int[2000]; String myDate[]=new String[2000]; double CJL[]=new double[2000]; double MaxCJL,MidCJL; Label label[]=new Label[10]; int MaxWorth,MinWorth;int x_move0,x_move1,MaxLength=0; int x0,y0,X,Y,Record_Num; boolean Mouse_Move,Name_Change=true; int JX_Five1,JX_Five2,JX_Ten1,JX_Ten2;public void init(){ TextField text1=new TextField(); Thread M_pointThread=null; setLayout(null); //声明布局管理器 this.setBackground(Color.white); //设置背景色 this.setForeground(Color.black); //设定文字颜色 for(int i=1;i< 10;i++) //以下循环用于向布局中添加标签 { label[i]=new Label(); this.add(label[i]); label[i].reshape(i*80-65,10,50,15); if(i==2){label[i].reshape(80,10,70,15);} if(i==7){label[i].reshape(510,10,80,15);} if(i >7){label[i].reshape((i-8)*490+45,380,70,15);} } FileName="000001"; //程序启动时的默认股票代码 Name_Str="上证指数"; this.add(text1); //向布局中添加文本框 text1.reshape(150,385,70,20); text1.getText(); //取得文本框中输入的内容}public void start(){ //创建并启动多线程 if (M_pointThread==null) { M_pointThread=new Thread(this); M_pointThread.start(); }}public void run(){ //运行多线程 Graphics M_graphics; M_graphics=getGraphics(); M_graphics.setXORMode(Color.white); while(true) //绘制“十字”游标 { try { if(Mouse_Move==true) { if(x0 >50 & x0< 600){M_graphics.drawLine(x0,30,x0,380);} if(y0 >30 & y0< 380){M_graphics.drawLine(50,y0,600,y0);} if(X >50 & X< 600){M_graphics.drawLine(X,30,X,380);} if(Y >30 & Y< 380){M_graphics.drawLine(50,Y,600,Y);} Mouse_Move=false; x0=X; y0=Y; } }catch(NullPointerException npe){} }}public boolean action(Event evt,Object arg) //监测事件 { FileName=text1.getText(); //取得新文件名 repaint(); //将各变量恢复初始状态 Name_Change=true; Move_Length=0; Move_Sum=0; MaxLength=0; MaxCJL=0; return true; }public boolean keyDown(Event evt,int key) //检测键盘事件 { if(key==10) //检测是否是回车键 { Event event=new Event(text1,Event.ACTION_EVENT,"text1"); deliverEvent(event); return true; } return false; }public boolean mouseDown(Event evt,int x_d,int y_d) //检测按下鼠标按键事件{ x_move0=x_d; //记录鼠标当前的横座标 x0=x_d; //把当前座标传递给另一线程 y0=y_d; return true;} public boolean mouseUp(Event evt,int x_up,int y_up) //检测释放鼠标按键事件{ int Screen=520; //定义在页面上的显示区域 x_move1=x_up; //记录鼠标当前的横座标 Move_Length=((int)(x_move1-x_move0)/10)*10; //计算鼠标移动距离 Move_Sum=Move_Sum+Move_Length; if(Move_Sum< 0){Move_Sum=0;} //控制K线的拖动范围 if(Move_Sum >MaxLength-Screen){Move_Sum=MaxLength-Screen-10;} x0=x_up; //把当前座标传递给另一线程 y0=y_up; MaxWorth=JG[Move_Sum]; MinWorth=JD[Move_Sum]; MaxCJL=CJL[Move_Sum];//以下循环用于查找页面显示区域内的最高、最低值及成交量 for(int i=Screen+Move_Sum;i >Move_Sum;i-=10) { if(MaxWorth< JG[i]){MaxWorth=JG[i];} if(MinWorth >JD[i]){MinWorth=JD[i];} if(MaxCJL< CJL[i]){MaxCJL=CJL[i];} } MidCJL=MaxCJL/2; for(int i=1;i< 7;i++) //计算出在纵座标上显示的中间值 { Mid_Worth[i]=MinWorth+(MaxWorth-MinWorth)/7*(7-i); } repaint(); return true;}public boolean mouseMove(Event evt,int x_m,int y_m) //检测鼠标移动事件{ int Axsis,MNumberR; Mouse_Move=true; Axsis=560+Move_Sum-((int)(x_m/10))*10; //设定横座标范围 if(Axsis >MaxLength){Axsis=MaxLength;} //在以下区域内,把鼠标当前横座标处的各种股票参数显示在相应的标签上 if(x_m >50&x_m< 600) { label[2].setText(myDate[Axsis]); label[3].setText(String.valueOf((float)KP[Axsis]/100)); label[4].setText(String.valueOf((float)JG[Axsis]/100)); label[5].setText(String.valueOf((float)JD[Axsis]/100)); label[6].setText(String.valueOf((float)SP[Axsis]/100)); label[7].setText(String.valueOf((int)CJL[Axsis])); label[8].setText(myDate[510+Move_Sum]); MNumberR=Move_Sum; if(Move_Sum >30){MNumberR=Move_Sum-30;} label[9].setText(myDate[MNumberR]); X=x_m; //把当前座标传递给另一线程 Y=y_m; } return true;}public void stop() //当页面关闭或转向其他页面时,释放系统资源{ if (M_pointThread!=null) { M_pointThread.stop(); M_pointThread=null; }}public void paint(Graphics g) //绘图方法{ if(Name_Change==true) //若改变了查询股票的代码 { ReadData(); //则重新读取数据 Name_Change=false; } PaintFrame(g); //调用绘制页面区域方法 PaintData(g); //调用绘制K线数据方法 x0=-1; y0=-1;}private void PaintFrame(Graphics g) //绘制页面区域方法{int nWidth =600;int nHeight=260;g.setColor(Color.white); g.fillRect(0,0,600,420); g.setColor(Color.black);g.fillRect(50,30,550,350);g.setColor(Color.white);g.drawLine(50,nHeight,nWidth,nHeight); //画出上下两区域间的分隔线g.setColor(Color.black); //设置字体颜色 for(int i=1;i< 7;i++) //绘出纵座标中间数值 { g.drawString(String.valueOf((float)Mid_Worth[i]/100),10,55+i*30); } g.drawString(String.valueOf((int)MaxCJL),2,270); g.drawString(String.valueOf((int)MidCJL),8,325); g.drawString("0",40,380);} public void PaintData(Graphics g) //绘制K线数据方法{ int SPPoint[]=new int[2000]; int KPPoint[]=new int[2000]; int JGPoint[]=new int[2000]; int JDPoint[]=new int[2000]; double CJLPoint[]=new double[2000]; int Left_Start=40,reDraw=250; //设置绘图左边界及参数 int i=0; int JxTemp1=0,JxTemp2=0;//以下语句在布局区域内绘出固定信息 g.setColor(Color.red); g.drawString("牡丹江",5,45); g.drawString("信息港",5,60); g.setColor(Color.black); g.drawString("开盘",150,20); g.drawString("最高",230,20); g.drawString("最低",310,20); g.drawString("收盘",390,20); g.drawString("成交量",470,20); g.drawString("要查询其他股票,请输入股票代码,然后回车。",230,400); for(int N=MaxLength;N >=0;N-=10) //该循环用于在绘图区域内作图 { //计算股票各参数在绘图区域内要显示的相对值 KPPoint[N]=((KP[N]-MinWorth)*200/(MaxWorth-MinWorth)); SPPoint[N]=((SP[N]-MinWorth)*200/(MaxWorth-MinWorth)); JGPoint[N]=((JG[N]-MinWorth)*200/(MaxWorth-MinWorth)); JDPoint[N]=((JD[N]-MinWorth)*200/(MaxWorth-MinWorth)); CJLPoint[N]=(CJL[N]*120/MaxCJL); for(int Num=0;Num< 5;Num++) //计算五日均线 { JxTemp1=JxTemp1+(SPPoint[N+(Num+1)*10]); JxTemp2=JxTemp2+(SPPoint[N+Num*10]); } JX_Five1=JxTemp1/5; JX_Five2=JxTemp2/5; JxTemp1=0; JxTemp2=0; for(int Num=0;Num< 10;Num++) //计算十日均线 { JxTemp1=JxTemp1+(SPPoint[N+(Num+1)*10]); JxTemp2=JxTemp2+(SPPoint[N+Num*10]); } JX_Ten1=JxTemp1/10; JX_Ten2=JxTemp2/10; JxTemp1=0; JxTemp2=0; if(N< 520+Move_Sum) //若位于显示区域内,则绘制K线 { i=i+10; //横座标按10象素递增 g.setColor(Color.white); g.drawLine(i+Left_Start,220-JX_Five1,i+Left_Start+10,220-JX_Five2); g.setColor(Color.yellow); g.drawLine(i+Left_Start,220-JX_Ten1,i+Left_Start+10,220-JX_Ten2); if(KP[N]< =SP[N]) //如果开盘价小于收盘价,则绘制阳线 { //绘制空心矩形 g.setColor(Color.red); g.drawRect(i+Left_Start,reDraw-SPPoint[N],8,(SPPoint[N]-KPPoint[N])); //绘制最高、最低价 if(SPPoint[N]==KPPoint[N]){g.drawRect(i+Left_Start,reDraw-SPPoint[N],8,1);} if(JGPoint[N] >SPPoint[N]){g.drawLine(i+Left_Start+4,reDraw-SPPoint[N], i+Left_Start+4,reDraw-JGPoint[N]);} if(JDPoint[N]< KPPoint[N]){g.drawLine(i+Left_Start+4,reDraw-JDPoint[N], i+Left_Start+4,reDraw-KPPoint[N]);} //在下方对应位置绘制成交量实心矩形 g.fillRect(i+Left_Start,380-(int)CJLPoint[N],8,(int)CJLPoint[N]); } else //如果开盘价大于收盘价,则绘制阴线 { //绘制实心矩形 g.setColor(Color.green); g.fillRect(i+Left_Start,reDraw-KPPoint[N],8,(KPPoint[N])-SPPoint[N]); //绘制最高、最低价 g.drawLine(i+Left_Start+4,reDraw-KPPoint[N],i+Left_Start+4,reDraw-JGPoint[N]); g.drawLine(i+Left_Start+4,reDraw-SPPoint[N],i+Left_Start+4,reDraw-JDPoint[N]); //在下方对应位置绘制成交量实心矩形 g.fillRect(i+Left_Start,380-(int)CJLPoint[N],8,(int)CJLPoint[N]); } if(i >540){N=0;} //如果显示区域已全部绘制完毕,则退出循环 }}}public void ReadData() //读取股票数据的方法{ int piont=1,Piont_Num;Integer tempInteger; Float tempFloat , Content_CJL; Float content_Num[]=new Float[5]; int Count_Number[]=new int[10];String content; try { //定位文件的URL地址 URL urlc=new URL("http://127.0.0.1/temp/"+FileName+".txt"); //打开数据流 BufferedReader bis=new BufferedReader(new InputStreamReader(urlc.openStream())); Name_Str=bis.readLine(); //读取股票的汉字名称 label[1].setText(Name_Str); //在相应标签内显示 while((content=bis.readLine())!=null) //按行读取整个文本文件内容 { Piont_Num=content.indexOf(' ',piont); //查找空格位置 Content_Date=content.substring(1,Piont_Num); //取出日期字符串 myDate[MaxLength]=Content_Date; piont=Piont_Num+1; for(int i=1;i< 5;i++) //从读入的一行中分离出对应数值 { Piont_Num=content.indexOf(' ',piont); content_Num[i]=new Float(content.substring(piont,Piont_Num)); piont=Piont_Num+1; } KP[MaxLength]=(int)(content_Num[1].floatValue()*100); JG[MaxLength]=(int)(content_Num[2].floatValue()*100); JD[MaxLength]=(int)(content_Num[3].floatValue()*100); SP[MaxLength]=(int)(content_Num[4].floatValue()*100); //最后取出成交量的数值 Content_CJL=new Float(content.substring(piont,content.length()-1)); CJL[MaxLength]=(int)Content_CJL.floatValue(); piont=1; Piont_Num=0; MaxLength=MaxLength+10; //读取下一行(记录数以10为单位递增) } MaxWorth=JG[Move_Sum]; MinWorth=JD[Move_Sum]; MaxCJL=CJL[Move_Sum]; //找出在页面布局内的最高、最低值及最大成交量 for(Record_Num=540+Move_Sum;Record_Num >Move_Sum;Record_Num-=10) { if(MaxWorth< JG[Record_Num]){MaxWorth=JG[Record_Num];} if(MinWorth >JD[Record_Num]){MinWorth=JD[Record_Num];} if(MaxCJL< CJL[Record_Num]){MaxCJL=CJL[Record_Num];} } MidCJL=MaxCJL/2; for(int i=1;i< 7;i++) //计算中间值 { Mid_Worth[i]=MinWorth+(MaxWorth-MinWorth)/7*(7-i); } bis.close(); //关闭数据流 repaint(); }catch(NullPointerException npe){ //捕捉可能出现的异常 }catch(IOException e){}}} 调试无法通过,请大家帮助看看,问题出在那里,我也在学习这个程序呢有次经验的请多多赐教,共同学习!QQ:69944558[email protected] 我调试成功代码在ftp://44vv.com/AAA.java 面试题:linux中,如何查看java进程中的线程状态 在frame上添加事件,一定要把所有函数重载吗? java 正则求解,100分 在线急盼!!! 请问如何在一个窗口中调用另一个窗口? 请高手解答。。。 从access中取出时间比较,出错? 我用的VisualCafe不能显示中文,怎么回事呀? 关于hashcode() 100分,江湖救急!!!!关于Applet客户端,和自己创建的服务端传送数据的问题。谁解决谁得分,只给一个人。 一个困惑我的问题,分数少请别介意 如何判断一个字符串的编码方式? OutOfMemoryError应该怎样处理,有高手吗?
[email protected]
[email protected]
[email protected]
谢了!
[email protected]
多谢!
[email protected]
applet股票软件不就是做个服务器建以ServerSocket与
前Socket时实通信,采样用
Java.awt.包或可能的话用Java2D去画点,线晕
[email protected]
[email protected]
dj反编,自己看转---☆ 用Java绘制K线图 ☆
作者:追风 Java语言中的Applet(Java小程序)和Application(Java应用程序)是在结构和功能上都存在很大差异的两种不同的编程方式。Applet应用于Web页上,可做出多姿多彩的页面特效,给网站增辉添色;Application则与其他编程语言(如VB、VC)一样,可编制各种应用程序。
本文要讨论的是第一种情况,在Web页上用Java Applet绘制K线图。
K线是股市行情分析中的一种参数指标,用股票每日的开盘价、最高价、最低价、收盘价及成交量等数据进行作图,配合五日、十日均线便可反映出一个阶段内该支股票的涨跌走势。
Java Applet所做的K线图多应用于证券类型的网站,以方便网上股民的分析操作。不过由于我国网速的关系,目前有些证券类网站把K线图做成了图片以节省下载的时间。当然,其绘制K线所用的工具(Java Applet)及绘制方法还是相同的。
在编写绘制K线的Java Applet时,有几处关键问题要解决,即:1)多线程的使用;2)布局管理器的选择;3)数据输入、输出流的应用;4)设置、监听鼠标与键盘事件。
下面通过一个实例,来详细阐述整个编程过程和方法。《查看演示》
一、使用多线程
一个完整的Java Applet包含四个方法,Init()、Start()、Stop()、Destroy()(即:初始化、开始、停止、清除),构成一个完整的生命周期,其运行次序也是由上而下顺序执行。
在绘制K线图的过程中,除了要绘制窗体及代表股票升降的阴线、阳线矩形外,还要监听鼠标事件并同时绘制一个自由移动的“十字”游标,来定位显示所检索股票每日的各种价格数值(如开盘价、收盘价等);这时,为了避免闪烁和减少重新计算的等待时间,除了重绘跟随鼠标移动的“十字”游标外,对页面的布局及阴线、阳线矩形等不进行重绘;这就需要应用多线程来完成该项任务。
1.关于多线程的一些基本概念:
多线程实际上就是启动另一个进程,其运行的过程独立于主程序之外,并从主程序的Start()方法载入、由Run()方法调用执行。实现多线程的方法有两种,即:创建Thread类的子类(类的继承)和实现runnable接口。
为便于使用,Java把所有有关线程的功能封装成Java类库中的一个类:Java.lang.Thread。通过这个类,Java可以创建、控制和终止线程,完成有关多线程的所有操作。
在Java语言中,一个子类只能继承一个超类(父类),由于我们所要编写的Java Applet是应用于网页中的,首先必须继承浏览器类(java.applet);因此,在本例中我们通过实现runnable接口的方法来实现多线程,实现的语句如下:
public class StockApplet extends java.applet.Applet implements Runnable
2.多线程的应用:
首先,在Init()方法中对要创建的线程(M_pointThread)进行定义及初始化:
Thread M_pointThread=null;
然后,在Start()和Stop()方法中加入以下代码:
//当打开浏览器页面开始载入Java Applet代码时,执行start()方法
public void start()
{
if (M_pointThread==null) //如果线程尚未产生
{
M_pointThread=new Thread(this); //则创建一个新线程
M_pointThread.start(); //启动该线程
}
}
//在当前页面关闭或转向其他Web页面时,
调用stop()方法,以释放系统资源
public void stop()
{
if (M_pointThread!=null) //如果线程尚在运行
{
M_pointThread.stop(); //停止该线程
M_pointThread=null; //释放线程所占资源
}
}
3.编写线程运行的代码:
public void run()
{
M_graphics=getGraphics();
M_graphics.setXORMode(Color.white); //采用异或方法绘制“十字”游标
while(true)
{
try
{
if(MouseMove==true) //侦测到鼠标的移动后,执行以下代码
{ //当鼠标位于以下区域(Java Applet布局)内时,执行画线操作
if(x0 >50 && x0< 600){M_graphics.drawLine(x0,30,x0,380);}
if(y0 >30 && y0 <380){M_graphics.drawLine(50,y0,600,y0);}
if(X >50 && X< 600){M_graphics.drawLine(X,30,X,380);}
if(Y >30 && Y< 380){M_graphics.drawLine(50,Y,600,Y);}
MouseMove=fase;
x0=X; //传递当前座标参数
y0=Y;
}
}
catch(NullPointerException npe){} //捕获可能出现的异常
}
二、布局管理器
本例中的Java Applet运行时,要在页面上Java Applet的运行区域内绘制相应的“标签”来显示不同的数值,并要加入一个“文本框”来接收输入的股票代码。对这些“标签”和“文本框”位置及大小的设定,便属于布局管理的应用范畴。
Java语言中提供的布局管理器种类有:边界式布局、卡片式布局、流式布局和网格式布局等,各有不同的特点,可根据实际需要选用;但有最大自由设计空间的是“无布局管理器”——即不使用任何布局格式,而通过手工方式添加组件到页面布局的绝对位置上。本例中使用的便是“无布局管理器”。
在使用“无布局管理器”时,首先要作出声明,即:
setLayout(null);
然后用reshape()方法指定组件的具体位置和尺寸,
基本语句如下所示:
Label label1=new Label(); //定义标签
this.add(label1); //把标签加入布局管理器
label1.reshape(10,10,30,30); //在指定位置绘制标签
对于多个标签和文本框,参照此格式添加即可。
三、输入、输出数据流
Java Applet在客户端浏览器上运行时,要从服务器端读取股票的相关数据进行做图,这就涉及到Java数据流的运用。
Java.io包提供了多个用于与各种I/O设备交换信息的类,其最顶层的两个类便是输入流类(InputStream)和输出流类(OutputStream)。
为了便于实现,在本例中我们先在服务器端把股票数据库(如:show128.dbf)中的有关字段写入一文本文件中(其格式为:第一行为股票的汉字名称,以后每一行内包括:开盘日期、开盘价、最高价、最低价、收盘价、成交量),并以该支股票的代码作为文件名(如:600001.txt);然后,再用Java Applet从服务器端的文本文件中读取数据。这样,就把对服务器端数据库的访问转化为对文件的I/O操作,实现的语句如下:
URL urlc=new URL("http://127.0.0.1/"+FileName+".txt");
BufferedReader bis=new BufferedReader(new InputStreamReader(urlc.openStream()));
注:第一条语句中的http://127.0.0.1/为在本机执行调试操作的URL地址,在上传到服务器上后要做相应的修改;FileName为要读取的文本文件名。
第二条语句定义了读取输入数据流的方法。
四、监听键盘及鼠标事件
在Java Applet小程序中,单击按钮、键入文本、使用鼠标或执行任何与界面相关的动作时,就发生一个事件,小程序就会作出适当的反应。
在本例中,我们通过使用action()方法来获得Java Applet小程序运行时所发生的事件。语句格式如下:
public boolean action(Event evt,Object arg)
{
FileName=text1.getText(); //提取文本框中输入的参数
ReadData(); //调用读数据流数据的方法
return true; //处理完毕,不需要其他方法再做处理
}
上面的action()方法中含有两个参数:一个是Event类的一个对象evt;另一个是Object类的一个对象arg。Event对象告诉我们发生了哪种事件,而Object对象将进一步告诉我们有关该事件的情况。每当有Event监听的事件发生时,Java Applet便自动调用该action()方法。
至此,在掌握了上述编程中的一些要点后,我们便可以成功地编制出一个完整的绘制K线的Java Applet小程序了(完整的源代码下载)。
五、编制HTML文档(Stock.html)
程序编制完成后,另外要做的是设置在Web页面上调用Java Applet的页面,即编制HTML文档。Stock.html文档的示例代码如下:
<HTML>
< HEAD >
< TITLE >股票K线图< /TITLE >
< /HEAD >
<body bgcolor=#00ffff >
<APPLET code=StockApplet.class name=StockApplet HEIGHT=500 WIDTH=400>
</APPLET >
< /body >
< /HTML >
在< APPLET >< /APPLET >标签对内,是对Java Applet小程序的调用代码。其中的StockApplet.class是经编译后生成的class文件,codeBase指向的是class文件所存放的路径。如果class文件与HTML文档存放在同一目录下,则可以省略这一项。
至此,编制Java Applet小程序的工作便全部完成。
在个人计算机上进行调试时,首先要安装个人Web服务,然后,把StockApplet.class与HTML文档一起拷贝到本机的WWW服务目录下(如:C:\Inetpub\wwwroot\),打开浏览器,在地址栏内输入http://127.0.0.1/Stock.html,回车,进行测试操作。
调试通过后,便可上传至服务器投入运行了。
本人正在尝试做一个个人股票管理系统
import java.awt.*;
import java.io.*;
import java.net.*;
public class StockApplet extends java.applet.Applet implements Runnable
{ //以下是公用变量的声明部分
int Move_Length=0,Move_Sum=0;
String FileName,Name_Str,Content_Date;
int SP[]=new int[2000];
int KP[]=new int[2000];
int JD[]=new int[2000];
int JG[]=new int[2000];
int Mid_Worth[]=new int[2000];
String myDate[]=new String[2000];
double CJL[]=new double[2000];
double MaxCJL,MidCJL;
Label label[]=new Label[10];
int MaxWorth,MinWorth;
int x_move0,x_move1,MaxLength=0;
int x0,y0,X,Y,Record_Num;
boolean Mouse_Move,Name_Change=true;
int JX_Five1,JX_Five2,JX_Ten1,JX_Ten2;
public void init()
{
TextField text1=new TextField();
Thread M_pointThread=null;
setLayout(null); //声明布局管理器
this.setBackground(Color.white); //设置背景色
this.setForeground(Color.black); //设定文字颜色
for(int i=1;i< 10;i++) //以下循环用于向布局中添加标签
{
label[i]=new Label();
this.add(label[i]);
label[i].reshape(i*80-65,10,50,15);
if(i==2){label[i].reshape(80,10,70,15);}
if(i==7){label[i].reshape(510,10,80,15);}
if(i >7){label[i].reshape((i-8)*490+45,380,70,15);}
}
FileName="000001"; //程序启动时的默认股票代码
Name_Str="上证指数";
this.add(text1); //向布局中添加文本框
text1.reshape(150,385,70,20);
text1.getText(); //取得文本框中输入的内容
}
public void start()
{ //创建并启动多线程
if (M_pointThread==null)
{
M_pointThread=new Thread(this);
M_pointThread.start();
}
}
public void run()
{ //运行多线程
Graphics M_graphics;
M_graphics=getGraphics();
M_graphics.setXORMode(Color.white);
while(true) //绘制“十字”游标
{
try
{
if(Mouse_Move==true)
{
if(x0 >50 & x0< 600){M_graphics.drawLine(x0,30,x0,380);}
if(y0 >30 & y0< 380){M_graphics.drawLine(50,y0,600,y0);}
if(X >50 & X< 600){M_graphics.drawLine(X,30,X,380);}
if(Y >30 & Y< 380){M_graphics.drawLine(50,Y,600,Y);}
Mouse_Move=false;
x0=X;
y0=Y;
}
}catch(NullPointerException npe){}
}
}
public boolean action(Event evt,Object arg) //监测事件
{
FileName=text1.getText(); //取得新文件名
repaint();
//将各变量恢复初始状态
Name_Change=true;
Move_Length=0;
Move_Sum=0;
MaxLength=0;
MaxCJL=0;
return true;
}
public boolean keyDown(Event evt,int key) //检测键盘事件
{
if(key==10) //检测是否是回车键
{
Event event=new Event(text1,Event.ACTION_EVENT,"text1");
deliverEvent(event);
return true;
}
return false;
}
public boolean mouseDown(Event evt,int x_d,int y_d) //检测按下鼠标按键事件
{
x_move0=x_d; //记录鼠标当前的横座标
x0=x_d; //把当前座标传递给另一线程
y0=y_d;
return true;
}
{
int Screen=520; //定义在页面上的显示区域
x_move1=x_up; //记录鼠标当前的横座标
Move_Length=((int)(x_move1-x_move0)/10)*10; //计算鼠标移动距离
Move_Sum=Move_Sum+Move_Length;
if(Move_Sum< 0){Move_Sum=0;} //控制K线的拖动范围
if(Move_Sum >MaxLength-Screen){Move_Sum=MaxLength-Screen-10;}
x0=x_up; //把当前座标传递给另一线程
y0=y_up;
MaxWorth=JG[Move_Sum];
MinWorth=JD[Move_Sum];
MaxCJL=CJL[Move_Sum];
//以下循环用于查找页面显示区域内的最高、最低值及成交量
for(int i=Screen+Move_Sum;i >Move_Sum;i-=10)
{
if(MaxWorth< JG[i]){MaxWorth=JG[i];}
if(MinWorth >JD[i]){MinWorth=JD[i];}
if(MaxCJL< CJL[i]){MaxCJL=CJL[i];}
}
MidCJL=MaxCJL/2;
for(int i=1;i< 7;i++) //计算出在纵座标上显示的中间值
{
Mid_Worth[i]=MinWorth+(MaxWorth-MinWorth)/7*(7-i);
}
repaint();
return true;
}
public boolean mouseMove(Event evt,int x_m,int y_m) //检测鼠标移动事件
{
int Axsis,MNumberR;
Mouse_Move=true;
Axsis=560+Move_Sum-((int)(x_m/10))*10; //设定横座标范围
if(Axsis >MaxLength){Axsis=MaxLength;}
//在以下区域内,把鼠标当前横座标处的各种股票参数显示在相应的标签上
if(x_m >50&x_m< 600)
{
label[2].setText(myDate[Axsis]);
label[3].setText(String.valueOf((float)KP[Axsis]/100));
label[4].setText(String.valueOf((float)JG[Axsis]/100));
label[5].setText(String.valueOf((float)JD[Axsis]/100));
label[6].setText(String.valueOf((float)SP[Axsis]/100));
label[7].setText(String.valueOf((int)CJL[Axsis]));
label[8].setText(myDate[510+Move_Sum]);
MNumberR=Move_Sum;
if(Move_Sum >30){MNumberR=Move_Sum-30;}
label[9].setText(myDate[MNumberR]);
X=x_m; //把当前座标传递给另一线程
Y=y_m;
}
return true;
}
public void stop() //当页面关闭或转向其他页面时,释放系统资源
{
if (M_pointThread!=null)
{
M_pointThread.stop();
M_pointThread=null;
}
}
public void paint(Graphics g) //绘图方法
{
if(Name_Change==true) //若改变了查询股票的代码
{
ReadData(); //则重新读取数据
Name_Change=false;
}
PaintFrame(g); //调用绘制页面区域方法
PaintData(g); //调用绘制K线数据方法
x0=-1;
y0=-1;
}
private void PaintFrame(Graphics g) //绘制页面区域方法
{
int nWidth =600;
int nHeight=260;
g.setColor(Color.white);
g.fillRect(0,0,600,420);
g.setColor(Color.black);
g.fillRect(50,30,550,350);
g.setColor(Color.white);
g.drawLine(50,nHeight,nWidth,nHeight); //画出上下两区域间的分隔线
g.setColor(Color.black); //设置字体颜色
for(int i=1;i< 7;i++) //绘出纵座标中间数值
{
g.drawString(String.valueOf((float)Mid_Worth[i]/100),10,55+i*30);
}
g.drawString(String.valueOf((int)MaxCJL),2,270);
g.drawString(String.valueOf((int)MidCJL),8,325);
g.drawString("0",40,380);
}
{
int SPPoint[]=new int[2000];
int KPPoint[]=new int[2000];
int JGPoint[]=new int[2000];
int JDPoint[]=new int[2000];
double CJLPoint[]=new double[2000];
int Left_Start=40,reDraw=250; //设置绘图左边界及参数
int i=0;
int JxTemp1=0,JxTemp2=0;
//以下语句在布局区域内绘出固定信息
g.setColor(Color.red);
g.drawString("牡丹江",5,45);
g.drawString("信息港",5,60);
g.setColor(Color.black);
g.drawString("开盘",150,20);
g.drawString("最高",230,20);
g.drawString("最低",310,20);
g.drawString("收盘",390,20);
g.drawString("成交量",470,20);
g.drawString("要查询其他股票,请输入股票代码,然后回车。",230,400);
for(int N=MaxLength;N >=0;N-=10) //该循环用于在绘图区域内作图
{ //计算股票各参数在绘图区域内要显示的相对值
KPPoint[N]=((KP[N]-MinWorth)*200/(MaxWorth-MinWorth));
SPPoint[N]=((SP[N]-MinWorth)*200/(MaxWorth-MinWorth));
JGPoint[N]=((JG[N]-MinWorth)*200/(MaxWorth-MinWorth));
JDPoint[N]=((JD[N]-MinWorth)*200/(MaxWorth-MinWorth));
CJLPoint[N]=(CJL[N]*120/MaxCJL);
for(int Num=0;Num< 5;Num++) //计算五日均线
{
JxTemp1=JxTemp1+(SPPoint[N+(Num+1)*10]);
JxTemp2=JxTemp2+(SPPoint[N+Num*10]);
}
JX_Five1=JxTemp1/5;
JX_Five2=JxTemp2/5;
JxTemp1=0;
JxTemp2=0;
for(int Num=0;Num< 10;Num++) //计算十日均线
{
JxTemp1=JxTemp1+(SPPoint[N+(Num+1)*10]);
JxTemp2=JxTemp2+(SPPoint[N+Num*10]);
}
JX_Ten1=JxTemp1/10;
JX_Ten2=JxTemp2/10;
JxTemp1=0;
JxTemp2=0;
if(N< 520+Move_Sum) //若位于显示区域内,则绘制K线
{
i=i+10; //横座标按10象素递增
g.setColor(Color.white);
g.drawLine(i+Left_Start,220-JX_Five1,i+Left_Start+10,220-JX_Five2);
g.setColor(Color.yellow);
g.drawLine(i+Left_Start,220-JX_Ten1,i+Left_Start+10,220-JX_Ten2);
if(KP[N]< =SP[N]) //如果开盘价小于收盘价,则绘制阳线
{ //绘制空心矩形
g.setColor(Color.red);
g.drawRect(i+Left_Start,reDraw-SPPoint[N],8,(SPPoint[N]-KPPoint[N]));
//绘制最高、最低价
if(SPPoint[N]==KPPoint[N]){g.drawRect(i+Left_Start,reDraw-SPPoint[N],8,1);}
if(JGPoint[N] >SPPoint[N]){g.drawLine(i+Left_Start+4,reDraw-SPPoint[N], i+Left_Start+4,reDraw-JGPoint[N]);}
if(JDPoint[N]< KPPoint[N]){g.drawLine(i+Left_Start+4,reDraw-JDPoint[N], i+Left_Start+4,reDraw-KPPoint[N]);}
//在下方对应位置绘制成交量实心矩形
g.fillRect(i+Left_Start,380-(int)CJLPoint[N],8,(int)CJLPoint[N]);
}
else //如果开盘价大于收盘价,则绘制阴线
{ //绘制实心矩形
g.setColor(Color.green);
g.fillRect(i+Left_Start,reDraw-KPPoint[N],8,(KPPoint[N])-SPPoint[N]);
//绘制最高、最低价
g.drawLine(i+Left_Start+4,reDraw-KPPoint[N],i+Left_Start+4,reDraw-JGPoint[N]);
g.drawLine(i+Left_Start+4,reDraw-SPPoint[N],i+Left_Start+4,reDraw-JDPoint[N]);
//在下方对应位置绘制成交量实心矩形
g.fillRect(i+Left_Start,380-(int)CJLPoint[N],8,(int)CJLPoint[N]);
}
if(i >540){N=0;} //如果显示区域已全部绘制完毕,则退出循环
}
}
}
public void ReadData() //读取股票数据的方法
{
int piont=1,Piont_Num;
Integer tempInteger;
Float tempFloat , Content_CJL;
Float content_Num[]=new Float[5];
int Count_Number[]=new int[10];
String content;
try
{ //定位文件的URL地址
URL urlc=new URL("http://127.0.0.1/temp/"+FileName+".txt");
//打开数据流
BufferedReader bis=new BufferedReader(new InputStreamReader(urlc.openStream()));
Name_Str=bis.readLine(); //读取股票的汉字名称
label[1].setText(Name_Str); //在相应标签内显示
while((content=bis.readLine())!=null) //按行读取整个文本文件内容
{
Piont_Num=content.indexOf(' ',piont); //查找空格位置
Content_Date=content.substring(1,Piont_Num); //取出日期字符串
myDate[MaxLength]=Content_Date;
piont=Piont_Num+1;
for(int i=1;i< 5;i++) //从读入的一行中分离出对应数值
{
Piont_Num=content.indexOf(' ',piont);
content_Num[i]=new Float(content.substring(piont,Piont_Num));
piont=Piont_Num+1;
}
KP[MaxLength]=(int)(content_Num[1].floatValue()*100);
JG[MaxLength]=(int)(content_Num[2].floatValue()*100);
JD[MaxLength]=(int)(content_Num[3].floatValue()*100);
SP[MaxLength]=(int)(content_Num[4].floatValue()*100);
//最后取出成交量的数值
Content_CJL=new Float(content.substring(piont,content.length()-1));
CJL[MaxLength]=(int)Content_CJL.floatValue();
piont=1;
Piont_Num=0;
MaxLength=MaxLength+10; //读取下一行(记录数以10为单位递增)
}
MaxWorth=JG[Move_Sum];
MinWorth=JD[Move_Sum];
MaxCJL=CJL[Move_Sum];
//找出在页面布局内的最高、最低值及最大成交量
for(Record_Num=540+Move_Sum;Record_Num >Move_Sum;Record_Num-=10)
{
if(MaxWorth< JG[Record_Num]){MaxWorth=JG[Record_Num];}
if(MinWorth >JD[Record_Num]){MinWorth=JD[Record_Num];}
if(MaxCJL< CJL[Record_Num]){MaxCJL=CJL[Record_Num];}
}
MidCJL=MaxCJL/2;
for(int i=1;i< 7;i++) //计算中间值
{
Mid_Worth[i]=MinWorth+(MaxWorth-MinWorth)/7*(7-i);
}
bis.close(); //关闭数据流
repaint();
}catch(NullPointerException npe){ //捕捉可能出现的异常
}catch(IOException e){}
}
}
有次经验的请多多赐教,共同学习!QQ:69944558
[email protected]
代码在ftp://44vv.com/AAA.java