# JTree & JComboBox - Elemente übers Fenster hinaus anzeigen



## speedy_g (14. Jan 2011)

Hi,


Also folgendes Problem - weil ich grad nicht weiß, wie sich das nennt, mal eine etwas laienhafte Beschreibung. Wenn man z.B. in Eclipse in einer Baumanzeige (z.B. bei den Packages) ist oder z.B. (mal nicht Java) im Windows-Explorer links in der Ordneransicht und der aktuelle Eintrag wird durch die Fensterbegrenzung rechts abgeschnitten - wenn ich nun mit der Maus drüber gehe, dann wird die Anzeige für diesen Eintrag über das Fenster hinaus verlängert.

Wie schalte ich das beim JTree ein ? Ich bin der Meinung in C# oder der MVC war das nur ein "enable", was ich irgendwo setzen mußte - aber im JTree will sich nichts passendes von mir finden lassen.


Und jetzt zur JComboBox - genau das verhalten hätte ich auch gerne in der aufgeklappten ComboBox  - also wenn die Einträge zu lang sind, daß mir dann beim Rüberfahren mit der Maus die Einträge komplett "verlängert" angezeigt werden. Wie kann ich das da hinbekommen ? (vermutlich hier nur mit nem Tooltip ? - aber wie bekomme ich zu der Zeit an die Stelle ein Tooltip und immer exakt über den aktuellen Eintrag ?)


MFG
speedy


----------



## KrokoDiehl (14. Jan 2011)

Hallo.
Also für einen _JTree_ ist mir hier eine derartige Funktionalität (außer der Umweg über einen Tooltip) nicht bekannt. Das Darstellen der Einträge im Tree übernimmt ein Renderer (TreeCellRenderer (Java Platform SE 6)). Hier könnte man mal probieren einen eigenen zu setzen und mit seiner Größe herumzuspielen, wenn der Eintrag selektiert ist. 
Könnte etwas knifflig werden 

Einen Tooltip im _JTree_ musst du auch über den Renderer setzen, das sieht dann etwa wie folgt aus:

```
public Component getTreeCellRendererComponent(...)
{
    //... Render-Komponente holen

    comp.setTooltTip( value.toString() );
    return comp;
}
```

Bei einer _JComboBox_ ist es halt so, dass das Popup der ComboBox so eingestellt wird, dass es so breit ist, wie die Combobox selbst. Man müsste also bei der Combobox selbst schauen, ob man an ihr Popup herankommt oder ein eigenes setzen kann, damit man hier mit der Größe arbeiten kann.
Vielleicht geht es aber auch hier über einen Renderer, denn die Combobox hat die Methode 
	
	
	
	





```
setRenderer()
```
.


----------



## speedy_g (14. Jan 2011)

Ja ein Tooltip - wäre halt die Workaroundvariante, aber nicht die schöne.  Kann ich einem Tooltip eine Position zuweisen, so daß ich es exakt über den Eintrag legen könnte ?

Aber selbst das möchte er bei mir nicht anzeigen.

Ich mach folgendes im getTreeCellRendererComponent:


```
Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        
((JComponent)component).setToolTipText( value.toString() );

return component;
```


MFG
speedy


----------



## KrokoDiehl (14. Jan 2011)

Die Position vom Tooltip bestimmt der Mauscursor. Ich habe außer dem Standardzeugs noch nichts mit Tooltips gemacht um zu schauen, ob und was man hier alles modifizieren kann. 
Jede _JComponent_ hat z.B. die Methode 
	
	
	
	





```
createToolTip()
```
, vielleicht kann man durch überschreiben dieser mehr erreichen?

Ach so, und bei JTrees muss man folgende Zeile aufrufen (warum auch immer):

```
ToolTipManager.sharedInstance().registerComponent( myJTree );
```


----------



## speedy_g (14. Jan 2011)

Also das "normale" ToolTip anzeigen funktioniert jetzt.

