2011-08-08 13 views
0

私のコードは、デフォルトでパネルの幅が581ピクセルですが、ユーザーがウィンドウのサイズを変更すると5000ポイントの時系列データをプロットします。私のコードはまた、同じ空間内の極大/極大をそれぞれが識別するいくつかの長方形のマーカーをプロットします。Javaの時系列データでユーザーが選択したマーカー

私はユーザーが任意の誤ったピークを手動で削除できるように、長方形ピークマーカのどれかを右クリックする必要があります。問題は、ユーザーがピークマーカを右クリックしたときに、私のコードが予想外のx座標を報告していることです。私はその理由が、581 xピクセルから5000データインデックスに変換する際の丸め誤差と関係している可能性があると考えます。しかし、私はその理由を確信していません。

ユーザーは、上記のピークマーカーの1つを右クリックして手動で選択できるソリューションをお勧めしますか?

以下のコードの関連するセクションを囲んでいます。私の実際のコードは、非常に長く、投稿するのが難しいです。しかし、以下の関連部分は、誰かが自分のアプローチの論理を見て、より効果的なアプローチを提案するのに十分なはずです。

質問でクラスを宣言するコードは次のとおりです。

class SineDraw extends JPanel implements MouseMotionListener, MouseListener { 
// lots of code, including the two segments excerpted below 
} 

私のデータがプロットされるように、コードのこのセグメントは、のJPanelのpaintComponentをオーバーロード:

// declare some variables 
ArrayList<Double> PeakList = new ArrayList<Double>() // this ArrayList is populated by an extraneous process 
visiblePoints = 5000 
hstep = getWidth()/visiblePoints //=581/5000 by default, but will change when user resizes window 
int numPeaks = PeakList.size(); 

// scale (y-coordinate) data relative to height of panel 
pts = new double[visiblePoints] 
for (int i = 0; i < pts.length-1; i++){pts[i]=//data vertical scaled to fill panel;} 

// plot the 5000 time-series-data-points within the 581 pixels in x-axis 
for (int i = 1; i < visiblePoints; i++) { 
    int x1 = (int) ((i - 1) * hstep); 
    int x2 = (int) (i * hstep); 
    int y1 = (int)pts[i - 1]; 
    int y2 = (int)pts[i]; 
    g2.drawLine(x1, y1, x2, y2); 
} 

// plot a rectangle for each of the local peaks 
for(int m=0;m<=(numPeaks-1);m++){ 
    if(i==(int)(PeakList.get(m)){ 
     int currentVal = (int)pts[(int)(PeakList.get(m)]; 
     g2.drawRect((int)(PeakList.get(m), currentVal, 6, 6); 
    } 
} 

コードのこのセクションではマウスの右クリックを処理するために:

public void mousePressed(MouseEvent e){ 
    // check to see if right mouse button was clicked 
    boolean jones = (e.getModifiers()&InputEvent.BUTTON3_MASK)==InputEvent.BUTTON3_MASK; 
    if(jones==true){ 
     // test the value returned as x-coordinate when user right-clicks (code always underestimates x-coordinate of local peaks by this test) 
     double ReverseHstep = visiblePoints/getWidth(); 
     int getX_ConvertedTo_i = (int) (e.getX()*ReverseHstep); 
     System.out.println("getX_ConvertedTo_i is: "+getX_ConvertedTo_i); 

     // check to see if peaklist contains a value within the x-coordinates of the user-selected-rectangle 
     if(PeakList.contains((double)(e.getX()-3)) 
       ||PeakList.contains((double)(e.getX()-2)) 
       ||PeakList.contains((double)(e.getX()-1)) 
       ||PeakList.contains((double)(e.getX())) 
       ||PeakList.contains((double)(e.getX()+1)) 
       ||PeakList.contains((double)(e.getX()+2)) 
       ||PeakList.contains((double)(e.getX()+3)) 
       ){ 
       // handling code will go here, but for now it is a print test that never succeeds because x-coordinate is always underestimated 
       System.out.println("You just selected a peak!"); 
     } 
     } 
    repaint(); 
    } 
+0

私はこれをテストしていますが、右クリックで取得しているx座標はそれぞれ対応する期待値の92.7%と93.8%の間にありますPeakList ArrayListのピーク。これは、問題が系統的な丸め誤差に起因する可能性があると主張する。 – CodeMed

+1

あなたはいくつの矩形を描いていますか?それほど多くない場合は、各矩形を別々のオブジェクトにして、クリックイベントを聴かせることもできます。そうすれば、どこに描かれたのかは問題ではありません。 – Jeremy

+0

私は約3百万のデータポイントを持っています。そこには、おそらくそれぞれが自分の矩形を必要とする3500のローカルピークがあります。任意の時点で、JPanelには5000個のデータポイントしかプロットされておらず、5,000個のデータポイントウィンドウに5〜15個のローカルピークが存在するかもしれませんが、パネルの下部にスクロールバーがあり、すべての3500のピークを表示するために100万データポイント。 JPanelは、ユーザがスクロールバーをutlizeしたときに再描画されます。 – CodeMed

答えて

1

この場合Rectangles)をクリックできるようにします。ここでは、クリック可能な描画を行うための簡単な例を示します。これを取り除くために重要なことは、mouseClickedメソッドです。マウスが四角形内でクリックされた場合にのみダイアログが表示されます。

1つのトリッキーなポイントは、矩形を色で塗りつぶす方法を見つけ出すことができなかったことです。

public class Canvas extends JPanel implements MouseListener{ 
    private Rectangle rect = new Rectangle(100,100); 

    public Canvas(){ 
     this.addMouseListener(this); 
     rect.setSize(100, 100); 
    } 

    @Override 
    public void paintComponent(Graphics g){ 
     g.setClip(rect); 
     g.setColor(Color.RED); 
     g.fillRect(0, 0, 100, 100); 
    } 

    @Override 
    public void mouseClicked(MouseEvent e){ 
     if(rect.contains(e.getPoint())){ 
      JOptionPane.showConfirmDialog(this, "Click!"); 
     } 
    } 

    // The rest of the MouseListener methods have been cut out 

    public static void main(String[] a){ 
     JFrame frame = new JFrame("Canvas Thingy"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setBounds(0, 0, 300, 300); 
     frame.add(new Canvas()); 
     frame.setVisible(true); 
    } 
} 
+0

ありがとうございます。クリック可能にしたい時系列データのマーカーごとに別のJPanelを作成する必要があるようです。 (5〜15個の小さなマーカーパネル、それぞれ5000データポイントがプロットされている大きなデータパネルに配置されています)JPanelを拡張する代わりにコードを変更してRectangleを拡張しようとするとエラーメッセージが表示されるRectangleは関連するメソッドをサポートしていないことを伝えます。 – CodeMed

+0

私はキャンバスに長方形のリストがあることを暗示していました。 – Jeremy

+0

私はこれをもう一度やり直しています。それ以上のコメントや質問があります。 – CodeMed

関連する問題