2014-12-06 3 views
1

안녕하세요. 타이머 이벤트가 발생할 때 데이터 테이블을 다시 칠하는 데 어려움이 있습니다. 내가 만들고있는 게임에서 플레이어의 연결성을 확인하고 있습니다. 플레이어가 연결되면 JTable이 변경되어 플레이어가 연결되었음을 표시해야합니다. 그러나 테이블을 채우는 변수가 변경 되더라도 테이블은 변경되지 않습니다.Repaint 호출시 JTable이 다시 그려지지 않음

내 GUI 코드는 기본적으로 플레이어가 GUI 변수가 변경된 문자열 변수에 연결되어있을 때마다 내 타이머가 매초마다 테이블을 다시 그려야하며 변경 사항을 확인하고 올바른 정보로 다시 그려야합니다. 변수가 변경되고 콘솔에서 해당 출력을 볼 수 있지만 그에 따라 테이블이 업데이트되지 않습니다.

감사합니다.

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); 
    } 
} 
+0

당신은 전화해야'무효화은()'대신 다시 그리기'의()'올바른 정보와 테이블을 다시 그려야합니다. –

+0

응답 해 주셔서 감사합니다. 시도했지만 여전히 동일한 결과가 발생했습니다. player1이 변수 player1을 연결하면 연결된 출력은 콘솔에 연결되지만 표는 변경되지 않습니다. – visualbasicNoob9000

+0

@MikeLaren _ repaint() 대신 invalidate()를 호출해야합니다. invalidate()가 JTable에서 어떻게 도움이되는지 궁금합니다. –

답변

5

문제는 새가있다 있도록, 새로운 JTable를 다시 대신 기존의 것을 다시 사용 (그리고 또한, 당신은 새로운 하나를 대체 할 수있는 이전을 제거하지 마십시오한다는 것이다 표시 될 기회 없음).

JTableTableModel을 오히려 업데이트하십시오. 제공되는 기본값 (JTable.getModel()을 호출하여 얻을 수 있음)을 사용하거나 JTable.setModel()을 사용하여 설정할 수있는 AbstractTableModel (및 fireXXX() 메서드 호출)을 확장하여 사용자 고유의 도구를 구현하십시오.

체크 아웃 How to use tables에 스윙 튜토리얼 및 TableModel

추가 팁에 특히 부분 : 멀리 static 변수에서 유지, 그들은 항상 상처를 줬어.

약간 업데이트 된 코드 (특히 꽤 아니지만, 당신에게 아이디어를 보여줍니다) :

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(); 
    } 

} 
+0

이 코드를 가져 오는 데 문제가 있습니다. 도와 주실 수 있습니까? 고맙습니다! – visualbasicNoob9000

+0

@ visualbasicNoob9000 업데이트 된 코드를 확인하십시오. 데모는 방법에 대해서만, 코드에는 정리가 필요합니다. –

+1

EDT 외부에서 모델을 업데이트하여 스윙의 단일 스레드 규칙을 위반하고 있습니다. 스레드 대신 – MadProgrammer

관련 문제