Jetzt wäre natürlich eine Positionierung genau beim/über/auf dem jeweiligen Eintrag noch ganz nett.

Das mit dem createToolTip funktioniert nicht, weil in dem jedesmal ein neues ToolTip erstellt wird und ein Setzen der Position wird einfach mißachtet/überschrieben.

Jetzt hab ich rausgefunden, daß die Componente JTree selber dafür zuständig ist, wo das ToolTip plaziert wird - also die Methode mal in der Initialisierung überschrieben.


```
jTree = new JTree(treeModel)
						{
							public Point getToolTipLocation(MouseEvent e)
							{
								Component component = this.getComponentAt( e.getPoint() );
								
							    return component.getLocation();
							}
						};
```

Funktioniert soweit, daß das ToolTip jetzt immer an Position 0,0 angezeigt wird, da component.getLocation() immer für x und y 0 zurück gibt. (das scheint das JTree-Objekt zu sein, was da zurück kommt)

Jetzt ist natürlich die Frage - wie bekomme ich dem JTree die wirkliche Position des aktuellen Nodes entlockt ? - also beginnend nach dem Icon vom Node.


MFG
speedy


----------



## André Uhres (15. Jan 2011)

Hallo speedy,

die Methode "getRowForLocation(int x, int y)" kann dir sicher weiterhelfen:

```
public Point getToolTipLocation(final MouseEvent event) {
    int xm = event.getX();
    int ym = event.getY();
    int row = getRowForLocation(xm, ym);
    TreeNode value = (TreeNode) getPathForRow(row).getLastPathComponent();
    JLabel comp = (JLabel) getCellRenderer().getTreeCellRendererComponent(
            this, value, false, false, value.isLeaf(), row, false);
    Point loc = getRowBounds(row).getLocation();
    loc.x += comp.getIcon().getIconWidth();
    loc.x += comp.getIconTextGap();
    return loc;
}
```
Gruß,
André


----------



## speedy_g (16. Jan 2011)

Cool, das funktioniert. 

Jetzt wollte ich das bei der ComboBox genauso machen. Einmal also das getListCellRendererComponent überschrieben, um den ToolTip zu setzen - funktioniert. Ein getToolTipLocation hat die ComboBox auch. Aber die ComboBox hat kein getRowForLocation oder ähnliches, soweit ich es gesehen habe.

Wie kann ich also bei der ComboBox den Index für eine bestimmte Mausposition rausbekommen ?


MFG
speedy


----------



## André Uhres (17. Jan 2011)

Hallo speedy,

ich denke, die folgende Seite wird dir weiterhelfen: Tips and Tricks for JTree, JList and JCombobox Part I | Java

Gruß,
André


----------



## speedy_g (17. Jan 2011)

Hi,

das ist ja im Prinzip das, was ich haben möchte. Aber ich habe trotzdem mal versucht mit Hilfe der Sourcen die eigene Variante (den normalen ToolTips eine andere Location zu geben) zu erweitern.

Aber irgendwo ist da ein Denkfehler drin.

Jenes getToolTipLocation ist in "MyComboBox".


```
public Point getToolTipLocation(MouseEvent mouseEvent)
	{
		Point location = null;
		
		if(isPopupVisible())
		{

			//MyComboBoxUI habe ich auch noch erstellt, aber implementiert nur die Methode getPopup(), die das
			//vorhandene popup-Objekt zurück gibt
			MyComboBoxUI myComboBoxUI = (MyComboBoxUI)getUI();
						
			if(myComboBoxUI != null)
			{
				
				ComboPopup comboPopup = myComboBoxUI.getPopup();
				
				if(comboPopup != null)
				{
					JList list = comboPopup.getList();
				
					if(list != null)
					{
				        JScrollPane jsp = (JScrollPane)SwingUtilities.getAncestorOfClass(JScrollPane.class, this);

				        if(jsp != null)
				        {
				        	Point p;
//							p = SwingUtilities.convertPoint(jsp, mouseEvent.getX(), mouseEvent.getY(), list);
							p = mouseEvent.getPoint();
							
							int index = list.locationToIndex( p );
							
							System.out.println( "index = "+ index );

							if(index > -1)
							{
								location = list.getCellBounds( index, index ).getLocation();
							}
				        }
					}
				}
			}
		}
		
		if(location == null)
		{
			System.out.println( "location = null" );
			
			location = super.getToolTipLocation( mouseEvent );
		}

		
		return location;
		
	}
```

