Java 在视口组件上使用JScrollPane鼠标侦听器
我有一个Java 在视口组件上使用JScrollPane鼠标侦听器,java,swing,Java,Swing,我有一个JScrollPane,可以将其视口视图设置为一系列不同的面板。每当单击其视口中的任何其他组件时,我都希望获得JScrollPane组件。如果我向JScrollPane添加一个MouseStener,当我直接单击窗格的边框时,它会接收我的鼠标事件,而不是在单击组件时 添加侦听器并最终找到所附滚动窗格的正确方法是什么?我不一定提前知道我在视口中显示的面板上的所有组件,只是它们将位于JPanel的某个子类上 import java.awt.event.MouseEvent; import j
JScrollPane
,可以将其视口视图设置为一系列不同的面板。每当单击其视口中的任何其他组件时,我都希望获得JScrollPane组件。如果我向JScrollPane添加一个MouseStener
,当我直接单击窗格的边框时,它会接收我的鼠标事件,而不是在单击组件时
添加侦听器并最终找到所附滚动窗格的正确方法是什么?我不一定提前知道我在视口中显示的面板上的所有组件,只是它们将位于JPanel的某个子类上
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.MouseInputAdapter;
import net.miginfocom.swing.MigLayout;
public class TestScrollPane extends MouseInputAdapter{
public void mouseEntered(MouseEvent arg0) {System.out.println("Entered " + arg0.getComponent());}
public void mouseExited(MouseEvent arg0) {System.out.println("Exited " + arg0.getComponent());}
public void mousePressed(MouseEvent arg0) {System.out.println("Pressed " + arg0.getComponent());}
public void mouseReleased(MouseEvent arg0) {System.out.println("Released " + arg0.getComponent());}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setLayout(new MigLayout());
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestPane pane1 = new TestPane("Scroll Pane 1");
TestPane pane2 = new TestPane("Scroll Pane 2");
frame.add(pane1, "push,grow");
frame.add(pane2, "push, grow");
TestMouseListener listener = new TestMouseListener();
pane1.addMouseListener(listener);
pane1.addMouseMotionListener(listener);
pane2.addMouseListener(listener);
pane2.addMouseMotionListener(listener);
frame.setVisible(true);
}
}
class TestPanel2 extends JPanel {
String name;
TestPanel2(String name){
this.name = name;
setLayout(new MigLayout());
JTextArea area = new JTextArea();
area.append(name);
add(area, "push, grow");
}
public String toString(){ return name; }
}
class TestPane extends JScrollPane {
String name;
TestPane(String name){
this.name = name;
TestPanel2 panel = new TestPanel2(name + " panel");
setViewportView(panel);
}
public String toString(){ return name; }
}
在本例中,我获得鼠标进入和退出事件,但我只能通过单击文本区域周围的边框来获得鼠标单击事件。即使我更改TestPane类以将侦听器添加到其viewportView面板中,我也无法判断textArea中发生了什么
class TestPane extends JScrollPane {
String name;
TestPane(String name){
this.name = name;
TestPanel2 panel = new TestPanel2(name + " panel");
TestMouseListener listener = new TestMouseListener();
panel.addMouseListener(listener);
panel.addMouseMotionListener(listener);
setViewportView(panel);
}
public String toString(){ return name; }
}
不过,我无法知道JPanel上有什么内容,因此我无法手动添加更深层次的侦听器。您应该将鼠标侦听器添加到JScrollPane的视图,而不是滚动窗格本身,因为滚动窗格只包含角点和滚动条
yourJScrollPane.getViewport().getView().addMouseListener(yourMouseListener);
此代码段将您的鼠标侦听器添加到JScrollPane的单视口组件中。您将遇到的问题是,如果面板包含的内容也包含鼠标侦听器,您将永远不会收到这些事件的通知(鼠标事件往往会被链中较高的人使用) 您可以使用addNotify,模拟JTable的工作方式。然后,您将遍历父链,直到找到所需的组件
当然,这是假设您不想使用鼠标侦听器…另一种可能的方法是使用AWTEventListener,然后弹出父树,查看您感兴趣的组件是否已被按下,或者是否包含已按下的子组件。例如:
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.MouseInputAdapter;
// import net.miginfocom.swing.MigLayout;
public class TestScrollPane extends MouseInputAdapter {
public void mouseEntered(MouseEvent arg0) {
System.out.println("Entered " + arg0.getComponent());
}
public void mouseExited(MouseEvent arg0) {
System.out.println("Exited " + arg0.getComponent());
}
public void mousePressed(MouseEvent arg0) {
System.out.println("Pressed " + arg0.getComponent());
}
public void mouseReleased(MouseEvent arg0) {
System.out.println("Released " + arg0.getComponent());
}
public static void main(String[] args) {
JFrame frame = new JFrame();
// frame.setLayout(new MigLayout());
frame.getContentPane().setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestPane pane1 = new TestPane("Scroll Pane 1");
TestPane pane2 = new TestPane("Scroll Pane 2");
frame.add(pane1, "push,grow");
frame.add(pane2, "push, grow");
// !! TestMouseListener listener = new TestMouseListener();
TestScrollPane listener = new TestScrollPane();
pane1.addMouseListener(listener);
pane1.addMouseMotionListener(listener);
pane2.addMouseListener(listener);
pane2.addMouseMotionListener(listener);
frame.pack();
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(
listener.createAWTWindowListener(), AWTEvent.MOUSE_EVENT_MASK);
}
private AWTEventListener createAWTWindowListener() {
AWTEventListener awt1 = new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent e) {
if (MouseEvent.MOUSE_PRESSED == e.getID()) {
MouseEvent event = (MouseEvent) e;
Component comp = event.getComponent();
if (comp != null) {
String scrollPanelName = recursivelyCheckForScrollPanel(comp);
if (scrollPanelName != null) {
System.out.println("TestPane pressed. Name: " + scrollPanelName);
} else {
System.out.println("TestPane not pressed");
}
}
}
}
private String recursivelyCheckForScrollPanel(Component comp) {
if (comp instanceof TestPane) {
return comp.toString();
} else {
comp = comp.getParent();
if (comp != null) {
return recursivelyCheckForScrollPanel(comp);
}
}
return null;
}
};
return awt1;
}
}
class TestPanel2 extends JPanel {
String name;
TestPanel2(String name) {
this.name = name;
// setLayout(new MigLayout());
JTextArea area = new JTextArea(5, 20);
area.append(name);
add(area, "push, grow");
}
public String toString() {
return name;
}
}
class TestPane extends JScrollPane {
String name;
TestPane(String name) {
this.name = name;
TestPanel2 panel = new TestPanel2(name + " panel");
setViewportView(panel);
}
public String toString() {
return name;
}
}
注:请参阅StanislovL和mkorbel的答案了解更多信息。@mkorbel:是的,它看起来应该很熟悉!谢谢你的代码!不,干得不错,因为JScrollPane(JViewport)不是JComponent,也不是容器,使用GetDeepTestComponent时我不能正常工作,必须有另一种方法:-)你能看看我在这里删除的帖子吗我对这种方法很乐观,尽管我在细节上遇到了一些障碍。实际上,我希望每个滚动窗格都有不同的侦听器,但是Toolkit.getDefaultToolkit().addAWTEventListener似乎不允许这种区分。正常工作了。事实上,当我意识到我有太多的监听器时,我的代码简化了很多。谢谢,@HovercraftFullOfEels!