JTable - nur eine Zeile markierbar, nicht editierbar

Hallo an alle,

ich bins noch einmal!
Ich hab folgendes Problem mit einem JTable:

Ich möchte, dass…A) immer nur ein Zeile markierbar ist
B) die Felder nicht editierbar sind (hab ich auf verschiedene Weisen probiert)
C) eine Scrollpane angefügt wird (das hab ich probiert wie in vielen Beispielen; hat nicht geklappt)
D) die Anzahl der Zeilen minimiert werden kann (ist das überhaupt möglich?)

Ich bin dankbar für jede Antwort!

Gruß
Sponge
Hier mein Code:


class VokabelnEditieren extends JDialog{
    String[] columnNames={"Deutsch","Englisch"};
    String[][] data;
    JTable table;
    TableModel model;
(...)
    public VokabelnEditieren(Steuerung pSteuerung){
        dieSteuerung=pSteuerung;
        this.setSize(500,500);
        this.setLocation(100,100);
        this.setLayout(null);
        this.setVisible(true);
(...) //Datenbankabruf
data= dieSteuerung.handleLese2DTabelleAus((String)comboBox.getSelectedItem(), 2, 3, "");
        deutsch = dieSteuerung.handleLese1DTabelleAus((String)comboBox.getSelectedItem(), 2, "");
        englisch = dieSteuerung.handleLese1DTabelleAus((String)comboBox.getSelectedItem(), 3, "");
       
(...) (Definition der Buttons und Textfelder)
        model = new DefaultTableModel(data, columnNames);
        table = new JTable(model);
        table.addMouseListener(new MouseAktion());
        table.setBounds(20,65,460,350);
        this.add(table);
        
        btHinzufuegen.addActionListener(new MenuAktion());
        btAbbrechen.addActionListener(new MenuAktion());
        btLoeschen.addActionListener(new MenuAktion());
        btEditieren.addActionListener(new MenuAktion());
        btAktualisieren.addActionListener(new MenuAktion());

        this.setResizable(false);
    }
(...) AktionListener; Mouselistener

[QUOTE=Spongee]A) immer nur ein Zeile markierbar ist
B) die Felder nicht editierbar sind (hab ich auf verschiedene Weisen probiert)
C) eine Scrollpane angefügt wird (das hab ich probiert wie in vielen Beispielen; hat nicht geklappt)
D) die Anzahl der Zeilen minimiert werden kann (ist das überhaupt möglich?)[/quote]

Zu A: Was genau meinst du bzw. was willst du erreichen?

Zu B: Könnte man so machen:

   public boolean isCellEditable(int row, int column) {
      return false;
   }
};```

Zu C: Du erzeugst eine JScrollPane und übergibst ihr als Argument deine JTable-Referenz.

Zu D: Was genau meinst du mit Zeilen minimieren?

Hallo L-ectron-X,

danke für deine schnelle Antwort!

B ist abgehackt! Ich hatte das vorher so probiert, aber es hat iwie nicht funktioniert! Dankeschön =)

Zu A: Bis jetzt ist es möglich, dass man mehrere Zeilen markieren kann! Kann man das unterbinden, dass immer nur genau eine Zeile markierbar ist?

Zu C: Das mit der ScrollPane habe ich ebenfalls probiert!

        JScrollPane scrollPane = new JScrollPane(table);
        this.add(scrollPane);

Was ist falsch? Wenn ich table add, dann fehlt die scrollepane schlicht weg…

Zu D: Ist es möglich, dass ich die Anzahl der Zeilen mit dem Hinzufügen einer neuen Zeile einfach um eins ertweiter oder minimiere, also es zunächst 10 gefüllte Zeilen sind, danach 11!

Gruß
Sponge

A) du kannst das über das SelectionModel machen
http://java.sun.com/javase/6/docs/api/javax/swing/JTable.html#getSelectionModel()

C)Ja alle Swing Componenten haben keine Scrollpane daher musst du sie explizit setzen.

D) Ja das musst du über das Model machen, wenn du dem Model eine Zeile hinzufügst dann merkt das die Tabelle und stellt alles korrekt da. Machst du das aber über die Tabelle direkt bekommt die Tabelle das nicht richtig mit. Der ordentliche Weg ist über daS Model zu gehen.

@Spongee: Aus deiner Antwort geht leider nicht hervor, ob nun Punkt C gelöst ist, oder nicht.
Vielleicht wäre noch zu sagen, dass die Scrollbalken erst angezeigt werden, wenn die in der JScrollPane eingebettete Komponente mehr Platz benötigt, als der von der JScrollPane bereitsgestellte Anzeigebereich zur Verfügung hat.

A) table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
Siehe JTable.setSelectionMode(int).

C) Diese Zeile löschen: this.add(table);
Diese Zeile an der selben Stelle einfügen: this.add(new JScrollPane(table));
Sollte das nicht funktionieren, hast Du an einer anderen Stelle einen Fehler eingebaut; zum Beispiel die table nochmals irgendwo hinzugefügt.

D) Es ist möglich. Du kannst entweder Dein Tabellenmodell erweitern (ableiten) oder einen TableModelListener an das Modell anhängen (TableModel.addTableModelListener(TableModelListener)). In beiden Fällen reagierst Du auf Veränderung des Modells und fügst dann eine neue Zeile ein (zum Beispiel wenn die letzte Zeile nicht mehr leer ist). Das könnte zum Beispiel so aussehen (ungetestet; im Browser getippt):


   @Override
   public boolean isCellEditable(int row, int column) {
      return false;
   }

   @Override
   public void setValueAt(Object val, int row, int column) {
      super.setValueAt(val, row, column);

      // if last row is edited and value is not empty; add row
      if (row == getRowCount() - 1 && val != null && val.toString().trim().length() != 0) {
        addRow(new Object[getColumnCount()]);
      }
};```
HTH, Ebenius

Hallo L-ectron-X, EagleEye und Ebenius

Danke für eure Antworten, die haben mich schon ein gutes Stück weiter gebracht!

Problem A) habe ich mit Ebenius Lösungsvorschlag gemacht, klappt einwandfrei!
Problem B) ist sowieso schon erledigt!
Problem D) habe ich ebenfalls mit Ebenius Lösungsvorschlag gemacht! Komischerweise funktioniert die addRow() nur innerhalb des Override… Hatte das bisher noch nicht so gemacht, dass man die Methoden der Konstruktoren einfach so überschreibt! Vielen dank für den Lösungsvorschlag, wieder mal was gelernt…

Problem C) besteht leider weiter hin! Ich habe mich vorher schon schlau gemacht, dass man der Scrollpane das JTable übergibt und dann die Scrollpane hinzufügt! Das klappt jedoch leider nicht! Ich hab keine Ahnung, der Fehler muss bestimmt wo anders liegen oder ich bin einfach zu blöd dafür =) Hier ist noch mal der Code… wenn ich das so ausführe, dann ist der/die/das JTable einfach weg bzw wird nicht anzeigt…

Kann sowas an dem Resizable(false) oder an meinem null-LayoutManager liegen?


(...)
model = new DefaultTableModel(data,columnNames){
            public boolean isCellEditable(int row, int column){
                return false;
            }
            public void setValueAt(Object val, int row, int column) {                  
                if (fuegeZeileHinzu==true) {
                    addRow(new Object[getColumnCount()]);
                }
                super.setValueAt(val, row, column);
                fuegeZeileHinzu=false;
            }
        };
table = new JTable(model);
table.addMouseListener(new MouseAktion());
table.setBounds(20,65,460,285);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        
this.add(new JScrollPane(table));
this.setResizable(false);
(...)

Du meinst, Du kannst auf addRow(…) nicht zugreifen, wenn Du das Modell aus der Tabelle holst? In etwa so?
table.getModel().addRow(new Object[5]); // <== compile error
Das liegt daran, dass die Methode addRow(Object[]) nicht im TableModel-Interface sondern in der Klasse ****DefaultTableModel implementiert ist. Die Tabelle weiß nicht, was sie genau für ein Modell hat, deswegen benutzt sie nur das Interface. Vorausgesetzt Du kannst sicher sein, dass die Tabelle eine bestimmte Implementierung des Modells besitzt, kannst Du das Modell in den konkreten Typ überführen (type cast): ((DefaultTableModel) table.getModel()).addRow(new Object[5]); // <== no compile error

