簡體   English   中英

用戶在Java中的時間序列數據中選擇的標記

[英]User-selected marker in time series data in Java

我的代碼在默認為581像素寬的面板中繪制了5000點的時間序列數據,但是當用戶調整窗口大小時,該寬度會改變。 我的代碼還繪制了幾個矩形標記,每個標記都標識了同一空間中的局部最大值/峰值。

我需要使用戶能夠右鍵單擊任何一個矩形峰標記,以便用戶可以手動刪除任何錯誤的峰。 問題是,當用戶右鍵單擊峰標記時,我的代碼報告的x坐標與預期不同。 我懷疑原因可能與將581個x像素轉換回5000個數據索引時的舍入誤差有關。 但我不確定原因。

誰能建議一種解決方案,使我的用戶通過右鍵單擊它來手動選擇上述峰標記之一?

我附上下面代碼的相關部分。 我的實際代碼非常非常長,發布起來太復雜。 但是下面的相關部分應該足以使別人看到我的方法的邏輯,然后提出一種更有效的方法。

聲明相關類的代碼是:

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();
    }

我建議您為要單擊的每件事創建對象(在本例中為Rectangles )。 這是一個簡化的示例,說明如何使繪制的內容可點擊。 要避免的關鍵是mouseClicked方法,該方法在鼠標在矩形內單擊時才會顯示對話框。

棘手的一點是,如果不在其上繪制另一個矩形,就無法弄清楚如何用顏色填充矩形。 我會把那個留給你;-)

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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM