線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5079
推到 Plurk!
推到 Facebook!

關於Tchart滑鼠座標取得

答題得分者是:st33chen
windheartalan
一般會員


發表:21
回覆:23
積分:8
註冊:2005-03-24

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-12-11 09:55:20 IP:61.219.xxx.xxx 訂閱
各位先進,又有問題想請教各位,
現在已知在MouseMove可以取得滑鼠座標x,y(非指座標軸之x,y),

問題來了,假設chart中有一條線(series),我想要知道,
我依照目前滑鼠所點的位置劃一直線,與該條線相交那個點的座標(視窗座標,非chart座標軸),
該如何得知呢?

因為滑鼠的位置,並不一定會落在線上,
所以這麼做是希望,可以透過滑鼠的移動,自動畫直線對應到該數列線上,
現在畫直線是ok,該數列的x,y座標值也可取得,
我想進一步於該數列x,y座標軸出畫出橫線,即針對直線與數列交會點處劃橫線,使得數列上該點呈現十字狀.
但這是需要知道該點視窗座標位置的,

想請問各位先進,有無什麼method,可以取得視窗座標值,或是說有什麼其他的做法可以指教,感恩.

st33chen
尊榮會員


發表:15
回覆:591
積分:1201
註冊:2005-09-30

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-12-11 17:26:23 IP:122.116.xxx.xxx 未訂閱
您好,
chart 元件的 mouseover 事件的 x, y 不就是您所要的嗎?
(若要得到 form 的 mouse 座標, 分別加 chart 元件的 left, top)
不知是否切題 ?
------
IS IT WHAT IT IS
我是 李慕白 請倒著唸.
又想把老話拿出來說, 請用台語發音 : 專家專家全是ROBOT CAR (滷肉腳啦);
都已接手這麼久了, 績效還是那麼爛, 講話還那麼大聲.
windheartalan
一般會員


發表:21
回覆:23
積分:8
註冊:2005-03-24

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-12-11 17:37:37 IP:219.84.xxx.xxx 訂閱

感謝st33chen 大大的回覆,我知道mouseover 事件可取得 x, y,但這只是A點,
A點未必會落在series的線上,所以我是要根據x座標畫直線之後,取得該直線與series曲線交會的B點座標,
B點的x,y座標軸值我知道,但無法取得B點視窗的座標位置(x座標一樣,但y座標不同)

目的是在取得B的Y座標後,劃一橫線,在B點處形成十字線的展現,
不知這樣敘述,能否了解我的問題所在,再煩請指導,感恩.

===================引 用 st33chen 文 章===================
您好,
chart 元件的 mouseover 事件的 x, y 不就是您所要的嗎?
(若要得到 form 的 mouse 座標, 分別加 chart 元件的 left, top)
不知是否切題 ?
st33chen
尊榮會員


發表:15
回覆:591
積分:1201
註冊:2005-09-30

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-12-11 18:37:04 IP:122.116.xxx.xxx 未訂閱
了解了,
很有趣的問題, 我再想想或找找

不過, 現在想到的是笨方法 :

由 mouse 的 x 值可以換算出該點是落在哪兩個數點的中間
再用中學所教的一個線段已知 x 求線段上 y 值的方法算出來
(忘了是不是叫作 插補法 差補法)

