i want show values of series @ current mouse position if cursor on chart. displayed in figure:
to accomplish behavior used tannotationtool
, onmousemove
event. additionally use tcursortool
style := cssvertical
, followmouse := true
draw vertical line @ current mouve position. unfortunately solution slow. if series count greater 10 user observe annotation run after mouse lag of 500ms. during investigation of issue, found out part of mousemoveevent bottleneck:
chtmain : tchart; fvalanno : tannotationtool; ... tfrmmain.chtmainmousemove(sender: tobject; shift: tshiftstate; x, y: integer) var hasdata : boolean; annolst : tstrings; begin ... if hasdata self.fvalanno.text := annolst.text else self.fvalanno.text := 'no data'; // if (x < self.chtmain.width - self.fvalanno.width - 5) self.fvalanno.shape.left := x + 10 else self.fvalanno.shape.left := x - self.fvalanno.width - 15; // if (y < self.chtmain.height - self.fvalanno.height - 5) self.fvalanno.shape.top := y + 10 else self.fvalanno.shape.top := y - self.fvalanno.height - 15; // if (fx >= self.chtmain.bottomaxis.istartpos) , (fx <= self.chtmain.bottomaxis.iendpos) , (fy >= self.chtmain.leftaxis.istartpos) , (fy <= self.chtmain.leftaxis.iendpos) self.fvalanno.active := true else self.fvalanno.active := false; ... end;
if use code above vertical line , annotation run after cursor 500ms @ series count of 100. lag increases higher series count is. on other hand if not use annotation code vertical line run after lag of 100ms.
is there other tool accomplish benaviour faster tchart components? or there properties can play make faster?
thanks in advance support!
edit: example code reproduce issue
- create new vcl project
- drop tchart component , checkbox on form
- create formcreate form , mousemoveevent chart
- switch code view insert following code:
code:
unit unit1; interface uses winapi.windows, winapi.messages, system.sysutils, system.variants, system.classes, vcl.graphics, vcl.controls, vcl.forms, vcl.dialogs, vcltee.teegdiplus, vcltee.teengine, vcl.extctrls, vcltee.teeprocs, vcltee.chart, vcltee.teetools, vcl.stdctrls; type tform1 = class(tform) chtmain: tchart; chkanno: tcheckbox; procedure formcreate(sender: tobject); procedure chtmainmousemove(sender: tobject; shift: tshiftstate; x, y: integer); private fcursor : tcursortool; fanno : tannotationtool; public { public-deklarationen } end; var form1: tform1; implementation {$r *.dfm} uses vcltee.series, system.dateutils; const arr_maxs : array[0..3] of double = (12.5, 25.8, 2.8, 56.7); procedure tform1.chtmainmousemove(sender: tobject; shift: tshiftstate; x, y: integer); function getxvalueindex(const aserie: tchartseries; const ax: double): integer; var index: integer; begin index := 0 aserie.xvalues.count - 1 begin if aserie.xvalue[index] >= ax break; end; // result := index - 1; end; var idx, : integer; cursorx, cursory, value : double; serie : tchartseries; legendtxt : string; annolst : tstrings; hasdata : boolean; showndate : tdatetime; begin // if not self.chkanno.checked begin // fanno.text := format('position:'#13#10' x: %d'#13#10' y: %d', [x, y]); end else begin // if (self.chtmain.seriescount < 1) begin // if assigned(self.fanno) self.fanno.active := false; exit; end; // self.chtmain.series[0].getcursorvalues(cursorx, cursory); // annolst := tstringlist.create; try // showndate := 0; hasdata := false; := 0 self.chtmain.seriescount - 1 begin // serie := self.chtmain.series[i]; // idx := getxvalueindex(serie, cursorx); if serie.xvalue[idx] > showndate begin // legendtxt := datetimetostr(serie.xvalue[idx]); if (annolst.count > 0) , (showndate > 0) annolst[0] := legendtxt else if annolst.count > 0 annolst.insert(0, legendtxt) else annolst.add(legendtxt); hasdata := true; showndate := serie.xvalue[idx]; end; // legendtxt := format('serie: %d', [i]); if length(legendtxt) <= 25 legendtxt := format('%-25s', [legendtxt]) else legendtxt := format('%s...', [legendtxt.substring(0, 22)]); // value := serie.yvalue[idx] * abs(arr_maxs[i]); legendtxt := format('%s: %3.3f %s', [legendtxt, value, 'none']); annolst.add(legendtxt); end; fanno.text := annolst.text; freeandnil(annolst); end; end; if (x < self.chtmain.width - self.fanno.width - 5) self.fanno.shape.left := x + 10 else self.fanno.shape.left := x - self.fanno.width - 15; // if (y < self.chtmain.height - self.fanno.height - 5) self.fanno.shape.top := y + 10 else self.fanno.shape.top := y - self.fanno.height - 15; // if (x >= self.chtmain.bottomaxis.istartpos) , (x <= self.chtmain.bottomaxis.iendpos) , (y >= self.chtmain.leftaxis.istartpos) , (y <= self.chtmain.leftaxis.iendpos) self.fanno.active := true else self.fanno.active := false; end; procedure tform1.formcreate(sender: tobject); var idx, j : integer; serie : tfastlineseries; start : tdatetime; value : double; begin // self.chtmain.view3d := false; self.chtmain.align := alclient; self.chtmain.backcolor := clwhite; self.chtmain.color := clwhite; self.chtmain.gradient.visible := false; self.chtmain.legend.legendstyle := lsseries; self.chtmain.zoom.allow := false; self.chtmain.allowpanning := pmnone; self.chtmain.backwall.color := clwhite; self.chtmain.backwall.gradient.visible := false; self.chtmain.leftaxis.automatic := false; self.chtmain.leftaxis.minimum := 0; self.chtmain.leftaxis.maximum := 2; self.chtmain.leftaxis.increment := 0.1; self.chtmain.leftaxis.visible := true; self.chtmain.leftaxis.axisvaluesformat := '#,##0.## lv'; // self.chtmain.bottomaxis.datetimeformat := 'dd.mm.yyyy hh:mm:ss'; self.chtmain.bottomaxis.increment := 1 / 6; self.chtmain.bottomaxis.automatic := true; self.chtmain.bottomaxis.labelssize := 32; self.chtmain.bottomaxis.labelsmultiline := true; self.chtmain.marginbottom := 6; self.chtmain.bottomaxis.title.caption := 'date'; self.chtmain.bottomaxis.visible := false; fanno := self.chtmain.tools.add(tannotationtool) tannotationtool; fanno.active := false; fanno.shape.customposition := true; fcursor := self.chtmain.tools.add(tcursortool) tcursortool; fcursor.followmouse := true; fcursor.style := cssvertical; randomize; start := now; idx := 0 3 begin // serie := self.chtmain.addseries(tfastlineseries) tfastlineseries; serie.fastpen := true; serie.showinlegend := false; serie.xvalues.datetime := true; serie.vertaxis := aleftaxis; serie.parentchart := self.chtmain; j := 1 1000 begin // value := random * arr_maxs[idx] * 1.8; serie.addxy(incsecond(start, j), value / arr_maxs[idx]); end; end; end; end.
- press [f9]
i not observe difference, whether use position annotation code or other one.
the tcursortool
has fullrepaint
property (false
default) draw using xor full chart doesn't need repainted everytime updates position. , fast.
however, tannotationtool
doesn't include possibility so, when update fannot text or position, forcing chart repaint, , having many points makes process slower.
you use tlabel
component instead of using tannotationtool
draw text.