Compiler-Fehler JTable mit XML befüllen | The constructor JTable(Object[], String[]) is undefined

Ralon

Mitglied
Hallo,

ich habe vor Kurzem mit java angefangen. Ich versuche ein Programm zu programmieren, das eine Tabelle, ausgelesen aus einer xml-Datei, anzeigt. Später soll diese dann je nach Vorgabe des Nutzers im Programm angepasst werden können.
Ich habe die Daten auch alle in eine ArrayList laden können, nun scheitere ich jedoch daran eine Tabelle mit diesen Daten zu befüllen.
Hiermit lese ich die XML-Datei aus und speichere die Daten dann in 3 verschiedene Arraylisten (name, costs, category).
Wenn ich mir das ins Log ausgeben lasse, funktioniert das wunderbar.

[CODE lang="java" title="XML auslesen"]private static final String FILENAME = "content.xml";
LootMain(){
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File(FILENAME));
doc.getDocumentElement().normalize();
NodeList nodelist = doc.getElementsByTagName("item");
ArrayList<String> name = new ArrayList<String>();
ArrayList<Integer> costs = new ArrayList<Integer>();
ArrayList<String> category = new ArrayList<String>();

for (int temp = 0; temp < nodelist.getLength(); temp++) {
Node node = nodelist.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String id = element.getAttribute("id");
System.out.println(id);
name.add(element.getElementsByTagName("name").item(0).getTextContent());
costs.add(Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent()));
category.add(element.getElementsByTagName("category").item(0).getTextContent());
}
}[/CODE]

Nun will ich ein Fenster generieren und darin eine Tabelle erstellen, die diese ArrayList beinhaltet. Dafür füge ich die drei ArrayLists zusammen in eine einzige: data.
[CODE lang="java" highlight="9"] List<String> data = new ArrayList<String>();
data.addAll(name);
data.add(String.valueOf(costs));
data.addAll(category);
JFrame frame = new JFrame("Generator");
String[] columnNames = { "Name", "Costs", "Category" };
Object[] objdata = data.toArray();
JPanel p = new JPanel();
JTable j = new JTable(objdata, columnNames);[/CODE]


In Zeile 9 bekomme ich nun den Fehler: The constructor JTable(Object[], String[]) is undefined
Ich dachte das läge womöglich an der Variablen-Klasse, deshalb habe ich bereits versucht data in ein Object umzuwandeln. Das brachte jedoch nicht den gewünschten Erfolg.
Könnt ihr mir helfen?
Danke im Voraus!

Beste Grüße
 
Den Konstruktor gibt es auch nicht. Du wolltest vermutlich "JTable(Object[][], Object[])" verwenden.

Also die Daten kommen in ein zwei-dimensionales Array, Zeilen und Spalten. Die Namen kommen in ein normales Object-Array (wobei ich, ehrlich gesagt, gerade nicht im Kopf habe um man "String[]" einfach auf "Object[]" zuweisen kann...schande ueber mich, bin aber auch muede).
 
Den Konstruktor gibt es auch nicht. Du wolltest vermutlich "JTable(Object[][], Object[])" verwenden.

Also die Daten kommen in ein zwei-dimensionales Array, Zeilen und Spalten. Die Namen kommen in ein normales Object-Array (wobei ich, ehrlich gesagt, gerade nicht im Kopf habe um man "String[]" einfach auf "Object[]" zuweisen kann...schande ueber mich, bin aber auch muede).
Danke für deine Antwort:
Wenn ich nun anstatt: "JTable j = new JTable(objdata, columnNames);":

Java:
              Object[] columnNames = { "Name", "Costs", "Category" };
              Object[] objdata = data.toArray();
              JPanel p = new JPanel();
              public JTable(Object[][] objdata,
                      Object[] columnNames) {
                  
              }

Ich hab auf deinen Hinweis auch versucht aus columnNames ein object zu machen.
Nun bekomme ich den Error: "JTable.Object cannot be resolved to a type" sowie Illegal modifier for parameter Object; only final is permitted.

So richtig werde ich daraus leider nicht schlau.
 
Nein, du hast den Link nicht gelesen, oder? Das ist einer der Konstruktoren von "JTable", der akzeptiert zwei Argumente, einmal ein zwei-dimensionales Object-Array, und einmal ein ein-dimensionales Object-Array fuer Spaltennamen.