In meiner Test-ComboBox sind 4 Elemente.

Im aufgeklappten Zustand - wenn ich mit der Maus über den Bereich gehe, der auch im zugeklappten Zustand da ist (also halt die ComboBox zugeklappt) - dann wird mir index=0 zurück gegeben. Wenn ich auf das Popup - also den aufgeklappten Bereich - gehe, dann wird mir index=1 zurückgegeben, wenn ich den Bereich "betrete". Danach wird die Methode nicht mehr aufgerufen - es wird also weder ein neuer Index noch ein "location=null" ausgegeben. (bzw. - solange ich im ersten Eintrag bin, wird mir manchmal auch öfter noch ein index=1 ausgegeben - aber ab dem 2. Eintrag dann definitiv nichts mehr) Ich hatte auch immer nach den "if != null" - er wird also auch nicht irgendwo vorher gestoppt, weil irgendwas null ist.


Wenn ich die Variante mit dem "convertPoint" nehme, dann wird mir der ToolTip weiterhin immer unter der Maus angezeigt. Wenn ich einfach nur den Punkt aus dem Mausevent nehme, dann wird mir in der ComboBox der ToolTip genau über der ComboBox mit dem Startpunkt "links oben in der Ecke" angezeigt, weil er nen Punkt 0,0 errechnet wird - das ist aber auch nicht zentriert (also auf der y Achse) über der Schrift und wenn ich das erste Mal in den aufgeklappten Bereich wechsel, dann wird mir auch der ToolTip "links oben in der Ecke" als Startpunkt vom aufgeklappten Bereich angezeigt* - also auch nicht zentriert über dem ersten Eintrag. Wenn ich dann zum zweiten, dritten etc. Eintrag gehe, wird der richtige ToolTip wieder unterhalb der Maus angezeigt und wenn ich dann zum ersten Eintrag gehe, wird der ToolTip auch unterhalb angezeigt.


*Ich bin mir nicht wirklich sicher, ob er da schon wirklich weiß, daß er über dem ersten Eintrag ist - es wird zwar index=1 ausgegeben, aber ich bin zu dem Zeitpunkt mit der Maus noch so halb (also auf dem Rand) in der ComboBox und noch nicht im aufgeklappten Bereich. Wenn ich tiefer im aufgeklappten Bereich bin, dann wird der ToolTip vom ersten Eintrag auch nochmal unter der Maus angezeigt.



Jetzt kann man auf der verlinkten Seite von Andre ja auch lesen, daß wenn man in einer ComboBox auch für jeden Eintrag ein ToolTip haben möchte, daß man dann im MyComboBoxUI eine Klasse MyComboPopup erstellen und im createPopup zurück geben soll und im Konstruktor vom MyComboPopup deren ViewToolTip.Register aufrufen soll. Also habe ich im Konstruktor mal das ToolTipManager.sharedInstance().registerComponent( list ); aufgerufen und auch ein getToolTipLocation in das MyComboPopup eingebaut. Der Konstruktor wird auf gerufen, aber das getToolTipLocation später dann nicht.



MFG
speedy


----------



## speedy_g (23. Jan 2011)

Hat niemand noch ne Idee, was ich da noch anderes probieren könnte, um es zum Funktionieren zu bringen ?


MFG
speedy


----------

