Мой код отображает 5000 точек временных рядов данных на панели шириной 581 пиксель по умолчанию, но эта ширина изменяется, когда пользователь меняет размер окна. Мой код также отображает несколько прямоугольных маркеров, каждый из которых идентифицирует локальный максимум/пик в этом же пространстве.Пользовательский маркер в данных временных рядов в Java
Мне нужно, чтобы пользователь мог щелкнуть правой кнопкой мыши по любому из прямоугольных пиковых маркеров, чтобы пользователь мог вручную удалить любой ложный пик. Проблема в том, что мой код сообщает о разных координатах x, чем ожидалось, когда пользователь щелкает правой кнопкой мыши на маркер пика. Я подозреваю, что причина может быть связана с ошибкой округления при преобразовании с 581 х пикселей в 5000 индексов данных. Но я не уверен в причине.
Может ли кто-нибудь предложить решение, позволяющее моим пользователям вручную выбрать один из вышеописанных пиковых маркеров, щелкнув правой кнопкой мыши на нем?
Включая соответствующие разделы приведенного ниже кода. Мой фактический код очень, очень длинный и слишком сложный для публикации. Но соответствующие части ниже должны быть достаточными для того, чтобы кто-то увидел логику моего подхода, а затем предложил более эффективный подход.
код, который объявляет класс в вопросе:
class SineDraw extends JPanel implements MouseMotionListener, MouseListener {
// lots of code, including the two segments excerpted below
}
Этот сегмент кода перегружает paintComponent в JPanel, так что мои данные нанесены:
// 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();
}
Я проверял это, и координаты х я получаю, щелкнув правой кнопкой мыши каждый между 92,7% и 93,8% от ожидаемых значений из соответствующих пик в массиве PeakList ArrayList. Это говорит о том, что проблема может быть связана с систематической ошибкой округления. – CodeMed
Сколько прямоугольников вы рисуете? Если не слишком много, вы можете сделать каждый прямоугольник отдельным объектом и заставить их прослушивать событие click. Тогда неважно, «где» было нарисовано. – Jeremy
У меня около 3 миллионов точек данных, в которых, возможно, есть 3500 локальных пиков, каждый из которых нуждается в собственном прямоугольнике. В любой момент времени в JPanel отображается только 5000 точек данных, и может быть от 5 до 15 локальных пиков в этом окне 5000 datapoint, но в нижней части панели есть полоса прокрутки, которая позволяет пользователю прокручивать 3 миллионов точек данных, чтобы увидеть все 3500 пиков. JPanel перекрашивается, когда пользователь использует полосу прокрутки. – CodeMed