Java:
Object[] row1 = new Object[] { "Value 1/1", "Value 1/2", "Value 1/3" }
Object[] row2 = new Object[] { "Value 2/1", "Value 2/2", "Value 2/3" }

Object[][] data = new Object[][] { row1, row2 };
Object[] columnNames = new Object[] { "Column 1", "Column 2", "Column 3" };

JTable table = new JTable(data, columnNames);
 
Nein, du hast den Link nicht gelesen, oder? Das ist einer der Konstruktoren von "JTable", der akzeptiert zwei Argumente, einmal ein zwei-dimensionales Object-Array, und einmal ein ein-dimensionales Object-Array fuer Spaltennamen.

Java:
Object[] row1 = new Object[] { "Value 1/1", "Value 1/2", "Value 1/3" }
Object[] row2 = new Object[] { "Value 2/1", "Value 2/2", "Value 2/3" }

Object[][] data = new Object[][] { row1, row2 };
Object[] columnNames = new Object[] { "Column 1", "Column 2", "Column 3" };

JTable table = new JTable(data, columnNames);
Hey,
doch habe ich, tut mir Leid, dass ich den Eindruck erwecke dem wäre nicht so. Ich habs bloß echt nur so mäßig verstanden. Deswegen die Nachfrage. Ich habe jetzt data so aktualisiert, jetzt ist es doch zweidimensional, oder?

[CODE lang="java" highlight="25"] ArrayList<String> name = new ArrayList<String>();
ArrayList<Integer> costs = new ArrayList<Integer>();
ArrayList<String> category = new ArrayList<String>();
for (int temp = 0; temp < nodelist.getLength(); temp++) {
Node node = nodelist.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
// get item id
String id = element.getAttribute("id");
System.out.println(id);
// get text
name.add(element.getElementsByTagName("name").item(0).getTextContent());
costs.add(Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent()));
category.add(element.getElementsByTagName("category").item(0).getTextContent());
System.out.println(name);
System.out.println(costs);
System.out.println(category);
}
}
List<String> data = new ArrayList<String>();
data.addAll(name);
data.add(String.valueOf(costs));
data.addAll(category);
String[] columnNames = { "Gegenstand", "Kategorie", "Preis" };
Object[][] objdata = (Object[][]) data.toArray();
JTable j = new JTable(objdata, columnNames)[/CODE]

Leider bekomme ich nun eine Exception: For input string: value. Wenn ich das richtig verstehe, handelt es sich ja offenbar in einer meiner Variablen nicht um die richtige Form. Also entweder eine integer ist fälschlicherweise ein string oder andersherum, oder?
Ich habe dann herumprobiert in der xml-Datei, die Daten zu ändern, um herauszufinden wo der Fehler herkommt, aber das hat leider keine Besserung gebracht, der Fehler blieb derselbe.

Beste Grüße
 
Leider bekomme ich nun eine Exception: For input string: value. Wenn ich das richtig verstehe, handelt es sich ja offenbar in einer meiner Variablen nicht um die richtige Form. Also entweder eine integer ist fälschlicherweise ein string oder andersherum, oder?
Ich habe dann herumprobiert in der xml-Datei, die Daten zu ändern, um herauszufinden wo der Fehler herkommt, aber das hat leider keine Besserung gebracht, der Fehler blieb derselbe.
Zeig am besten mal den ganzen Stacktrace
 
