2013-03-27 120 views
3

比方說,我有這樣的XYSeries如何獲取XYSeries x位置的屏幕x位置?

XYSeries temps = new XYSeries("Temperature"); 
temps.add(0, 43); 
temps.add(1, 42); 
temps.add(2, 40); 
temps.add(3, 38); 
temps.add(4, 35); 
temps.add(5, 35); 
temps.add(6, 34); 
temps.add(7, 33); 
temps.add(8, 32); 
temps.add(9, 32); 

如果呈現,這將圖表在10小時內把溫度。

如何獲得本系列中每個數據點的屏幕x位置?換句話說,我如何找出第六個數據點在屏幕上的位置?

我想要做的是確定哪個數據點是最近的 - 在X軸上 - 到用戶觸摸屏幕的位置,以便可以顯示數據點的詳細信息。

XYChart.getSeriesAndPointForScreenCoordinate()排序的工作,除了用戶必須直接觸摸一條線,而他們應該能夠觸摸該數據點的x軸垂直的任何地方。我認爲這只是將圖表空間轉換爲屏幕空間的問題(反之亦然),但我還沒有看到Javadoc中只有x位置的任何方法;它們都需要x和y,如果y不匹配數據點,則不返回任何內容。

任何想法?

更新

以丹的智慧進去,就可以得到「圖表空間」與toScreenPoint()方法給定的屏幕x位置的x位置,如下所示:

double[] chartPoint = chart.toScreenPoint(new double[] {event.getX(), event.getY()}, 2); 
// double[0] == 4935.436905570652 

但是,現在問題是採用這個座標並找到它最近的數據點。我可以手動搜索最近的數據指向自己,如果有一種方式來獲得的「圖表空間」對於一個給定XYSeries指數/數據點x位置:

// Build a list of the data points' chart space x-positions 
double[] dataPointPositions = new double[temps.getItemCount()]; 
for(int index = 0; index < dataPointPositions.length; index++) 
{ 
    dataPointPositions[index] = getXPositionForIndex(index, scale); 
} 

// (Go thru the list of data point positions, comparing them to the 
// value taken from toScreenPoint() to find which one is closest.) 

所以,現在的數百萬美元的問題是,有沒有一個getXPositionForIndex()方法已經在ACE,或者有沒有辦法用現有的方法寫一個?這個方法會爲XYSeries數據點取一個索引(可能還有比例),它將返回該數據點的「圖表空間」x位置。 這是我卡住的地方。

整個想法是觸摸屏幕並找出用戶觸摸最接近的十個數據點(在本例中)是哪一個。

更新2

我更新了我的代碼只是爲了看看toRealPoint()將返回。這是我的OnTouchListener;你可以看到我輸出一些不同的值,只是爲了看看我得到:

@Override 
public boolean onTouch(View view, MotionEvent event) 
{ 
    Log.i(TAG, "onTouch()"); 
    Log.i(TAG, "event.x = " + event.getX() + ", event.y = " + event.getY()); 

    double[] screenPoints = chart.toScreenPoint(new double[] {event.getX(), event.getY()}, 0); 
    Log.i(TAG, "Screen points: " + event.getX() + " = " + screenPoints[0] + ", " + event.getY() + " = " + screenPoints[1]); 

    double[] realPoints1 = chart.toRealPoint(event.getX(), event.getY()); 
    Log.i(TAG, "Real points #1: " + event.getX() + " = " + realPoints1[0] + ", " + event.getY() + " = " + realPoints1[1]); 

    double[] realPoints2 = chart.toRealPoint((float)screenPoints[0], (float)screenPoints[1]); 
    Log.i(TAG, "Real points #2: " + screenPoints[0] + " = " + realPoints2[0] + ", " + screenPoints[1] + " = " + realPoints2[1]); 

    return true; 
} 

不幸的是,我回來的數字並不樂觀:

03-27 17:10:18.277: I/MainActivity(1149): onTouch() 
03-27 17:10:18.277: I/MainActivity(1149): event.x = 98.19905, event.y = 259.41077 
03-27 17:10:18.277: I/MainActivity(1149): Screen points: 98.19905 = 2049.3714971127715, 259.41077 = -Infinity 
03-27 17:10:18.287: I/MainActivity(1149): Real points #1: 98.19905 = -Infinity, 259.41077 = 44.807568573847 
03-27 17:10:18.297: I/MainActivity(1149): Real points #2: 2049.3714971127715 = -Infinity, -Infinity = Infinity 