============================================
找到一個嫌疑犯 :
chart1.Series[0].CalcYPosvalue( mouse x 值換成 line 的 x 值);
對不起, 好像也不是
==============================================
您可以在 editing chart 的左下角的 help 中找到 Calculating Co-ordinates 這一段
好像答案在裏面
==================================================
終於測好答案了 : 終究還是要用 已知 x 求線段上 y 值的方法 :

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TeEngine, Series, StdCtrls, ExtCtrls, TeeProcs, Chart;
type
TForm1 = class(TForm)
Chart1: TChart;
Button1: TButton;
Series1: TLineSeries;
Label1: TLabel;
Label2: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label3: TLabel;
Label4: TLabel;
Label10: TLabel;
Label11: TLabel;
procedure Button1Click(Sender: TObject);
procedure Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
chartx, charty : integer;
x0, x2, y0, y2 : double;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
chart1.Series[0].AddXY(10,10);
chart1.Series[0].AddXY(20,40);
chart1.Series[0].AddXY(30,20);
chart1.Series[0].AddXY(40,10);
chart1.Series[0].AddXY(50,40);
chart1.Series[0].AddXY(60,20);
chart1.Refresh;
x0 := chart1.Series[0].MinXValue;
x2 := chart1.Series[0].maxxvalue;
y0 := chart1.Series[0].MinYValue;
y2 := chart1.Series[0].MaxYValue;
end;
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var xval, yval, yval2, yval3 : real;
ii : integer;
begin
label1.Caption := inttostr(x);
label2.Caption := inttostr(y);
if x2 < > x0 then begin
xval := chart1.Series[0].xScreenToValue(x);
for ii:=1 to chart1.Series[0].Count-1 do begin
if xval < c h a r t 1 . S e r i e s [ 0 ] . x V a l u e [ i i ] t h e n b e g i n
x0 := chart1.Series[0].XValue[ii-1];
x2 := chart1.Series[0].XValue[ii];
y0 := chart1.Series[0].yValue[ii-1];
y2 := chart1.Series[0].yValue[ii];
if y2>y0 then
yval := (xval-x0)/(x2-x0)*(y2-y0) y0
else begin
yval := (x2-xval)/(x2-x0)*(y0-y2) y2;
end;
break;
end;
end;
// mouse 所在的 圖的 x 值
label5.caption := floattostr(xval);
// 由 xval 算出來的 線上 的 y 值
label6.Caption := floattostr(yval);
// mouse 在 圖中的 y 值, 如果把 mouse 移到線上, 值應和 label6 非常接近
label8.caption := floattostr(chart1.Series[0].yScreenToValue(y));
// 答案
label7.Caption := floattostr(chart1.Series[0].CalcYSizeValue(yval));
end;
end;
end.
------
IS IT WHAT IT IS
我是 李慕白 請倒著唸.
又想把老話拿出來說, 請用台語發音 : 專家專家全是ROBOT CAR (滷肉腳啦);
都已接手這麼久了, 績效還是那麼爛, 講話還那麼大聲.
編輯記錄
st33chen 重新編輯於 2008-12-11 18:42:58, 註解 無‧
st33chen 重新編輯於 2008-12-11 18:46:04, 註解 無‧
st33chen 重新編輯於 2008-12-11 18:56:31, 註解 無‧
st33chen 重新編輯於 2008-12-11 23:27:08, 註解 無‧
st33chen 重新編輯於 2008-12-11 23:28:14, 註解 無‧
st33chen 重新編輯於 2008-12-11 23:29:49, 註解 無‧
st33chen 重新編輯於 2008-12-11 23:32:21, 註解 無‧
st33chen 重新編輯於 2008-12-11 23:34:53, 註解 無‧
windheartalan
一般會員


發表:21
回覆:23
積分:8
註冊:2005-03-24

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-12-12 08:46:38 IP:219.84.xxx.xxx 訂閱
十分感謝您~ 相當的用心回覆,
的確,大大所說的兩種方法都可以,
CalcYPosvalue也是可以的,他是把value轉換成座標的樣子,

我昨天後來有從tchart的範例程式其中一個form找到一些方向,
再加上大大所說,測試後,兩種方法都可以達到我要的效果,再次謝謝您~


===================引 用 st33chen 文 章===================
了解了,
很有趣的問題, 我再想想或找找

不過, 現在想到的是笨方法 :

由 mouse 的 x 值可以換算出該點是落在哪兩個數點的中間
再用中學所教的一個線段已知 x 求線段上 y 值的方法算出來
(忘了是不是叫作 插補法 差補法)