Zeig am besten mal den ganzen Stacktrace
So sieht mein Code aus..hab gerade das meiste rauskommentiert was ich gerade nicht brauche:
Java:
package lgpackage;
import javax.swing.*;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LootMain {
    private static final String FILENAME = "content.xml";
    LootMain(){
          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
          try {
              dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
              DocumentBuilder db = dbf.newDocumentBuilder();
              Document doc = db.parse(new File(FILENAME));
              doc.getDocumentElement().normalize();
              NodeList nodelist = doc.getElementsByTagName("item");
              ArrayList<String> name = new ArrayList<String>();
              ArrayList<Integer> costs = new ArrayList<Integer>();
              ArrayList<String> category = new ArrayList<String>();
              for (int temp = 0; temp < nodelist.getLength(); temp++) {
                  Node node = nodelist.item(temp);
                  if (node.getNodeType() == Node.ELEMENT_NODE) {
                      Element element = (Element) node;
                      // get item id
                      String id = element.getAttribute("id");
                      // get text
                        name.add(element.getElementsByTagName("name").item(0).getTextContent());
                        costs.add(Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent()));
                        category.add(element.getElementsByTagName("category").item(0).getTextContent());
                  }
              }
              List<String> data = new ArrayList<String>();
              data.addAll(name);
              data.add(String.valueOf(costs));
              data.addAll(category);
            String[] columnNames = { "Gegenstand", "Kategorie", "Preis" };
            Object[][] objdata = (Object[][]) data.toArray();
            JTable j = new JTable(objdata, columnNames);
            JFrame frame = new JFrame("Loot Generator | Das schwarze Auge");
//            JPanel p = new JPanel();
              j.setRowHeight(15);
              j.setShowHorizontalLines( false );
              j.setRowSelectionAllowed( true );
              j.setColumnSelectionAllowed(false);
              JScrollPane jsp = new JScrollPane(j, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
              jsp.setPreferredSize(new Dimension(450, 200));
//              List<Integer> list = new ArrayList<>();
//              for(int i = 0;i<j.getModel().getRowCount();i++)
//              {
//                  list.add(Integer.valueOf((String) j.getModel().getValueAt(i,2)));
//              }
//             int sum = 0;
//             for(int i = 0; i < list.size(); i++) 
//             {
//                 sum += list.get(i);
//             }
//             System.out.println(sum);  
//              JLabel T_Selection = new JLabel("Was sollen die Held*innen finden dürfen?");
//              JCheckBox CB_Weapon = new JCheckBox("Waffen");
//              JCheckBox CB_Armor = new JCheckBox("Rüstung");
//              JCheckBox CB_Potion = new JCheckBox("Tränke");
//              JCheckBox CB_Herbs = new JCheckBox("Kräuter");
//              JCheckBox CB_Clothes = new JCheckBox("Kleidung");
//              JCheckBox CB_Money = new JCheckBox("Geld");
//              JCheckBox CB_Misc = new JCheckBox("Anderes");
//              JLabel T_MoneySum = new JLabel("Die gesamte Summe beläuft sich auf " + sum + " Silbertaler");
//              p.add(T_Selection);
//              p.add(CB_Weapon);
//              p.add(CB_Armor);
//              p.add(CB_Potion);
//              p.add(CB_Herbs);
//              p.add(CB_Clothes);
//              p.add(CB_Misc);
//              p.add(CB_Money);
//              p.add(jsp);
//              p.add(T_MoneySum);
//              frame.add(p);
//              frame.setSize(500,400);
//              frame.setVisible(true);
               

          } catch (ParserConfigurationException | SAXException | IOException e) {
              e.printStackTrace();
          }
      }
    public static void main(String[] args) {
        new LootMain();
}
}

