# Fragen zu JList



## Gayson (1. Okt 2004)

Hallo!

Ich habe ein paar Fragen zur JList, vielleicht könnt ihr sagen, ob diese umsetzbar sind:
1. Kann man einen einzelnen Eintrag eine bestimmte Farbe zuweisen? Wenn ja, wie?
2. Kann man einen einzelnen Eintrag unauswählbar/ unselektierbar machen?
3. Kann man eine Art Linie zwischen zwei Spalten/ Reihen ziehen (mit "-----" hab ich es schon ausprobiert, sieht bescheiden aus...)?

Wollt euch auch mal sagen, dass dieses Forum spitze für jemanden wie mich ist, der sich langsam in Java reinfummeln muss! Hier wuird mir eigentlich immer geholfen! Danke an alle!


----------



## Beni (1. Okt 2004)

Zum selektieren: schreib Dir ein eigenes ListSelectionModel, da kannst du dann selbst definierten, was selektiert wird, und was nicht.

Und zum Aussehen der einzelnen Zellen: da kannst du ein ListCellRenderer  implementieren. Dann bist du selbst für das Zeichnen verantwortlich.


----------



## Gayson (1. Okt 2004)

Kannst du mir mal ganz kurz das mit dem ListSelectionModel zeigen? Ich habe zwar schon das ListSelectionModel benutzt (SINGLE_SELECTION), aber ich schaff es z.B. nicht, dass jedoch nicht "Kai" auswählbar ist...


```
dienstplanList.setLayoutOrientation(JList.VERTICAL_WRAP);
			dienstplanList.setVisibleRowCount(v.size()+1); //+1 fürs Datum
			dienstplanList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			DefaultListModel listModel = new DefaultListModel();
			listModel.addElement("Kai");
			listModel.addElement("Jan");
			listModel.addElement("Johannes");
			listModel.addElement("´Wolfram");
			listModel.addElement("Uwe");
			dienstplanList.setModel(listModel);
```

Danke!!!


----------



## Beni (1. Okt 2004)

Du musst eine ganz neue Klasse schreiben, die das macht:

Das hier ist nur ein kleiner Ausschnitt, mit etwas Pseudocode:

```
public class ExcludingSelectionModel implements SelectionModel{

  [...]

  public void insertIndexInterval(int index, int length, boolean before){
    for( Alle Elemente von index bis index+length )
      if( Element i ist selektierbar )
        Element i selektieren
      else
        Element i überspringen
  }
}
```

Vielleicht kannst du auch vom "DefaultListSelectionModel" erben, und dort die wichtigen Methoden überschreiben/verändern.


----------



## Gayson (2. Okt 2004)

Hab ich das so richtig verstanden?


```
class ExcludingSelectionModel implements ListSelectionModel{
	public void insertIndexInterval(int index, int length, boolean selectionable){
		for(int i=index; i<=index+length; i++){
			if(selectionable==true)
				JList.setSelectedIndex(i);
			// else do nothing
		}
	}
}
```

Die Zeile "JList.setSelectedIndex(i);" ist ja definitiv falsch, wie schaff ich es, dass aus dieser Klasse heraus meine Jlist angesprochen wird?
Das Problem ist ja jetzt auch noch, dass ich jede einzelne Methode des ListSelectionModel einzeln überschreiben müsste, oder kann man das irgendwie umgehen?


----------



## Beni (2. Okt 2004)

Ein ListSelectionModel lagert sozusagen einige Methoden der JList aus, d.h. die JList ruft diese Methoden auf, und du musst die Selektion im Model speichern.

Du setzt einer JList das Model:

```
JList list = ...
list.setSelectionModel( new ExcludingSelectionModel() );
```

Und ab diesen Zeitpunkt ist das Model für das speichern der Elemente verantwortlich. Du musst also z.B. ein Vector in deinem Model haben, in welchem alle selektierten Objekte gespeichert werden.



```
class ExcludingSelectionModel implements ListSelectionModel{
  private boolean[] selected = ... // Ein Boolean-Array ist eine Möglichkeit.
  // Das braucht relativ viel Speicherplatz, dafür ist es einfach zu benutzen.

   public void insertIndexInterval(int index, int length, boolean selectionable){
      for(int i=index; i<=index+length; i++){
         if(selectionable==true)
           selected[ i ] = true; // Element i ist selektiert. Das wird nun im Model gespeichert.
         // else do nothing
      }
   }

   public boolean isSelectedIndex( int index ){
     return selected[ index ];
   }
}
```


----------



## Gayson (2. Okt 2004)

