# Mausklick an darunterliegende Komponente weiterleiten



## MrPink (18. Okt 2010)

Hallo,

ich habe ein spezielles Problem und auch nach längerer Suche bei Google und auch hier im Forum keine Lösung finden können.

Deshalb nun meiner 1. Beitrag in diesem Forum.

Ich habe eine JTabbedPane. Dieser füge ich mit der Method addTab(String, Component) mehrere Tabs hinzu. Mit der Method setTabComponentAt(int, Component) setze ich für die Reiter ein eigenes Label.

```
JTabbedPane lTabbedPane = new JTabbedPane(JTabbedPane.NORTH, JTabbedPane.WRAP_TAB_LAYOUT);
    getContentPane().add(lTabbedPane);
    
    lTabbedPane.addTab(null, createPanel("Panel one") );
    lTabbedPane.setTabComponentAt(0, createLabel("one") );
    
    lTabbedPane.addTab(null, createPanel("Panel two") );
    lTabbedPane.setTabComponentAt(1, createLabelWithListener("two") );
```

Das funktioniert auch soweit.
Wenn ich jetzt für meinen eigenen Label einen MouseListener registriere, kommt anscheinend der Mausklick nicht mehr in dem darunter liegenden Container, in diesem Fall die JTabbedPane an.

Hier einmal der komplette Code:
	
	
	
	





```
public class TabbedPaneTest extends JFrame {
  
  
  public static void main(String[] args) {
    new TabbedPaneTest();
  }
  
  
  public TabbedPaneTest() {
    super("TabbedPaneTest");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(400, 100);
    init();
    setVisible(true);
  }
  
  
  
  private void init() {
    JTabbedPane lTabbedPane = new JTabbedPane(JTabbedPane.NORTH, JTabbedPane.WRAP_TAB_LAYOUT);
    getContentPane().add(lTabbedPane);
    
    lTabbedPane.addTab(null, createPanel("Panel one") );
    lTabbedPane.setTabComponentAt(0, createLabel("one") );
    
    lTabbedPane.addTab(null, createPanel("Panel two") );
    lTabbedPane.setTabComponentAt(1, createLabelWithListener("two") );
  }
  
  private JPanel createPanel(final String pPanelText) {
    return new JPanel() {
      public void paint(Graphics pGrp) {
        pGrp.drawString(pPanelText, 50, 20);
      }
    };
  }
  
  private JLabel createLabel(String pText) {
    JLabel lLabel = new JLabel(pText);
    return lLabel;
  }
  
  private JLabel createLabelWithListener(String pText) {
    JLabel lLabel = new JLabel(pText);
    lLabel.addMouseListener( new MouseListener() {
      public void mouseReleased(MouseEvent e) {
        Component lContainer = ((Component)e.getSource()).getParent();
        lContainer.dispatchEvent( SwingUtilities.convertMouseEvent((Component)e.getSource(), e, lContainer) );
      }
      public void mousePressed(MouseEvent e) { }
      public void mouseExited(MouseEvent e) { }
      public void mouseEntered(MouseEvent e) { }
      public void mouseClicked(MouseEvent e) { }
    });
    return lLabel;
  }

}
```

Ich habe auch schon alles mögliche mit den SwingUtilities ausprobiert, bin dabei aber leider nicht auf die richtige Lösung gestoßen.
Ich möchte eine eigene Label-Klasse haben, die die Events einfach "durchlässt" bzw. "weiterleitet".
Wie kann ich soetwas realisieren? Kann mir dan jemand einen Tipp geben?

MFG Simon


----------



## JensArpe (18. Okt 2010)

ohne mich jetzt wirklich damit befasst zu haben (habs nur mal schnell compiliert).. das Label mit dem Text scheint da was zu verdecken. Versuch mal bei Tab 2 ganz weißt rechts oder links zu klicken. Bei mir wechelts da dann nämlich den Tab.


----------



## MrPink (18. Okt 2010)

Das stimmt. Dann wechselt der Tab. Allerdings auch nur, wenn man "neben" den Label klickt. genau das ist mein Problem.
Ich möchte, dass dieser Wechsel auch passiert, wenn man "auf" den Label klickt, wie bei dem ersten Tab ("one"), bei dem kein extra Listener registriert ist.


----------



## Morl99 (19. Okt 2010)

Vermutlich wäre es am besten wenn du uns kurz beschreibst, was du erreichen möchtest. Gibt es einen bestimmten Grund, warum du einen neuen Tab nicht einfach mit einem String beschreibst? Wenn ja, wäre es vielleicht eine Lösung dem Listener des Labels ein setSelectedComponent spendierst?

Noch etwas sonnige Literatur von Oracle: How to Use Tabbed Panes

Wenn dir das nicht weiterhilft, versuch mal zu beschreiben, was du mit deinen Tabs erreichen möchtest.


----------



## Volvagia (19. Okt 2010)

Wenn du dem MouseListener wieder entfernst, bekommt das Untere wieder das Event. Ansonst wäre es unter Umständen eine einfach Möglichkeit, wenn du im Listener des Labels die Eventmethode des Panes aufrufst. Oder warscheinlich besser, das Pane bekommt den Listener und du rufst dementsprechend eine Methode des Labels auf.


----------



## MrPink (19. Okt 2010)

Danke für die bisherigen Antworten.
Leider ist mein Problem damit nicht gelöst.

