2

I am having an unexpected behavior with the Java GUI. I want to create a JScrollPane containing a JTable then add this JScrollPane to a Frame.

Here is the code :

public class UrlsScrollPanel extends JScrollPane {
private static final long serialVersionUID = 1L;

public UrlsScrollPanel() {

    //setup urls and collections
    ArrayList<URL> urls = URL.getAll();
    ArrayList<Collection> collections = new ArrayList<>();
    for(URL url : urls) collections.add(new Collection(url));

    //table
    String[] columns = {            
        "database",
        "status",
        "consumption",
        "last snapshot date",
        "last message",
        "details",
        "stop collect"
    };  

    AbstractTableModel dataModel = new AbstractTableModel() {
        private static final long serialVersionUID = 1L;

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            System.out.printf("row: %d, column: %d \n", rowIndex, columnIndex); //is never called.
            URL url = urls.get(rowIndex);
            Collection collection = collections.get(rowIndex); 
            ArrayList<Message> lastMessages = collection.getLastSnapshot().getMessages();
            Message lastMessage = lastMessages.get(lastMessages.size() - 1);

            if(columnIndex == 0) return url.toString();
            if(columnIndex == 1) return collection.getStatus(); 
            if(columnIndex == 2) return ConsumptionChart.getChartPanel(collection);
            if(columnIndex == 3) return collection.getLastSnapshot().getDate();
            if(columnIndex == 4) return String.format("[ %s ] %s", lastMessage.getDate(), lastMessage.getBody()); 
            return "Comming soon.";
        }

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

        @Override
        public int getColumnCount() {
            return columns.length;
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    };
    JTable table = new JTable(dataModel);
    add(table);
    setBackground(Color.red);
    setSize(500, 500);
}
}

And here is how I call it :

public static void main(String[] args) {        
    JFrame frame = new JFrame();
    frame.setVisible(true);
    frame.setResizable(true);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setExtendedState(JFrame.MAXIMIZED_BOTH );
    frame.setLocationRelativeTo(null);
    UrlsScrollPanel panel = new UrlsScrollPanel();
    frame.add(panel, BorderLayout.CENTER);
    SwingUtilities.updateComponentTreeUI(frame);
}

The result is a red square blinking at the top left of the frame then disappearing immediately. Also the dataModel seems to be never called.

Any help in what I am doing wrong is much appreciated, thanks for your time!

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Guillaume Robbe
  • 658
  • 1
  • 7
  • 18

1 Answers1

2

Don't extend JScrollPane. Instead, use your table to construct a JScrollPane:

frame.add(new JScrollPane(table), BorderLayout.CENTER);

The approach is described here; a complete example is shown here; an alternative approach using setViewportView() is examined here.

Are these two not similar?

JScrollPane panel = new JScrollPane(); panel.add(table);
…
JScrollPane panel = new JScrollPane(table);

No. As shown in How a Scroll Pane Works, the first formulation adds the table directly to the JScrollPane, replacing the JViewport component that occupies the central position in the ScrollPaneLayout and that would have been used to display the table. The second formulation invokes setViewportView(table) internally, which tells the scroll pane's JViewport what component to display.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Ok, I just changed, my class is not extending JScrollPane anymore and posses a method getPanel(). However I still don't understand why my previous approach is not working. Is `JScrollPane panel = new JScrollPane(); panel.add(table);` not similar to `JScrollPane panel = new JScrollPane(table)` ? Thanks for your help! PS: there is no need to specify BorderLayout.CENTER when adding a component to a JFrame because this is the default layout. – Guillaume Robbe Jul 20 '16 at 09:12
  • Good question; I've elaborated above. – trashgod Jul 20 '16 at 12:17
  • Thanks for the explanation, it makes sense now! – Guillaume Robbe Jul 20 '16 at 15:40