Проблема с mouseListener на JPanel - PullRequest
       18

Проблема с mouseListener на JPanel

1 голос
/ 12 ноября 2009

У меня проблема с mouseListener в JPanel.Я добавляю JLabel, который содержит изображение (размер 600 x 600) в JPanel, и добавляю mouseListener для JPanel.

Каждый раз, когда я нажимаю на изображение, оно должно меняться на другое, и это работает нормально.Однако проблема в том, что, только если я нажму на правой стороне или в центре изображения, изображение изменится на другое изображение.Изображение не меняется, когда я нажимаю на верхнюю или левую сторону.Это меня смущает.Я хочу, чтобы изображение менялось на другое, когда я щелкаю повсюду на экране.

private final int SECOND= 1;
private final int FIRST = 0;
int imageCounter = 0;

JLabel picture;
JPanel panel;

...

private mainLayout () {
  GridBagLayout m = new GridBagLayout();
  Container c = (Container)getContentPane();
  GridBagConstraints con;
  c.setLayout (m);

  picture = new JLabel();
  picture.setIcon(getImages(myImage.get(imageCounter).get(FIRST)));  //first Image

  panel = new JPanel();     
  con = new GridBagConstraints();
  con.anchor=GridBagConstraints.CENTER;
  con.gridy = 1; con.gridx = 0;     
  m.setConstraints(panel, con);
  c.add(panel);
  panel.add(picture); //add the pictures

  panel.addMouseListener(l);
  ....
}

MouseListener l = new MouseAdapter(){
  public void mouseClicked (MouseEvent e) 
  {
    Point p = e.getPoint();
    if((panel.getBounds().contains(p))
       picture.setIcon(getImages(myImage.get(imageCounter).get(SECOND)));
  }
};

Ответы [ 4 ]

2 голосов
/ 26 сентября 2012

Вероятная проблема, с которой вы столкнулись, та же, с которой я столкнулся, в том, что ваше событие сожрано в вашей иерархии, как предполагалось предыдущим постером. Что касается ответа Camickr, это действительно не имеет значения, если вы продлите JPanel или JLabel, если вы знаете о последствиях. JPanel предлагает вам гораздо больше возможностей и уже содержит много полезных вещей. Но давайте возьмем простой пример, где у вас есть следующее:

A JFrame, который содержит JPanel, назовите его JParent. JParent имеет набор слушателей мыши, выделенных для него.

JParent содержит дочерний элемент JPanel, который добавляется к его компонентам и называется JChild. JChild также имеет свой собственный набор слушателей мыши.

Что произошло, когда вы нажали на область, которая не занята JChild? Вы получите ответ от слушателей JParent. Если щелкнуть область с видимым JChild, будут срабатывать только события мыши JChild.

Так что будьте очень осторожны при отладке, поскольку свинг Java может вести себя иначе, чем вы могли бы привыкнуть в других реализациях рисования простых форм / графических интерфейсов. События в основном однократные, а компонент самого низкого уровня получает первые кубики. Если вы все равно попытаетесь запустить события родителя, ваши координаты x / y будут основаны на дочернем, а не на родительском. Я все еще пытаюсь найти хорошую работу вокруг себя, потому что мне нужен доступ конкретно к родителю, чтобы переместить объект в другое место.

Лучшее, что я могу придумать, это не беспорядок для отладки / размышления, это две идеи: а) пусть каждый из ваших отдельных компонентов содержит свой собственный эксклюзивный набор событий и попытается предотвратить появление эффекта «пузырения». б) обрабатывать все события на родительском

Я бы предпочел a, так как он позволяет избежать неприятных вещей, таких как проверка классов компонентов, просто чтобы выяснить, какую реакцию вы хотите (то есть, например, какое меню щелкнуть правой кнопкой мыши, чтобы показать).

Редактировать: Так что вы можете справиться с этим любым способом, который я обнаружил. Вы можете использовать сообщение dispatchEvent для пересылки событий обратно вверх по цепочке. В моем случае я должен сожрать первое событие (или изменить его) и отправить x-y позиции, как если бы они были относительно родителя (используя смещения). Я бы сказал, что лучший способ сделать это - пересылка, потому что тогда все ваши отдельные компоненты могут быть инкапсулированы.

2 голосов
/ 13 ноября 2009

Проблема выглядит так, как будто она может быть в этом ненужном коде:

Point p = e.getPoint();
if((panel.getBounds().contains(p))

Слушатель мыши находится на панели, поэтому координаты мыши будут относительно левой верхней панели.panel.getBounds() получает границы панели относительно того, чем является ее родительский контейнер.

Стоит отметить, что событие мыши ведет себя очень странно.Они «всплывают», пока не попадают на компонент с подключенным слушателем мыши.Таким образом, добавление слушателя мыши фактически меняет поведение компонента.Добавление слушателя к родителю может пропустить события в зависимости от того, как именно настроен компонент (который может меняться произвольно).Есть несколько способов обойти это, но ни один из них не хорош.

0 голосов
/ 12 ноября 2009

Из любопытства, почему вы используете JLabel для отображения изображения? Возможно, вам лучше написать класс ImagePanel, который расширяет JPanel и переопределяет метод paint () для создания вашего собственного чертежа. Затем вы можете прикрепить MouseListeners прямо к панели.

0 голосов
/ 12 ноября 2009

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

...