當試圖改變一個屏幕指向一個使用toRealPoint()的真實點,它總是給我-Infinity x位置(這是我唯一真正關心的)。我不確定是否應該通過它的「原始」屏幕點(從MotionEvent)或「轉換」的屏幕點(從toScreenPoint()),所以我試着用它來看看它會輸出什麼。

我做得完全錯誤的?如果沒有,有什麼想法?

更新3

我認爲我們(或者說...... )可能已經過這樣想的太多了。 MotionEvent提供的觀點實際上不需要翻譯;它提供的座標已經是合適的「屏幕空間」。 做什麼需要翻譯的是數據點座標;他們在「圖表空間」中,爲了將它們與「屏幕空間」進行比較,您必須這樣翻譯它們。

考慮下面的代碼:

@Override 
public boolean onTouch(View view, MotionEvent event) 
{ 
    Log.i(TAG, "onTouch()"); 
    Log.i(TAG, "event.x = " + event.getX() + ", event.y = " + event.getY()); 

    for(int i = 0; i < tempSeries.getItemCount(); i++) 
    { 
     double x = tempSeries.getX(i); 
     double y = tempSeries.getY(i); 
     double[] screenPoint = chart.toScreenPoint(new double[] { x, y }, 0); 

     Log.i(TAG, x + "," + y + " = " + screenPoint[0] + "," + screenPoint[1]); 
    } 

    return true; 
} 

當用戶觸摸屏幕時,所有我在這裏做的是輸出MotionEvent座標,然後我在我的XYSeries循環直通每一個數據點。我打印出原始數據點(範圍從0.0到23.0,因爲我總共有24個數據點)。我還使用toScreenPoint()方法打印出已翻譯的「屏幕空間」點。這允許將MotionEvent座標與數據點座標進行比較。

我不會打擾從該代碼發佈冗長的輸出,因爲它並不重要。重要的是要實現在「8 PM」x軸(其內部數據點值爲20 [12 + 8 = 20])周圍垂直觸摸屏幕,我在OnTouchListener講座中收到的座標MotionEvent我碰到了x位置420.0(+/- 20左右)。現在,如果我查看所有翻譯過的「screenPoint」值,我會發現一個值大約是420.0 - 「8 PM」值!

總之,要將用戶的觸摸轉換爲數據點x位置值,您只需將MotionEvent x位置與toScreenPoint()轉換後的數據點x位置進行比較。 toScreenPoint()將數據點的x位置轉換爲MotionEvent使用的相同座標系統(例如「屏幕空間」)。從那裏,找出用戶觸摸時最接近的數據點是通過轉換數據點x位置循環並與x位置比較的微不足道的事情。 :)

回答

3

XYChart類有這樣的方法:

public double[] toScreenPoint(double[] realPoint, int scale) 

然而,爲了使用它,你將不得不放棄你可能用來創建GraphicalView實例的方式。

舉例來說,這樣的:

GraphicalView view = ChartFactory.getLineChartView(context, dataset, renderer); 

將成爲這樣的:

XYChart chart = new LineChart(dataset, renderer); 
GraphicalView view = new GraphicalView(context, chart); 

做這將是你將有你的chart實例的引用,這樣你就可以調用的好處我提到的方法。

更新:我認爲更新的問題是尋找相反的方法,將屏幕點轉換爲真實點。你可以在XYChart中使用這種方法:

public double[] toRealPoint(float screenX, float screenY, int scale) 
+0

我已經給了這個更多的想法,並已更新/澄清了這個問題。 XYSeries中有多個數據點,每個數據點都通過XYSeries.add()添加。每個都有一個從零開始的索引,根據它們添加的順序分配。是否有可能採取這個指數,並獲得數據點的「圖表空間」x位置?如果是這樣,那麼我可以手動進行檢查並確定觸摸最接近哪個數據點。任何幫助/提示/指導你可以提供將是如此真棒。我最終將把所有這些放在教程中,因爲我確定還有其他人想要在他們的圖表中添加「光標」。 :) – 2013-03-27 18:13:00

+0

我希望我的問題正確。請看我編輯的答案。 – 2013-03-27 19:58:35

+0

謝謝丹。是的,我相信這就是我需要的 - 反向的方法。非常感謝你在這裏的幫助,不幸的是我不認爲這種方法可行。我更新了問題以顯示我的結果。 – 2013-03-27 22:23:04