2011-08-08 1 views
0

Мой код отображает 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(); 
    } 
+0

Я проверял это, и координаты х я получаю, щелкнув правой кнопкой мыши каждый между 92,7% и 93,8% от ожидаемых значений из соответствующих пик в массиве PeakList ArrayList. Это говорит о том, что проблема может быть связана с систематической ошибкой округления. – CodeMed

+1

Сколько прямоугольников вы рисуете? Если не слишком много, вы можете сделать каждый прямоугольник отдельным объектом и заставить их прослушивать событие click. Тогда неважно, «где» было нарисовано. – Jeremy

+0

У меня около 3 миллионов точек данных, в которых, возможно, есть 3500 локальных пиков, каждый из которых нуждается в собственном прямоугольнике. В любой момент времени в JPanel отображается только 5000 точек данных, и может быть от 5 до 15 локальных пиков в этом окне 5000 datapoint, но в нижней части панели есть полоса прокрутки, которая позволяет пользователю прокручивать 3 миллионов точек данных, чтобы увидеть все 3500 пиков. JPanel перекрашивается, когда пользователь использует полосу прокрутки. – CodeMed

ответ

1

Предлагаю вам создать объекты (в этот случай 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); 
    } 
} 
+0

спасибо.Похоже, мне нужно создать отдельный JPanel для каждого маркера в моих данных временных рядов, которые я хочу кликать. (От 5 до 15 небольших панелей-маркеров, каждый из которых помещается на большую панель данных, где также отображаются мои 5000 точек данных.) Я говорю это, потому что, когда я пытаюсь изменить код, чтобы расширить Rectangle вместо расширения JPanel, я получаю сообщения об ошибках говоря, что Rectangle не поддерживает соответствующие методы. – CodeMed

+0

Я подразумевал, что ваш холст может иметь список прямоугольников. – Jeremy

+0

Я сейчас работаю над этим, и у меня могут появиться дополнительные комментарии/вопросы, когда я буду вдаваться в него. – CodeMed

 Смежные вопросы

  • Нет связанных вопросов^_^