Tschuldige wegen meinen dummen Fragen Ich habe mich irgendwie noch nicht ganz in das Klassen-Thema eingearbeitet, find das grad etwas verwirrend:

1. Wie fülle ich denn das Vektor-Boolean mit true und false? Und soweit ich verstanden habe, "sammelt" dieser Vektor doch von jedem JList-Eintrag, ob der im Moment selektiert ist oder nicht, oder? Bräuchte man dann nicht noch einen Vektor, der zu jedem JList-Eintrag speichert, ob man den selektieren kann?
2. Und ist die Methode insertIndexInterval dazu da, um anzugeben, welche JList-Einträge selektierbar sind?

Vielen Dank, Benni, für deine Antworten, finds wirklich nett, dass du mir hilfst!


----------



## Beni (2. Okt 2004)

> 1. Wie fülle ich denn das Vektor-Boolean mit true und false? Und soweit ich verstanden habe, "sammelt" dieser Vektor doch von jedem JList-Eintrag, ob der im Moment selektiert ist oder nicht, oder? Bräuchte man dann nicht noch einen Vektor, der zu jedem JList-Eintrag speichert, ob man den selektieren kann?


Nun, der Witz (oder auch das Problem) ist, dass Du selbst entscheiden kannst/musst, _wie_ du genau speichern willst, welche Elemente selektiert sind. Die JList wird einfach nur die Methoden aufrufen, die das Interface vorgibt.

Also, das mit dem speichern der Zustände, da gibt es verschiedene Varianten...

Eine Liste. Wenn was selektiert wird, fügst du die Indices der Liste hinzu. (Stichwort Wrapperklasse java.lang.Integer). Wenns nicht mehr selektiert ist, entfernst du die Indices von der Liste. (Eine sortierte Liste kann da übrigens viel Zeit beim suchen ersparren :wink: )
Du machst einen riesigen boolean-Array, der für jedes Element angibt  selektiert/nicht selektiert.
Dann wirst du sowas schreiben können "boolean elementXSelektiert = booleanArray[ indexVonElementX ];"

Und ja, die nicht-selektierbaren Elemente musst du auch noch irgendwo speichern. (Aber vielleicht kannst du das ja direkt _in_ den Elementen speichern, dann muss das Model nur die Elemente abfragen "he du, bist du selektierbar?").



> 2. Und ist die Methode insertIndexInterval dazu da, um anzugeben, welche JList-Einträge selektierbar sind?


Diese Methode wird durch das Interface "ListSelectionModel" vorgeschreiben, und was sie _genau_ machen soll, kannst du in der API nachlesen.


----------



## Gayson (5. Okt 2004)

Oh mannoman, habe mich jetzt noch mal ne Stunde hingesetzt, bin immer noch nicht weiter. Habe immer noch Verstehensprobleme:

1. Hatte das schon mal gefragt: Der Kompiler will, das jede einzelne Methode vom ListSelectionModel neu geschrieben wird, muss/ sollte ich das machen?
2. Die Api schreibt zu insertIndexInterval: "Insert length indices beginning before/after index. This is typically called to sync the selection model with a corresponding change in the data model." Hatte mir dazu auch die deutsche Übersetzung angeschaut, hat mir aber nicht weiter geholfen. Wie soll nun diese Methode, wenn die fertig ist, verwendet werden? Soll sie bei einer Liste bestimmen, welche Elemente selektiert werden dürfen? Ich versteh echt nur Bahnhof....


----------



## Beni (6. Okt 2004)

Vielleicht hilft dir folgendes Beispiel eines ListSelectionListeners, der jedes zweite Element nicht selektiert.

Aber wenn du dir selbst sowas zusammenschreibst, ist es wahrscheinlich einfacher von DefaultListSelectionModel zu erben, und nur die wichtigen Methoden zu überschreiben.


