vector
vector

Reputation: 379

JTable Not Redrawing When Repaint Called

Hi I am having difficulty with my data table not repainting when my timer event occurs. I am checking for player connectivity in a game I am working on making. When a player connects the JTable should change to show that a player has connected; however, the table is not changing, even though the variables populating the table are changing.

My GUI code is linked below, basically when a player is connected a string variable in the GUI code changes and then my timer should be redrawing the table every second and notice that change and redraw with the correct information. The variable is changing and I can see that output in the console, but the table will not update accordingly.

Thank you for looking.

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

@SuppressWarnings("serial")
public class DPServerGUI extends JFrame implements ActionListener
{
  private DPServerTest mainServer;

  private JPanel serverPanel;
  private JButton startButton;
  private JButton loadServerButton;
  private JLabel serverLabel;
  String[] header = {"Players", "Connected To Server"};
  private JTable connectedClientsList;
  private DefaultTableModel tableModel;
  private JScrollPane scrollPane;
  private static Dimension dim;
  private Timer timer;
  public static String player1Connected = "No";
  public static String player2Connected = "No";
  public static String player3Connected = "No";
  public static String player4Connected = "No";

  public DPServerGUI()
  {
    serverPanel = new JPanel();

    startButton = new JButton("Start Game");
    startButton.addActionListener(this);

    loadServerButton = new JButton("Load Server");
    loadServerButton.addActionListener(this);

    tableModel =  new DefaultTableModel();
    scrollPane = new JScrollPane(getTable());

    serverLabel = new JLabel("Server Not Running");
    dim = Toolkit.getDefaultToolkit().getScreenSize();

    serverPanel.add(serverLabel);
    serverPanel.add(startButton);
    serverPanel.add(loadServerButton);
    serverPanel.add(scrollPane);
    this.add(serverPanel);
  }

  private JTable getTable()
  {
    String[][] table = 
    {
        {"Player 1", player1Connected},
        {"Player 2", player2Connected},
        {"Player 3", player3Connected},
        {"Player 4", player4Connected}
    };
    connectedClientsList = new JTable(table, header);
    return connectedClientsList;
  }
  public void updatePlayerList()
  {
    String [][] playerList = mainServer.exportPlayerList();
    connectedClientsList = new JTable(playerList, header);
  }
  @Override
  public void actionPerformed(ActionEvent event)
  {
    if (event.getSource() == loadServerButton)
    {
      System.out.println("Load server clicked!");
      loadServerButton.setEnabled(false);
      mainServer = new DPServerTest(8888);
      serverLabel.setText("Server Loaded!");
      timer = new Timer(1000, this);
      timer.start();
    }
    if (event.getSource() == startButton)
    {
      serverLabel.setText("Game Started");
    }
    if (event.getSource() == timer)
    {
      mainServer.playerConnectionStatus();
      String[][] table = 
        {
            {"Player 1", player1Connected},
            {"Player 2", player2Connected},
            {"Player 3", player3Connected},
            {"Player 4", player4Connected}
        };
      connectedClientsList = new JTable(table, header);
      if (player1Connected != "No") System.out.println(player1Connected);
      repaint();
    }
  }

  public static void main(String[] args)
  {
    DPServerGUI serverGUI = new DPServerGUI();
    serverGUI.setTitle("Dark Project Server GUI");
    serverGUI.setSize(800,600);
    serverGUI.setLocationRelativeTo(null);
    serverGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    serverGUI.setVisible(true);
  }
}

Upvotes: 1

Views: 1169

Answers (1)

Guillaume Polet
Guillaume Polet

Reputation: 47608

The problem is that you are recreating a new JTable instead of re-using the existing one (and additionally, you don't remove the old one to replace it by the new one, so the new one has no chance to ever be displayed).

Rather update the TableModel of the JTable. Either use the default one provided (you can get it by invoking JTable.getModel()) which is a DefaultTableModel or implement your own by extending AbstractTableModel (and calling fireXXX() methods) which you can set using JTable.setModel().

Check out the Swing tutorial on How to use tables and especially the part on TableModel

Additional tip: stay away from static variables, they always hurt.

Slightly updated code (not specifically pretty, but shows you the idea):

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.AbstractTableModel;

@SuppressWarnings("serial")
public class DPServerGUI extends JFrame {

    private JPanel serverPanel;
    private JButton startButton;
    private JButton loadServerButton;
    private JLabel serverLabel;

    private JTable connectedClientsList;
    private JScrollPane scrollPane;
    public String player1Connected = "No";
    public String player2Connected = "No";
    public String player3Connected = "No";
    public String player4Connected = "No";

    public DPServerGUI() {
        serverPanel = new JPanel();

        startButton = new JButton("Start Game");

        loadServerButton = new JButton("Load Server");

        scrollPane = new JScrollPane(getTable());

        serverLabel = new JLabel("Server Not Running");

        serverPanel.add(serverLabel);
        serverPanel.add(startButton);
        serverPanel.add(loadServerButton);
        serverPanel.add(scrollPane);
        this.add(serverPanel);
    }

    private PlayerTableModel tableModel;

    public class PlayerTableModel extends AbstractTableModel {

        private String[] header = { "Players", "Connected To Server" };
        private String[][] table = { { "Player 1", player1Connected }, { "Player 2", player2Connected }, { "Player 3", player3Connected },
                { "Player 4", player4Connected } };

        @Override
        public String getColumnName(int column) {
            return header[column];
        }

        @Override
        public int getRowCount() {
            return table.length;
        }

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return table[rowIndex][columnIndex];
        }

        public void setPlayerConnected(int rowIndex, boolean connected) {
            table[rowIndex][1] = connected ? "Yes" : "No";
            fireTableCellUpdated(rowIndex, 1);
        }

    }

    private JTable getTable() {
        tableModel = new PlayerTableModel();
        connectedClientsList = new JTable(tableModel);
        return connectedClientsList;
    }

    public static void main(String[] args) {
        final DPServerGUI serverGUI = new DPServerGUI();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                serverGUI.setTitle("Dark Project Server GUI");
                serverGUI.setSize(800, 600);
                serverGUI.setLocationRelativeTo(null);
                serverGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                serverGUI.setVisible(true);
            }
        });

        // Dummy thread that simulates user connecting and disconnecting randomly.
        Timer t = new Timer(2000, new ActionListener() {

            Random random = new Random();

            @Override
            public void actionPerformed(ActionEvent e) {
                for (int i = 0; i < serverGUI.tableModel.getRowCount(); i++) {
                    serverGUI.tableModel.setPlayerConnected(i, random.nextBoolean());
                }

            }
        });
        t.start();
    }

}

Upvotes: 5

Related Questions