Der Fehler den ich bekomme lautet:
Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [[Ljava.lang.Object; ([Ljava.lang.Object; and [[Ljava.lang.Object; are in module java.base of loader 'bootstrap')
at LootGenerator/lgpackage.LootMain.<init>(LootMain.java:51)
at LootGenerator/lgpackage.LootMain.main(LootMain.java:102)
 
Hoer' mal kurz auf mit den Listen zu spielen und baue das 2D-Array ohne Listen! Dann wuerdest du schnell merken was du brauchst und was dabei falsch laeuft.

Im Moment befuellst du drei Listen, naemlich "name", "costs", und "category", dann vereinigst du die alle in eine Liste, naemlich "data". Daran ist aber leider nichts zwei-dimensional. Also du machst jetzt mal folgendes, du baust dir pro XML-Node ein Array:

Java:
Object[] zeile = new Object[3];
zeile[0] = element.getElementsByTagName("name").item(0).getTextContent();
zeile[1] = Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent());
zeile[2] = element.getElementsByTagName("category").item(0).getTextContent();

Das ist *eine Zeile* mit mehreren Spalten. Soweit so klar? Dann koennen wir das auf die 2D-Struktur ausbauen die wir brauchen, naemlich in dem wir "zeile" in einem Array speicher:

Java:
Object[][] zeilen = new Object[500][];

for (int index = 0; index < nodelist.getLength(); index++) {
    Node node = nodelist.item(index);
    
    if (node.getNodeType() == Node.ELEMENT_NODE) {
        Element element = (Element) node;
        
        Object[] zeile = new Object[3];
        zeile[0] = element.getElementsByTagName("name").item(0).getTextContent();
        zeile[1] = Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent());
        zeile[2] = element.getElementsByTagName("category").item(0).getTextContent();
        
        zeilen[index] = zeile;
    }
}

Jetzt hast du eine zwei-dimensiale Struktur, naemlichen Object-Arrays in einem Object-Array. Der Inhalt von "zeilen" als Baum sieht jetzt so aus:

Code:
Object[]
 |- 0: Object[]
 |      |- 0: "bla"
 |      |- 1: 5485
 |      \- 2: "bla"
 |- 1: Object[]
 |      |- 0: "bla"
 |      |- 1: 5485
 |      \- 2: "bla"
 |- 2: Object[]
 |      |- 0: "bla"
 |      |- 1: 5485
 |      \- 2: "bla"
 |- 3: null
 |- 4: null
 |- 5: null
 |- 6: null
 ...

Jetzt haben wir zwar die richtige Struktur, aber das Array ist ja eine fixe Groesze, hat also zuviele Zeilen. Deswegen tauschen wir "zeilen" gegen eine "List" aus, um dies zu umgehen (wir koennten das Array auch haendisch vergroeszern...aber wer will das schon?).

Java:
List<Object[]> zeilen = new ArrayList<>();

for (int temp = 0; temp < nodelist.getLength(); temp++) {
    Node node = nodelist.item(temp);
    
    if (node.getNodeType() == Node.ELEMENT_NODE) {
        Element element = (Element) node;
        
        Object[] zeile = new Object[3];
        zeile[0] = element.getElementsByTagName("name").item(0).getTextContent();
        zeile[1] = Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent());
        zeile[2] = element.getElementsByTagName("category").item(0).getTextContent();
        
        zeilen.add(zeile);
    }
}

Der Inhalt von "zeilen" als Baum sieht jetzt so aus:

Code:
Object[]
 |- 0: Object[]
 |      |- 0: "bla"
 |      |- 1: 5485
 |      \- 2: "bla"
 |- 1: Object[]
 |      |- 0: "bla"
 |      |- 1: 5485
 |      \- 2: "bla"
 \- 2: Object[]
        |- 0: "bla"
        |- 1: 5485
        \- 2: "bla"

Jetzt muessen wir das "nur noch" in ein 2D-Object-Array uebersetzen:

Code:
Object[][] data = (Object[][])zeilen.toArray();

Und wir haben die korrekte Datenstruktur welche von "JTable" gebraucht wird.
 
Hey, riesiges Dankschön für deine Hilfe...
In der Theorie verstehe ich nun das Problem. Eine Liste kann natürlich nicht zweidimensional sein - alles klar.
Es sieht nun so aus:

Java:
          dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
          DocumentBuilder db = dbf.newDocumentBuilder();
          Document doc = db.parse(new File(FILENAME));
          doc.getDocumentElement().normalize();
          System.out.println("Root Element :" + doc.getDocumentElement().getNodeName());
          System.out.println("------");
          NodeList nodelist = doc.getElementsByTagName("item");
          List<Object[]> zeilen = new ArrayList<>();
          for (int temp = 0; temp < nodelist.getLength(); temp++) {
              Node node = nodelist.item(temp);
              
              if (node.getNodeType() == Node.ELEMENT_NODE) {
                  Element element = (Element) node;
                  Object[] zeile = new Object[3];
                  zeile[0] = element.getElementsByTagName("name").item(0).getTextContent();
                  zeile[1] = Integer.valueOf(element.getElementsByTagName("costs").item(0).getTextContent());
                  zeile[2] = element.getElementsByTagName("category").item(0).getTextContent();
                  zeilen.add(zeile);
              }
          }
        Object[][] data = (Object[][])zeilen.toArray();
        String[] columnNames = { "Gegenstand", "Kategorie", "Preis" };
        JFrame frame = new JFrame("Loot Generator");
        JTable j = new JTable(data, columnNames);

Jetzt habe ich allerdings wieder einen Error:

Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [[Ljava.lang.Object; ([Ljava.lang.Object; and [[Ljava.lang.Object; are in module java.base of loader 'bootstrap')
at LootGenerator/lgpackage.LootMain.<init>(LootMain.java:50)
at LootGenerator/lgpackage.LootMain.main(LootMain.java:96)
Ich schätze das Problem liegt bei "Object[][] data = (Object[][])zeilen.toArray(); , oder?
 

Zurück
Oben