Die Formulierung verrät, dass Du beim Verständnis noch einige Probleme hast. Hier werden sogenannte anonyme Klassen gebildet. Anonym sind sie, weil sie keinen bestimmten Namen tragen. Es wird einfach die Klasse (per Konstruktor bestimmt) erweitert. Im konkreten Fall ist addRow(Object[]) dann natürlich auch vorhanden, da der Typ nicht TableModel sondern DefaultTableModel’ ist.

Tausch mal das aus:

+ this.add(new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS));```
Wenn Du nun keine Skrollbalken siehst, liegt der Fehler ganz sicher an ganz anderer Stelle (und dann hilft auch der Quelltextausschnitt nicht weiter ;) ).

Mir helfen die Sun-Tutorials oft weiter: [ul][li][Sun Java™ Tutorial: How to Use Scroll Panes](http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html)
[/li][li][Sun Java™ Tutorial: How to Use Tables](http://java.sun.com/docs/books/tutorial/uiswing/components/table.html)[/ul]
[/li]Tipp am Rande: Ein Ausrufezeichen macht einen Satz meist nicht schöner, nicht ausdrucksstärker und nicht verständlicher. Statt dessen fühlt man sich oft angebrüllt. ;-)

Nix für ungut, Ebenius

Genau. Ein mögliches Problem habe ich bereits ins Gespräch gebracht.

Der Type Cast hat wunderbar geklappt, habe ich auch benötigt. Dankeschön =)
Ebenfalls danke für die wiederholte Erklärung der anonymen Klassen.

Zurück zum eigentlichen Problem: Die Scrollpane wird auch dann nicht sichtbar, was den Fehler woanders vermuten lässt. Die Scrollpane (dies ist an L-ectron-X) wird auf jedenfall gebraucht, es ist also nicht so, dass die Größe des JTable ausreicht. Jedoch wird die Tabelle gar nicht mehr angezeigt, wenn ich die Scrollpane zur Oberfläche hinzufüge - Klingt komisch, ist aber so… Naja ich werde mal schauen, wo der Fehler noch liegen könnte. Das Thema ist auch nicht mehr sooo aktuell.
Ich bedanke mich trotzdem bei allen, die mir geholfen haben!

Entschuldige, falls das mit den Ausrufezeichen wie ein “Angebrülle” rüber kam. Hab mir das angewöhnt, da ich es einfach…mhh… “schöner” als ein Punkt finde. Aber du hast recht: Ein Ausrufezeichen macht es echt nicht immer ausdrucksstärker oder übersichtlicher.

Im Eclipse den Cursor auf die Variable setzen, CTRL+SHIFT+G drücken, dann werden alle Referenzen gesucht. Wenn Du keine IDE benutzt: Benenn einfach die Variable an ihrer Deklaration um und kompiliere. Dann findest Du an allen Compiler-Errors potentielle Verwendungen. :slight_smile:

Happy Hacking, Ebenius

Versuch’s mal so:

scroll.setBounds(20, 65, 460, 350);
this.add(scroll);```
Besser ist es allerdings, LayoutManager zu verwenden. Mehr dazu:
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html

@Ebenius: Netter Tip zum Debuggen. Danke!

@AndreUhres: Vieeelllllllllllllllllllllleennnnnnnnnn Dank!!!
Das war die Lösung! Jetzt wird auch im Header tatsächlich die columneNames angezeigt. Perfekt! Muss wohl echt an dem Null-Layout Manager gelegen haben.

In Zukunft werde ich mich mehr mit Layout Managern auseinander setzen: Momentan war dafür leider einfach keine Zeit bzw. auch das Interesse, weil das Programm bis nächste Woche fertig hätte sein sollen.

Viel Dank noch mal an alle, dir mir geholfen haben!
Ihr seid Klasse! Thema [Erledigt]

MfG
Spongee