Was will ich:
Ich habe eine eigene Label-Klasse, die Texte für mehrsprachigkeit von EINER Quelle bezieht (ini-Datei mit allen Texten, keine Java-Typischen Resource-Bundles!).
Das beziehen der Texte aus einer Datenbank ist in einem sogenannten Autorenmodus auch möglich.
Um genau diesen Autorenmodus geht es. Der Anwender soll im laufendem Programm die Möglichkeit haben, per Shift+Rechtsklick auf ein Label zu klicken. Dann soll sich ein Dialog öffnen, indem der Nutzer eine neue Beschriftung und einen Tooltip für dieses Label eingeben kann. Zusätzlich kann er über eine Combobox die entsprechende Sprache einstellen.
Die Informationen werden dann beim Schließen bzw. beim klick auf "Save" in die Datenbank geschrieben.
Das ganze funktioniert auch schon soweit, auch für Label auf den Tabs. Nur geht mein Mausklick nun leider nicht mehr auf den Tab durch.

Mein Wunsch ist es, ein Label zu haben, dass, egal wo es eingebettet ist (in ein JPanel, eine JTabbedPane, eine JTable, ...), MouseEvents an die darunterliegende Komponente weiterzuleiten.
Ich möchte nicht extra die entsprechende Komponente an das Label geben müssen und dieses dann direkt ansprechen. Ich dachte an eine Lösung, in der es möglich ist über die Methode getParent():Component den MouseEvent einfach weiter zu "dispatchen".

Dieser Versuch sollte aus meinem obigen Beispiel in der Implementierung der mouseReleased-Methode deutlich werden.


----------



## MrPink (19. Okt 2010)

Ich habe gerade nochmal etwas rumexperementiert.
Also zum einen ist es wohl ganz sinnvol, wenn ich alle MouseEvents weiterleite (JTabbedPane z.B. reagiert auf mousePressed und nicht auf mouseReleased) ;-).

Ich habe den Teil des "dispatchen" mal in eine seperate Metode ausgelagert. Diese Methode rufe ich jetzt jeweils in meinen mouse-Event-Methode auf:


```
private JLabel createLabelWithListener(String pText) {
    JLabel lLabel = new JLabel(pText);
    lLabel.addMouseListener( new MouseListener() {
      public void mouseReleased(MouseEvent e) {
        dispatchMyEvent(e);
      }
      public void mousePressed(MouseEvent e) {
        dispatchMyEvent(e);
      }
      public void mouseExited(MouseEvent e) {
        dispatchMyEvent(e);
      }
      public void mouseEntered(MouseEvent e) {
        dispatchMyEvent(e);
      }
      public void mouseClicked(MouseEvent e) {
        dispatchMyEvent(e);
      }
    });
    return lLabel;
  }
  
  
  private void dispatchMyEvent(MouseEvent pMEvt) {
    Component lSource = null;
    Container lParent = null;
    if(pMEvt.getSource() instanceof Component) {
      lSource = (Component)pMEvt.getSource();
      lParent = lSource.getParent().getParent();
    }
    MouseEvent lRetargetedMouseEvent = SwingUtilities.convertMouseEvent(lSource, pMEvt, lParent);
    lParent.dispatchEvent(lRetargetedMouseEvent);
  }
```
Der restliche Code ist unverändert.

Wie man sehen kann, frage ich jetzt den "Source" (MouseEvent.getSource) ZWEIMAL nach seinem Parent. Dann bekomme ich die JTabbedPane zurück und das selektieren funktioniert.

Hat einer eine Idee, warum ich zweimal nach dem Parent fragen muss? Ist das bei den Swing-Komponenten so? Funktioniert das auch noch, wenn ich mein Label z.B. in eine Zelle einer JTable packe oder auf einen JButton oder auf sonst eine Komponente?


----------



## MrPink (22. Okt 2010)

Kann mir keiner darauf eine Antwort geben.
Ich erwarte jetzt nicht, dass sich extra jemand bis zur entsprechenden Tiefe in die Swing-Komponenten einarbeitet.
Das könnte ich auch selber machen.
Ich weiß z.B., dass die Swing-Komponente noch aus anderen Komponente, u.a. den sogenannten ui-Komponente bestehen,
die für das LAF zuständig sind.
In meinem Fall mit der JTabbedPane bekomme ich eben beim ersten getParent():Component einen solches Object zurück. Vielleicht hilft das ja anderen schon mal weiter.

Ich dachte, dass vielleicht schon mal jemand anderes ein ziemlich ähnliches Problem hatte und sich schon mal in die Thematik eingearbeitet hat.
Wenn dem nicht so ist, werde ich das Thema am 29.10. als "erledigt" markieren?


----------



## Michael... (22. Okt 2010)

MrPink hat gesagt.:


> Hat einer eine Idee, warum ich zweimal nach dem Parent fragen muss?


Nur meine Vermutung einen JTabbedPane beinhaltet ja mehrere "Tab" Komponenten, mit dem ersten getParent() bekommt eben diesen Reiter und mit dem zweiten die JTabbedPane die den Reiter enthält.


----------



## N4pst3r (22. Okt 2010)

ich übersetze deinen progrmmierstil besser nicht in meinen... da steig ich nicht durch 
drum:
nimm den MouseListener vom Label, verknüpf ihn mit der tebbedPane und sobald du drauf klickst (wie auch immer) reagiert das Label (mit bestimmten events) und nach der verknüpfung der tabbedPane (mit bestimmten events).
Un dwenn du dem Label einen Listener anhängst, wie soll dann auch der container wissen das du ihn ebenfalls ansprichst?
wenn du dem Label einen Mouse Listener zuweist werden ja beim klick schon alle möglichen MouseEvents abgerufen.
schreib in die "public void mouseClicked( MouseEvent e ){}" dass dein TabbedPane aktiviert werden soll.

denn soweit ich dich verstanden hab, ist dein hauptproblem dass du die tabbedpane nicht mehr anklicken und aktivieren kannst or?


----------

