JLayeredPane: как проверить, есть ли под ним другой компонент

У меня есть JLayeredPane. На что я помещаю несколько компонентов. Эти компоненты являются классами, расширяющими jPanel. Все компоненты размещены в одном слое глубины. Каждый компонент может иметь или не иметь другой компонент/компоненты полностью/частично выше/ниже него. Когда я нажимаю на компоненты, щелкается самый верхний.

Как проверить, есть ли еще компоненты ниже топомоста в том месте, где я щелкнул? Как я могу «передать» событие щелчка одному из этих или многим из этих компонентов ниже?

РЕДАКТИРОВАТЬ: рабочий пример

 import java.awt.*;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.util.ArrayList;
 import javax.swing.*;

 public class JavaJLayeredPane {
    JFrame frame;
    JLayeredPane layeredPane;
    JPanel Panel1;
    JPanel panel;

 public void createUI()
 {
    frame = new JFrame("Items one ove the other");
    frame.setPreferredSize(new Dimension(600, 400));
    frame.setLayout(new BorderLayout());

    layeredPane = new JLayeredPane();
    frame.add(layeredPane, BorderLayout.CENTER);

    layeredPane.setBounds(0, 0, 600, 400);

    ArrayList<Color> colorList = new ArrayList<Color>();
    colorList.add(Color.red);
    colorList.add(Color.yellow);
    colorList.add(Color.blue);
    colorList.add(Color.green);
    colorList.add(Color.cyan);

    for (int i=0; i<5; i++){
    String mytext="no"+ i;
    Panel1 = new myarea(mytext);
    Panel1.setBackground(colorList.get(i));
    if (i==0){Panel1.setBounds(210, 110, 20, 20);}
    if (i==1){Panel1.setBounds(200, 100, 150, 150);}
    if (i==2){Panel1.setBounds(250, 110, 170, 120);}
    if (i==3){Panel1.setBounds(180, 130, 110, 110);}
    if (i==4){Panel1.setBounds(450, 150, 50, 50);}
    layeredPane.add(Panel1, new Integer(0), 0);
    }

    panel = new JPanel();
    frame.add(panel);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }



public static void main(String[] args) {
    JavaJLayeredPane overlapPane = new JavaJLayeredPane();
            overlapPane.createUI();
}

   public class myarea extends JPanel implements  MouseListener{
        public String areaname;

    public myarea(String myname) {
        addMouseListener(this);
        areaname=myname;
    }

//LISTENERS    
    @Override
 public void mousePressed(MouseEvent evt){
}
    @Override
public void mouseReleased(MouseEvent evt){
}
    @Override
public void mouseClicked(MouseEvent evt){
    if(evt.getButton() == MouseEvent.BUTTON1){
    JOptionPane.showMessageDialog(null,areaname ) ;    
    }

  }
    @Override
  public void mouseEntered(MouseEvent evt){
  }
    @Override
  public void mouseExited(MouseEvent evt){
  }
 }


 }

Если мы нажмем на прямоугольник, который находится внутри другого, мы получим его имя. Как проверить, есть ли внизу другой прямоугольник, и если да, то как получить его свойства?