```
/*
 * Created on 23.06.2004
 */
package forum;

import java.util.TreeSet;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class Editor {
	public static void main( String[] args ){
		
		JList list = new JList( new String[]{ "A", "B", "C", "D", "E", "F", "G",
				"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
				"U", "V", "W", "X", "Y", "Z"} );
		
		list.setSelectionModel( new Selection() );
		
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		
		frame.getContentPane().add( new JScrollPane( list ) );
		frame.pack();
		frame.setLocationRelativeTo( null );
		frame.setVisible( true );
	}
}

class Selection implements ListSelectionModel{
	private TreeSet selected = new TreeSet();
	private Vector listener = new Vector();
	private boolean adjusting = false;
	private int anchor = -1, lead = -1;
	
	public boolean isSelectable( int index ){
		return index % 2 == 0;
	}
	
	public void setSelectionInterval(int index0, int index1) {
		boolean old = adjusting;
		adjusting = true;
		clearSelection();
		adjusting = old;
		
		setAnchorAndLead( index0, index1 );
		
		addSelectionInterval( index0, index1 );
	}

	public void addSelectionInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			if( isSelectable( i ))
				selected.add( new Integer( i ));
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ) );
	}

	public void removeSelectionInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			selected.remove( new Integer( i ));
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ) );
	}

	public int getMinSelectionIndex() {
		if( isSelectionEmpty() )
			return -1;
		else
			return ((Integer)selected.first()).intValue();
	}

	public int getMaxSelectionIndex() {
		if( isSelectionEmpty() )
			return -1;
		else
			return ((Integer)selected.last()).intValue();
	}

	public boolean isSelectedIndex(int index) {
		return selected.contains( new Integer( index ) );
	}

	public int getAnchorSelectionIndex() {
		return anchor;
	}

	private void setAnchorAndLead( int anchor, int lead ){
		boolean old = adjusting;
		adjusting = true;
		
		setAnchorSelectionIndex( anchor );
		setLeadSelectionIndex( lead );
		
		adjusting = old;
	}
	
	public void setAnchorSelectionIndex(int index) {
		if( anchor != index ){
			anchor = index;
			
			fireValueChanged( new ListSelectionEvent( this, Math.min( anchor, index )-1, 
					Math.max( anchor, index )+1, adjusting ) );
		}
	}

	public int getLeadSelectionIndex() {
		return lead;
	}

	public void setLeadSelectionIndex(int index) {
		if( lead != index ){
			lead = index;
			
			fireValueChanged( new ListSelectionEvent( this, Math.min( lead, index )-1, 
					Math.max( lead, index )+1, adjusting ) );
		}
	}

	public void clearSelection() {
		if( !isSelectionEmpty() ){
			int max = getMaxSelectionIndex();
			int min = getMinSelectionIndex();
			selected.clear();
			
			setAnchorAndLead( -1, -1 );
			
			fireValueChanged( new ListSelectionEvent( this, min, max, adjusting ) );
		}
	}

	public boolean isSelectionEmpty() {
		return selected.isEmpty();
	}

	public void insertIndexInterval(int index, int length, boolean before) {
		if( before )
			addSelectionInterval( index-1, index-2+length );
		else
			addSelectionInterval( index+1, index+length );
	}

	public void removeIndexInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			selected.remove( new Integer( i ) );
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ));
	}

	public void setValueIsAdjusting(boolean valueIsAdjusting) {
		adjusting = valueIsAdjusting;
	}

	public boolean getValueIsAdjusting() {
		return adjusting;
	}

	public void setSelectionMode(int selectionMode) {
	}

	public int getSelectionMode() {
		return MULTIPLE_INTERVAL_SELECTION;
	}

	protected void fireValueChanged( ListSelectionEvent event ){
		for( int i = 0, n = listener.size(); i<n; i++ )
			((ListSelectionListener)listener.get(i)).valueChanged( event );
	}
	
	public void addListSelectionListener(ListSelectionListener x) {
		listener.add( x );
	}

	public void removeListSelectionListener(ListSelectionListener x) {
		listener.remove( x );
	}
}
/*
 * Created on 23.06.2004
 */
package forum;

import java.util.TreeSet;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class Editor {
	public static void main( String[] args ){
		
		JList list = new JList( new String[]{ "A", "B", "C", "D", "E", "F", "G",
				"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
				"U", "V", "W", "X", "Y", "Z"} );
		
		list.setSelectionModel( new Selection() );
		
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		
		frame.getContentPane().add( new JScrollPane( list ) );
		frame.pack();
		frame.setLocationRelativeTo( null );
		frame.setVisible( true );
	}
}

class Interval{
	private int lower, upper;
	
	public Interval(){
	}
	
	public Interval( int lower, int upper ){
		setLower( lower );
		setUpper( upper );
	}
	
	public int getLower() {
		return lower;
	}
	public void setLower(int lower) {
		this.lower = lower;
	}
	public int getUpper() {
		return upper;
	}
	public void setUpper(int upper) {
		this.upper = upper;
	}
}

class Selection implements ListSelectionModel{
	private TreeSet selected = new TreeSet();
	private Vector listener = new Vector();
	private boolean adjusting = false;
	private int anchor = -1, lead = -1;
	
	public boolean isSelectable( int index ){
		return index % 2 == 0;
	}
	
	public void setSelectionInterval(int index0, int index1) {
		boolean old = adjusting;
		adjusting = true;
		clearSelection();
		adjusting = old;
		
		setAnchorAndLead( index0, index1 );
		
		addSelectionInterval( index0, index1 );
	}

	public void addSelectionInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			if( isSelectable( i ))
				selected.add( new Integer( i ));
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ) );
	}

	public void removeSelectionInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			selected.remove( new Integer( i ));
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ) );
	}

	public int getMinSelectionIndex() {
		if( isSelectionEmpty() )
			return -1;
		else
			return ((Integer)selected.first()).intValue();
	}

	public int getMaxSelectionIndex() {
		if( isSelectionEmpty() )
			return -1;
		else
			return ((Integer)selected.last()).intValue();
	}

	public boolean isSelectedIndex(int index) {
		return selected.contains( new Integer( index ) );
	}

	public int getAnchorSelectionIndex() {
		return anchor;
	}

	private void setAnchorAndLead( int anchor, int lead ){
		boolean old = adjusting;
		adjusting = true;
		
		setAnchorSelectionIndex( anchor );
		setLeadSelectionIndex( lead );
		
		adjusting = old;
	}
	
	public void setAnchorSelectionIndex(int index) {
		if( anchor != index ){
			anchor = index;
			
			fireValueChanged( new ListSelectionEvent( this, Math.min( anchor, index )-1, 
					Math.max( anchor, index )+1, adjusting ) );
		}
	}

	public int getLeadSelectionIndex() {
		return lead;
	}

	public void setLeadSelectionIndex(int index) {
		if( lead != index ){
			lead = index;
			
			fireValueChanged( new ListSelectionEvent( this, Math.min( lead, index )-1, 
					Math.max( lead, index )+1, adjusting ) );
		}
	}

	public void clearSelection() {
		if( !isSelectionEmpty() ){
			int max = getMaxSelectionIndex();
			int min = getMinSelectionIndex();
			selected.clear();
			
			setAnchorAndLead( -1, -1 );
			
			fireValueChanged( new ListSelectionEvent( this, min, max, adjusting ) );
		}
	}

	public boolean isSelectionEmpty() {
		return selected.isEmpty();
	}

	public void insertIndexInterval(int index, int length, boolean before) {
		if( before )
			addSelectionInterval( index-1, index-2+length );
		else
			addSelectionInterval( index+1, index+length );
	}

	public void removeIndexInterval(int index0, int index1) {
		int a = Math.min( index0, index1 );
		int b = Math.max( index0, index1 );
		
		for( int i = a; i <= b; i++ )
			selected.remove( new Integer( i ) );
		
		setAnchorAndLead( index0, index1 );
		
		fireValueChanged( new ListSelectionEvent( this, index0, index1, false ));
	}

	public void setValueIsAdjusting(boolean valueIsAdjusting) {
		adjusting = valueIsAdjusting;
	}

	public boolean getValueIsAdjusting() {
		return adjusting;
	}

	public void setSelectionMode(int selectionMode) {
	}

	public int getSelectionMode() {
		return MULTIPLE_INTERVAL_SELECTION;
	}

	protected void fireValueChanged( ListSelectionEvent event ){
		for( int i = 0, n = listener.size(); i<n; i++ )
			((ListSelectionListener)listener.get(i)).valueChanged( event );
	}
	
	public void addListSelectionListener(ListSelectionListener x) {
		listener.add( x );
	}

	public void removeListSelectionListener(ListSelectionListener x) {
		listener.remove( x );
	}
}
```


----------



## Gayson (6. Okt 2004)

was meinst du denn mit "wichtigen Methoden"? Diejenigen, die ich benutze, oder wovon ist das abhängig.

Danke!!


----------



## Beni (6. Okt 2004)

In deinem Fall sind es all die Methoden, die sich ein bisschen anders verhalten. Also setSelectionInterval, addSelectionInterval und insertIndexInterval.


----------



## Gayson (12. Okt 2004)

Nicht böse sein, habs jetzt doch anders gemacht, war mir irgendwie zu schwer 

Hab nen ListSelectionListener genommen, der einen Eintrag nicht auswählt, wenn er zwischen 1 und 31 liegt:

```
dienstplanList.addListSelectionListener(new ListSelectionListener() {
														public void valueChanged( ListSelectionEvent e ) {
															int selectedIndex = dienstplanList.getSelectedIndex();
															String selectedValue = dienstplanList.getSelectedValue().toString();
															for (int i=1; i<=31; i++){
																final Integer iInteger = new Integer(i);
																String iString = iInteger.toString();
																if (selectedValue.equals(iString)){
																	dienstplanList.setSelectedIndex(selectedIndex+1);
																}
															}
														}
													});
```

Vielen lieben Dank trotzdem!!!!


----------

