Выбранный пользователем маркер в данных временных рядов в Java - PullRequest
0 голосов
/ 09 августа 2011

Мой код отображает 5000 точек данных временного ряда на панели шириной 581 пиксель по умолчанию, но эта ширина изменяется, когда пользователь изменяет размер окна.Мой код также отображает несколько прямоугольных маркеров, каждый из которых идентифицирует локальный максимум / пик в этом же месте.

Мне нужно разрешить пользователю щелкнуть правой кнопкой мыши любой из маркеров прямоугольного пика, чтобы пользователь мог вручнуюудалить любой ложный пик.Проблема в том, что мой код сообщает о других x-координатах, отличных от ожидаемых, когда пользователь щелкает правой кнопкой мыши пиковый маркер.Я подозреваю, что причина может быть связана с ошибкой округления при преобразовании из 581 x-пикселей обратно в 5000 индексов данных.Но я не уверен в причине.

Может кто-нибудь предложить решение, которое позволит моим пользователям вручную выбрать один из вышеописанных пиковых маркеров, щелкнув по нему правой кнопкой мыши?

Я согласенприложив соответствующие разделы кода ниже.Мой настоящий код очень, очень длинный и слишком сложный для публикации.Но соответствующих частей ниже должно быть достаточно, чтобы кто-то увидел логику моего подхода и затем предложил более эффективный подход.

Код, который объявляет рассматриваемый класс:

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

Этот сегмент кода перегружает компонент paintCanPanel, так что мои данные отображаются:

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

1 Ответ

1 голос
/ 09 августа 2011

Я предлагаю вам создать объекты (в данном случае 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);
    }
}
...