1

I have a list of elements that in turn are lists of elements:

{{entity1, entity2}, {}, {entity3}, {entity4}, {entity5, entity6, entity7}, {}, ...}

I want to convert this list to a JTable. The list is 36 long, which should translate to a table of 6 by 6. Let's assume that the above example is a table of 3x2, the result'd be:

_______________________________
| entity1 |         | entity3 |
| entity2 |         |         |
|_________|_________|_________|
| entity4 | entity5 |         |
|         | entity6 |         |
|         | entity7 |         |
|_________|_________|_________|

Side note, each entity is an object itself (e.g. employee object), and I'd want to output only a specific property of the entities (e.g. .firstName or something similar). Maybe this can be done with .map? But unfortunately I'm not all too familiar with that.

What I got so far, is a loop for the initial list. Let's assume the outer list is called location (i.e. 36 locations) and the inner elements are employees on specific locations. (In practice the entities are in an arraylist, and the locations in an array.) This is untested, but it seems easy enough that it should work? (Please tell me if it's not.)

Location[] locations; // 36 locations
Location[][] locations2d; // new array 6x6
for(int x = 0; x < 6; x++) {
  for(int y = 0; y < 6; y++) {
    locations2d[x][y] = locations[6*x+y];
  }
}

But how do I now easily get this 2dlocations into my 6x6 JTable, considering I only want the .firstName of the entities in that list?


Trying some stuff out, I came up with this:

public Overview() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        tabbedPane.setBounds(10, 11, 414, 239);
        contentPane.add(tabbedPane);

        // Create new scrollpane
        JScrollPane scrollPaneEntityOverview = new JScrollPane();
        scrollPaneEntityOverview.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        // Set entity location data to table
        Object[][] data = locationToTable();
        JTable table = new JTable(data, null); // 1

        // Create new scrollpane, initialize with table
        JScrollPane scrollPaneMap = new JScrollPane(table);
        scrollPaneMap.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        tabbedPane.addTab("Entity overview", null, scrollPaneEntityOverview, null);
        tabbedPane.addTab("Map", null, scrollPaneMap, null);
    }

    public Object[][] locationToTable() {
        Object[][] data = new Object[6][6];
        Location[] locations = WorldMap.getInstance().getLocations();
        for (int x = 0; x < 6; x++) {
            for(int y = 0; y < 6; y++) {
                data[x][y] = locations[6*x+y];
            }
        }
        return data;
    }

As you can see, I'm trying to add the table to a scrollpane, which is part of a tabbed window. However, when trying this out the tab is empty: nothing shows. Furthermore, I also get the following NullPointerException, which links to //1 in the snippet above:

java.lang.NullPointerException
    at javax.swing.JTable$1.getColumnCount(Unknown Source)
    at javax.swing.JTable.createDefaultColumnsFromModel(Unknown Source)
    at javax.swing.JTable.tableChanged(Unknown Source)
    at javax.swing.JTable.setModel(Unknown Source)
    at javax.swing.JTable.<init>(Unknown Source)
    at javax.swing.JTable.<init>(Unknown Source)
    at javax.swing.JTable.<init>(Unknown Source)
    at game.Overview.<init>(Overview.java:59)
    at game.Overview$1.run(Overview.java:29)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239
  • *"I want to convert this list to a jTable."* Does not seem a good fit for a `JTable` (also note the case of class name). – Andrew Thompson Jan 02 '16 at 11:19
  • @AndrewThompson Edited the case. But why isn't it a good fit? – Bram Vanroy Jan 02 '16 at 11:20
  • 1
    Because it is (fundamentally) for multiple rows of a single entity. Everything about table has been specialized for showing rows each devoted to aspects or properties of that one record. – Andrew Thompson Jan 02 '16 at 11:30
  • @AndrewThompson Well, in a way it is: each cell is a location with a coordinate (0,0 etc.) and at that location there are employees. What else would you propose? – Bram Vanroy Jan 02 '16 at 11:36
  • 1
    If you have a look at the [`DefaultTableModel`'s constructor](https://docs.oracle.com/javase/7/docs/api/javax/swing/table/DefaultTableModel.html#DefaultTableModel(java.lang.Object[][],%20java.lang.Object[])), you will see that you can simply pass a 2D array of data (in the form of row/columns). See [How to use tables](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html) for more details – MadProgrammer Jan 02 '16 at 11:39
  • @MadProgrammer I tried some stuff out, but I run into some issues. First of all a NullPointerexception, and second : well, nothing happens! There's no data shown in the table. – Bram Vanroy Jan 02 '16 at 13:36
  • Also, you shouldn't have a variable name start with a number `2dlocations` change it to `locations2d` for example, this could lead to some problems in the future. – Frakcool Jan 02 '16 at 16:14
  • @Frakcool Thanks, edited. – Bram Vanroy Jan 02 '16 at 16:16
  • 1
    Stop using a null layout, this can lead to more problems, instead try with a [Layout Manager](https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) or combinations of them. See [Null Layout is Evil](http://www.fredosaurus.com/notes-java/GUI/layouts/nulllayout.html) and [Why is it frowned upon to use a null layout](http://stackoverflow.com/questions/6592468/why-is-it-frowned-upon-to-use-a-null-layout-in-swing) – Frakcool Jan 02 '16 at 16:20
  • For better help sooner please post an [MCVE](http://stackoverflow.com/help/mcve) with hardcoded values and no dependencies, which we can copy-paste and see the same issues as you, following my above recommendations, this will get you more and better responses and less confusion – Frakcool Jan 02 '16 at 16:29
  • @BramVanroy You will need to supply columns, otherwise the `JTable` will display nothing – MadProgrammer Jan 02 '16 at 19:02

1 Answers1

2

As shown in Creating a Table Model, this is a good case for extending AbstractTableModel. For some arbitrary Entity,

class Entity extends Object {…}

model your data a list of lists:

class EntityModel extends AbstractTableModel {

    public EntityModel(List<List<Entity>> data) {
        this.data = data;
    }

    List<List<Entity>> data;

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public int getColumnCount() {
        return data.get(0).size();
    }

    @Override
    public Object getValueAt(int row, int col) {
        List list = data.get(row);
        return list.get(col);
    }

Override getColumnName() as desired. A complete example is shown here. Refine the appearance of each cell using a suitable renderer as required, for example.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045