person geo    schedule 01.02.2014    source источник
comment
Звучит как очень плохое использование JLayeredPane IMO. Может быть, работающий пример может изменить мое мнение.   -  person Paul Samsotha    schedule 01.02.2014
comment
@peeskillet. Мой случай слишком сложен, чтобы публиковать его здесь. Почему плохое использование? Нет ничего плохого в размещении компонентов друг над другом в JLayeredPane, и нет ничего плохого в том, что нужно иметь доступ ко всем перекрывающимся компонентам с помощью мыши. Есть?   -  person geo    schedule 01.02.2014
comment
Зачем вообще использовать JlayeredPane, если вы собираетесь разместить все компоненты на одном слое? Вот этого я и добивался.   -  person Paul Samsotha    schedule 01.02.2014
comment
Я согласен, что это звучит немного подозрительно, имея все компоненты на одном слое, но вы можете добавить MouseListener к самой JLayeredPane, а затем выполнить итерацию по его компонентам, чтобы увидеть, какой из них находится в точке щелчка мыши. Кроме того, никто не будет спрашивать у вас всю вашу программу, но ваш случай, безусловно, не слишком сложен, если вы не сведете его к минимальному компилируемому и исполняемый пример, что-то, что да, потребует усилий, но часто оно того стоит.   -  person Hovercraft Full Of Eels    schedule 01.02.2014
comment
В порядке. Я не упомянул, что кроме тех, которые могут перекрываться, есть и другие компоненты, находящиеся на других слоях. Объекты, которые могут перекрываться, являются разными экземплярами одного и того же класса, и их может быть несколько сотен. Сотни слоев не нужны, и я думаю, что это не очень хороший дизайн. И в любом случае это не решило бы мою проблему, чтобы узнать, что именно скрывается за компонентом, который я нажимаю.   -  person geo    schedule 01.02.2014
comment
Я не понимаю, почему кто-то заминусовал вопрос. Неважно, лучший ли мой подход к разработке программного обеспечения, вопрос прост и прямолинеен. Многие компоненты в JLayeredPane, как получить доступ с помощью мыши к тем, что ниже.   -  person geo    schedule 01.02.2014
comment
Я не голосую за вас и не голосую за вас, но воздержусь от попыток ответить на этот вопрос до тех пор, пока вы не опубликуете mcve. Это не требование, конечно, но это поможет тем, кто пытается вам помочь.   -  person Hovercraft Full Of Eels    schedule 01.02.2014
comment
@HovercraftFullOfEels Я хотел бы дать mcve, но это сложно. Но мой вопрос довольно прост. На 1-м изображении в [ссылка] (docs.oracle.com/javase /tutorial/uiswing/components/) есть 5 цветных панелей. Предположим, они находятся на одном слое, и вы нажимаете на верхний левый угол зеленого слоя. Мой вопрос заключается в том, как узнать, находятся ли другие панели до точки, на которую я нажал. На рисунке красный, голубой и пурпурный должны быть разрешены, а желтый (вероятно) нет. Но предположим, что красный цвет меньше и полностью скрыт под зеленым. Откуда мы знаем, что лежит под зеленым?   -  person geo    schedule 01.02.2014
comment
Ваш вопрос по своей сути прост, но для того, чтобы построить ответ и протестировать его, мне пришлось бы создать свой собственный mcve, что, как вы утверждаете, сложно. Поскольку это ваш вопрос, я предпочитаю, чтобы основные усилия по созданию этого инструмента были вашими, а не моими, но, возможно, если вы подождете дольше, придет кто-то другой, создаст свой собственный и решит его для вас. Если этого не произойдет в ближайшее время, рассмотрите возможность пересмотра своего решения не создавать его. Если вы передумаете, пожалуйста, сообщите мне, чтобы я посмотрел на него. На данный момент я выхожу из системы. Удача!   -  person Hovercraft Full Of Eels    schedule 02.02.2014
comment
Просто добавил рабочий пример того, что я пытаюсь сделать   -  person geo    schedule 02.02.2014
comment
Не связано: пожалуйста, изучите соглашения об именах Java и придерживайтесь их.   -  person kleopatra    schedule 02.02.2014


Ответы (1)


По сути две задачи:

  • посетить компоненты в том же слое, которые находятся ниже того, который получает mouseEvent, и найти первый, который содержит местоположение мыши
  • если найдено, вручную отправьте событие (и пусть оно обрабатывает дальнейшие отправки, если это необходимо)

JLayeredPane API помогает с первым, а Component имеет метод для второго — единственное, что требует внимания, — это преобразование координат, где в игру вступают вспомогательные методы SwingUtilities.

@Override
public void mouseClicked(MouseEvent evt) {
    if (!SwingUtilities.isLeftMouseButton(evt)) return;
    Component[] siblings = layeredPane.getComponentsInLayer(JLayeredPane.getLayer(this));
    int pos = layeredPane.getPosition(this);
    for (Component sibling : siblings) {
        // interested in siblings below
        if (layeredPane.getPosition(sibling) > pos) {
            // convert coordinates
            Point p = SwingUtilities.convertPoint(this, evt.getX(), evt.getY(), sibling);
            if (sibling.contains(p)) {
                // convert event
                MouseEvent dispatch = SwingUtilities.convertMouseEvent(
                        this, evt, sibling);
                // manually dispatch the event
                sibling.dispatchEvent(dispatch);
                break;
            }
        }

    }
    // do my own work
    System.out.println(getName() + evt);
}
person kleopatra    schedule 02.02.2014