我想創建一個應用程序,其中一些事件應該像處理父容器一樣處理。例如,我有一個包含JLabel的JPanel。頂級的JPanel現在實現了鼠標移動和拖拽。我需要做些什麼才能使事件看起來像是到達JPanel而不是標籤本身。 (改變源對象很重要)將事件傳遞給父節點
有沒有比實際實現事件並在父項中複製它們更好的解決方案? (這會在一些有5個孩子的物體後變得乏味)。
我想創建一個應用程序,其中一些事件應該像處理父容器一樣處理。例如,我有一個包含JLabel的JPanel。頂級的JPanel現在實現了鼠標移動和拖拽。我需要做些什麼才能使事件看起來像是到達JPanel而不是標籤本身。 (改變源對象很重要)將事件傳遞給父節點
有沒有比實際實現事件並在父項中複製它們更好的解決方案? (這會在一些有5個孩子的物體後變得乏味)。
在您的事件偵聽器中,您可以將事件分派給父組件。
作爲myEvent
事件處理函數的參數:
Component source=(Component)myEvent.getSource();
source.getParent().dispatchEvent(myEvent);
但是這種解決方案意味着創造的每個元素添加一個新的事件監聽。
所以,你可以創建一個單一的事件處理程序,並重新使用它,將它添加到所有選定的孩子,像這樣:
final Container parent=this; //we are a the parent container creation code
MouseListener myCommonListener=new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
parent.dispatchEvent(e);
}
@Override
public void mouseEntered(MouseEvent e) {
parent.dispatchEvent(e);
}
@Override
public void mouseExited(MouseEvent e) {
parent.dispatchEvent(e);
}
@Override
public void mousePressed(MouseEvent e) {
parent.dispatchEvent(e);
}
@Override
public void mouseReleased(MouseEvent e) {
parent.dispatchEvent(e);
}
};
JLabel label=new JLabel("This is the first Label");
label.addMouseListener(myCommonListener);
JLabel label2=new JLabel("This is the second Label");
label2.addMouseListener(myCommonListener);
//... and so on
你應該把它分派到父事件之前轉換。轉換包括向父母親屬轉換座標。
public class RedispatchingMouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener{
public void mouseClicked(MouseEvent e) {
redispatchToParent(e);
}
public void mousePressed(MouseEvent e) {
redispatchToParent(e);
}
public void mouseReleased(MouseEvent e) {
redispatchToParent(e);
}
public void mouseEntered(MouseEvent e) {
redispatchToParent(e);
}
public void mouseExited(MouseEvent e) {
redispatchToParent(e);
}
public void mouseWheelMoved(MouseWheelEvent e){
redispatchToParent(e);
}
public void mouseDragged(MouseEvent e){
redispatchToParent(e);
}
public void mouseMoved(MouseEvent e) {
redispatchToParent(e);
}
private void redispatchToParent(MouseEvent e){
Component source = (Component) e.getSource();
MouseEvent parentEvent = SwingUtilities.convertMouseEvent(source, e, source.getParent());
source.getParent().dispatchEvent(parentEvent);
}
}
鼠標事件被自動定位到有鼠標偵聽最深的部分。因此,要實現您的目標,您可以簡單地刪除JLabel上的所有鼠標偵聽器,並且它永遠不會被選爲鼠標事件的目標。
下面的代碼將在給定的組件和他們的孩子遞歸禁用鼠標監聽器:
private void disableMouseForComponent(Component... components) {
for (Component c : components) {
if (c instanceof Container) {
disableMouseForComponent(((Container) c).getComponents());
}
for (MouseListener l : c.getMouseListeners()) {
c.removeMouseListener(l);
}
for (MouseMotionListener l : c.getMouseMotionListeners()) {
c.removeMouseMotionListener(l);
}
}
}
-1'ed:你是否在意解釋原因? 這樣做是比添加派發給父級的偵聽器更好的資源。 – qwertzguy 2018-02-25 21:08:27
爲什麼你需要做到這一點(例如)? – Pete 2010-09-29 03:58:53
我有很多標籤的對象,無論第一次實際點擊哪個標籤,都應該可以拖動。現在,只有當我點擊元素的背景,而不是內部的任何標籤時,它們纔可以拖動。 – viraptor 2010-09-29 09:44:47