在新系列可见后,Canvas.textout不显示文本

时间:2015-05-20 12:53:56

标签: delphi teechart

所以我正在做的是在onmousemove事件中使用以下代码在teechart图表上显示鼠标指针的x和y值:

oscilografia.Repaint;

if ((x>236) and (x<927)) and ((y>42) and (y<424)) then
begin
  oscilografia.Canvas.Brush.Style := bsSolid;
  oscilografia.Canvas.Pen.Color := clBlack;
  oscilografia.Canvas.Brush.Color := clWhite;
  oscilografia.Canvas.TextOut(x+10,y,datetimetostr(oscilografia.Series[0].XScreenToValue(x))+','+FormatFloat('#0.00',oscilografia.series[0].YScreenToValue(y)));
  edit1.Text:=inttostr(x)+'  '+inttostr(y);
end;

代码工作正常,但是当我通过在图例上选择它来使另一个系列可见时会出现问题:canvas.textout创建的框内的文本不再显示。

鼠标后框仍然存在,但没有任何文字。所以我想解决这个问题。

2 个答案:

答案 0 :(得分:6)

基本问题在于绘画是如何运作的。 Windows没有持久的绘图表面。在下次系统需要重新绘制时,您在窗口上绘制的内容将被覆盖。

您需要安排所有绘画都响应WM_PAINT消息。在Delphi术语中,通常意味着您将绘制代码放在一个被覆盖的Paint方法中。

所以基本过程是这样的:

  1. 导出图表控件的子类,并在该类中覆盖Paint。调用继承的Paint方法,然后执行代码以显示所需的文本。
  2. OnMouseMove事件处理程序中,如果您检测到需要更新鼠标坐标文本,请在图表上调用Invalidate
  3. Invalidate的调用会将该窗口标记为脏,当下一个绘制周期发生时,Paint中的代码将被执行。
  4. 更重要的是,当出现任何其他强制绘画周期的情况时,例如对图表的其他修改,您的绘画代码将再次执行。
  5. 注意,作为子类的替代方法,您可以使用TChart事件OnAfterDraw。但我不是TChart的专家,所以我不确定。主要观点如上所述。

答案 1 :(得分:1)

a comment you wrote开始,我看到你跟着this example 请注意,它不会绘制任何矩形;它只绘制文字,所以我不确定你的鼠标是什么盒子 另请注意,示例调用InvalidateDavid Heffernan中建议的his answer。 在下面找到相同示例的修改版本,在文本之前绘制一个矩形。

procedure TForm1.FormCreate(Sender: TObject);
begin
    Series1.FillSampleValues(10);
    Chart1.View3D := False;
end;

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var tmpL,tmpL2,ClickedValue : Integer;
    tmpWidth, tmpHeight: Integer;
    tmpText: string;
begin
    clickedvalue := -1;
    tmpL2:= -1;

    With Chart1 do
    begin
        If (Series1.Clicked(X, Y) <> -1) And (not OnSeriesPoint) Then
        begin
            Canvas.Brush.Style := bsSolid;
            Canvas.Pen.Color := clBlack;
            Canvas.Brush.Color := clWhite;
            tmpText:=FormatFloat('#.00',Series1.XScreenToValue(x))+','+FormatFloat('#.00',Series1.YScreenToValue(y));
            tmpWidth:=Canvas.TextWidth(tmpText)+10;
            tmpHeight:=Canvas.TextHeight(tmpText);
            Canvas.Rectangle(x+5, y, x+tmpWidth, y+tmpHeight);
            Canvas.TextOut(x+10,y,tmpText);
            OnSeriesPoint := True;
            ClickedValue:= Series1.Clicked(x,y);
        End;

        //Repaint Chart to clear Textoutputted Mark
        If (ClickedValue=-1) And (OnSeriesPoint) Then
        begin
            OnSeriesPoint := False;
            Invalidate;
        End;

        tmpL := Chart1.Legend.Clicked(X, Y);

        If (tmpL <> -1) And ((tmpL <> tmpL2) Or (not OnLegendPoint)) Then
        begin
            repaint;
            Canvas.Brush.Color := Series1.LegendItemColor(tmpL);
            Canvas.Rectangle( X, Y, X + 20, Y + 20);
            Canvas.Brush.Color := clWhite;
            Canvas.TextOut(x+15,y+7,FormatFloat('#.00',Series1.XValues.Items[Series1.LegendToValueIndex(tmpl)]));
            tmpL2 := tmpL;
            OnLegendPoint := True;
        End;

        If (tmpL2 = -1) And (OnLegendPoint) Then
        begin
            OnLegendPoint := False;
            Invalidate;
        End;
    End;
End;