============================================
找到一個嫌疑犯 :
chart1.Series[0].CalcYPosvalue( mouse x 值換成 line 的 x 值);
對不起, 好像也不是
==============================================
您可以在 editing chart 的左下角的 help 中找到 Calculating Co-ordinates 這一段
好像答案在裏面
==================================================
終於測好答案了 : 終究還是要用 已知 x 求線段上 y 值的方法 :

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TeEngine, Series, StdCtrls, ExtCtrls, TeeProcs, Chart;
type
TForm1 = class(TForm)
Chart1: TChart;
Button1: TButton;
Series1: TLineSeries;
Label1: TLabel;
Label2: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label3: TLabel;
Label4: TLabel;
Label10: TLabel;
Label11: TLabel;
procedure Button1Click(Sender: TObject);
procedure Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
chartx, charty : integer;
x0, x2, y0, y2 : double;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
chart1.Series[0].AddXY(10,10);
chart1.Series[0].AddXY(20,40);
chart1.Series[0].AddXY(30,20);
chart1.Series[0].AddXY(40,10);
chart1.Series[0].AddXY(50,40);
chart1.Series[0].AddXY(60,20);
chart1.Refresh;
x0 := chart1.Series[0].MinXValue;
x2 := chart1.Series[0].maxxvalue;
y0 := chart1.Series[0].MinYValue;
y2 := chart1.Series[0].MaxYValue;
end;
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var xval, yval, yval2, yval3 : real;
ii : integer;
begin
label1.Caption := inttostr(x);
label2.Caption := inttostr(y);
if x2 < > x0 then begin
xval := chart1.Series[0].xScreenToValue(x);
for ii:=1 to chart1.Series[0].Count-1 do begin
if xval < c h a r t 1 . S e r i e s [ 0 ] . x V a l u e [ i i ] t h e n b e g i n
x0 := chart1.Series[0].XValue[ii-1];
x2 := chart1.Series[0].XValue[ii];
y0 := chart1.Series[0].yValue[ii-1];
y2 := chart1.Series[0].yValue[ii];
if y2>y0 then
yval := (xval-x0)/(x2-x0)*(y2-y0) y0
else begin
yval := (x2-xval)/(x2-x0)*(y0-y2) y2;
end;
break;
end;
end;
// mouse 所在的 圖的 x 值
label5.caption := floattostr(xval);
// 由 xval 算出來的 線上 的 y 值
label6.Caption := floattostr(yval);
// mouse 在 圖中的 y 值, 如果把 mouse 移到線上, 值應和 label6 非常接近
label8.caption := floattostr(chart1.Series[0].yScreenToValue(y));
// 答案
label7.Caption := floattostr(chart1.Series[0].CalcYSizeValue(yval));
end;
end;
end.
st33chen
尊榮會員


發表:15
回覆:591
積分:1201
註冊:2005-09-30

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-12-12 12:18:00 IP:118.168.xxx.xxx 未訂閱
可以 show 一下 大大您的作法 嗎?
謝謝

我另一個想法是
固定 x, 用一個 loop 去改變 y 直到 碰壁 或 點的顏色等於線的顏色
這樣就不必套公式去算
不過後來沒試

======================================================

2008-10-15
謝謝您, 我了解您我解法的差別了.
------
IS IT WHAT IT IS
我是 李慕白 請倒著唸.
又想把老話拿出來說, 請用台語發音 : 專家專家全是ROBOT CAR (滷肉腳啦);
都已接手這麼久了, 績效還是那麼爛, 講話還那麼大聲.
編輯記錄
st33chen 重新編輯於 2008-12-12 12:37:36, 註解 無‧
st33chen 重新編輯於 2008-12-15 21:00:54, 註解 無‧
windheartalan
一般會員


發表:21
回覆:23
積分:8
註冊:2005-03-24

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-12-15 10:32:55 IP:203.66.xxx.xxx 訂閱
大大您好,
程式改了很多次,您說的插補法的部份,後來已經沒有留,感覺比較複雜,
後來直接利用現有的method來做處理,大概內容如下,

//先取得滑鼠所在座標軸位置x1,y1
TmpSeies := TChart(Sender).SeriesList.items[0];
TmpSeies.GetCursorValues(x1,y1);
if x1 > 0 then begin
//該座標值含小數,截取x1整數部份
ipos := pos('.',FloatToStr(x1))-1;
if ipos = -1 then begin
i:= StrToint(FloatToStr(x1));
end else begin
i:= StrToint(copy(FloatToStr(x1),1,ipos));
end;
//由x1值,取得該點對應的y軸value值
yvalue := TChart(Sender).SeriesList.Items[0].Yvalue[i];
//透過y軸value值,取得y軸座標位置
YPosition:=chart1.LeftAxis.CalcYPosValue(yvalue);
//區域內畫線
if (x1 > 0) and (x1 <=300) then begin
Chart1.Canvas.Pen.color := clskyblue;
//畫縱線
Chart1.Canvas.MoveTo(x,0);
Chart1.Canvas.LineTo(x,Chart1.Height-10);
//畫橫線
Chart1.Canvas.MoveTo(0,YPosition);
Chart1.Canvas.LineTo(Chart1.Width-10,YPosition);
end;
end;

===================引 用 st33chen 文 章===================
可以 show 一下 大大您的作法 嗎?
謝謝

我另一個想法是
固定 x, 用一個 loop 去改變 y 直到 碰壁 或 點的顏色等於線的顏色
這樣就不必套公式去算
不過後來沒試
系統時間:2024-04-20 21:18:40
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!