合二为一测试,并加上了向左向右箭头移动
把之前的K线Q柱测试程序和十字光标测试程序,再加上向左向右移动,Home键到头,End键到尾,这些功能合并在一起测试了一下。雏形差不多了。
要优化改进的地方估计就是类的划分了,这个测试程序只是验证功能性的。
类的划分以及可重用性没考虑。最好是都定义成各种对象,如K线对象,Q柱对象,十字光标对象,网格对象,等等,这样便于扩展修改。。。
还有向左回溯,向右回溯,向上放大,向下缩小等功能还没实现。。。
#!/usr/bin/env python
# -*- coding:gb2312 -*-
from tkinter import *
import re
class QZ: # 量柱
def __init__(self, kxt, color):
self.kxt = kxt
self.cvs = kxt.cvs
self.color = color
self.qz = None # Q柱
def create_qz(self, td, qty):
self.td = td
tmp, y0 = self.kxt.zxj2zsj(td, 0)
tmp, self.qz = self.kxt.zxj2zsj(td, qty)
if qty > 0:
self.qz = self.cvs.create_line(self.td, y0, self.td, self.qz, fill=self.color, width=9)
else:
tmp,y1 = self.kxt.zxj2zsj(td, 1)
self.qz = self.cvs.create_line(self.td, y0, self.td, y1, fill=self.color, width=9)
class KX: # K线
def __init__(self, kxt):
self.kxt = kxt
self.cvs = kxt.cvs
self.kx = None # K线
self.kz = None # K柱
def create_kx(self, td,jk,js,zg,zd):
self.td = td
tmp, self.jk = self.kxt.zxj2zsj(td, jk)
tmp, self.js = self.kxt.zxj2zsj(td, js)
tmp, self.zg = self.kxt.zxj2zsj(td, zg)
tmp, self.zd = self.kxt.zxj2zsj(td, zd)
if js > jk:
color = 'red'
elif js < jk:
color = 'green'
else:
color = 'gray'
self.color = color
if zg>zd:
self.kx = self.cvs.create_line(self.td, self.zd, self.td, self.zg, fill=color, width=1)
elif zg==zd:
tx,ty = self.kxt.zxj2zsj(td, zg+1)
self.kx = self.cvs.create_line(self.td, self.zd, self.td, ty, fill=color, width=1)
else:
pass
if js!=jk:
self.kz = self.cvs.create_line(self.td, self.jk, self.td, self.js, fill=color, width=9)
else:
tx,ty = self.kxt.zxj2zsj(td, js+1)
self.kz = self.cvs.create_line(self.td, self.jk, self.td, ty, fill=color, width=9)
class KXT: # K线图
def __init__(self, root, width=800, height=600):
self.root = root
self.cvs = Canvas(self.root, width=width, height=height, bg='black', cursor='crosshair')
self.cvs.pack(fill=BOTH, expand=1)
self.root.resizable(0,0)
self.width = width
self.height = height
self.ox = 0
self.oy = self.height-1
self.x_min = 0
self.x_max = self.width-1
self.y_min = 0
self.y_max = self.height-1
self.kx_kd = 9 # K线宽度
self.kx_jj = 13 # K线间距
self.kx_max = int(self.width/self.kx_jj-1)
self.kx_list = []
self.qz_list = []
self.kx_offset = 0
self.kx_count = 30
self.kx_data = []
self.root.bind('<Enter>', self.do_Enter)
self.root.bind('<Leave>', self.do_Leave)
self.root.bind('<Motion>', self.do_Enter)
self.cur_xx = None
self.cur_yy = None
self.cur_txt = None
self.last_x = None
self.root.bind('<Left>', self.do_Left)
self.root.bind('<Right>', self.do_Right)
self.root.bind('<Home>', self.do_Home)
self.root.bind('<End>', self.do_End)
def do_Home(self, event):
if self.last_x is None: return
self.last_x = 10
newx = self.last_x
self.cvs.coords(self.cur_yy, newx, self.y_min, newx, self.y_max)
self.cvs.coords(self.cur_txt, newx, event.y)
self.cvs.itemconfig(self.cur_txt, text='X%d,Y%d' % (newx,event.y) )
def do_End(self, event):
if self.last_x is None: return
self.last_x = self.kx_max*self.kx_jj+10
newx = self.last_x
self.cvs.coords(self.cur_yy, newx, self.y_min, newx, self.y_max)
self.cvs.coords(self.cur_txt, newx, event.y)
self.cvs.itemconfig(self.cur_txt, text='X%d,Y%d' % (newx,event.y) )
def do_Left(self, event):
if self.last_x is None: return
self.last_x -= self.kx_jj
if self.last_x < self.x_min: self.last_x = 10
newx = self.last_x
self.cvs.coords(self.cur_yy, newx, self.y_min, newx, self.y_max)
self.cvs.coords(self.cur_txt, newx, event.y)
self.cvs.itemconfig(self.cur_txt, text='X%d,Y%d' % (newx,event.y) )
def do_Right(self, event):
if self.last_x is None: return
self.last_x += self.kx_jj
if self.last_x > self.x_max: self.last_x = self.kx_max*self.kx_jj+10
newx = self.last_x
self.cvs.coords(self.cur_yy, newx, self.y_min, newx, self.y_max)
self.cvs.coords(self.cur_txt, newx, event.y)
self.cvs.itemconfig(self.cur_txt, text='X%d,Y%d' % (newx,event.y) )
def do_Enter(self, event):
idx = (event.x-10)//self.kx_jj
newx = 10+idx*self.kx_jj
self.last_x = newx
if self.cur_xx is None:
self.cur_xx = self.cvs.create_line(self.x_min, event.y, self.x_max, event.y, fill='green')
else:
self.cvs.coords(self.cur_xx, self.x_min, event.y, self.x_max, event.y)
if self.cur_yy is None:
self.cur_yy = self.cvs.create_line(newx, self.y_min, newx, self.y_max, fill='green')
else:
self.cvs.coords(self.cur_yy, newx, self.y_min, newx, self.y_max)
if self.cur_txt is None:
self.cur_txt = self.cvs.create_text(newx, event.y, anchor=SW, text='X%d,Y%d' % (newx,event.y), fill='green')
else:
self.cvs.coords(self.cur_txt, newx, event.y)
self.cvs.itemconfig(self.cur_txt, text='X%d,Y%d' % (newx,event.y) )
def do_Leave(self, event):
self.last_x = None
if self.cur_xx is not None:
self.cvs.delete(self.cur_xx)
self.cur_xx = None
if self.cur_yy is not None:
self.cvs.delete(self.cur_yy)
self.cur_yy = None
if self.cur_txt is not None:
self.cvs.delete(self.cur_txt)
self.cur_txt = None
def clearall(self):
self.cvs.delete(ALL)
self.kx_data = []
self.kx_list = []
def setdata(self, data):
self.kx_data = data
def setprate(self, maxy, maxprice):
self.rate = maxy/maxprice
def p2y(self, price):
return int(self.rate*price)
def setqrate(self, maxy, maxqty):
self.qrate = maxy/maxqty
def q2y(self, qty):
return int(self.qrate*qty)
def drawall(self):
kd = self.kx_data
n = len(kd)
if n > self.kx_max: n=self.kx_max
for i in range(n):
k = KX(self)
k.create_kx(10+i*self.kx_jj, self.p2y(kd[i][1]), self.p2y(kd[i][2]), self.p2y(kd[i][3]), self.p2y(kd[i][4]) )
self.kx_list.append(k)
q = QZ(self, k.color)
q.create_qz(10+i*self.kx_jj, self.q2y(kd[i][5]) )
self.qz_list.append(q)
def zsj2zxj(self, zsj_px, zsj_py): # 左上角坐标系点的坐标转化成左下角坐标系点的坐标
px, py = zsj_px, self.height-1-zsj_py
return px,py
def zxj2zsj(self, zxj_px, zxj_py): # 左下角坐标系点的坐标转化成左上角坐标系点的坐标
px, py = zxj_px, self.height-1-zxj_py
return px,py
def getdata():
"""
171221 8.16 8.20 8.26 8.15 10763
171222 8.20 8.19 8.31 8.16 9672
171225 8.16 8.19 8.22 8.13 11088
"""
f=open('kx2.txt', 'r')
s=f.read()
f.close()
ss = re.findall(r'\d{6} [\d\.]+ [\d\.]+ [\d\.]+ [\d\.]+ [\d]+',s)
ds=[]
for s in ss:
tmp=[]
ts=s.split(' ')
tmp.append(ts[0])
for i in range(1,6):
tmp.append( float(ts[i]) )
ds.append(tmp)
return ds
class App:
def __init__(self):
ds = getdata()
self.root = Tk()
self.root.title('K线Q柱测试...')
self.mykx = KXT(self.root, 600, 300)
self.mykx.setdata(ds)
self.mykx.setprate(300, 9.00)
self.mykx.setqrate(50, 100000.00)
self.mykx.drawall()
def Run(self):
self.root.mainloop()
###################################################
app = App()
app.Run()