2017-12-13 48 views
0

저는이 문제를 며칠 동안 처리해 왔으며 어디에서 잘못되었는지 이해할 수 없습니다. 서버 - 클라이언트 채팅 프로그램을 만들었고 서버 GUI에는 사용자 목록을 보여주는 탭이 있습니다. 이 목록은 내가 원하는 모든 방식으로 작동합니다. UserList을 클라이언트 GUI에 추가하고 JList이 있지만, DefaultListModel을 업데이트하면 JListServerGUI에서만 업데이트됩니다. 디버그를 시도하여 ChatGUI의 JList이 표시 가능하지 않으며 이유 또는 수정 방법을 알 수 없습니다. (클라이언트 조인 할 때 등록 방법은 프로그램에서 나중에라고합니다)JList가 표시되지 않습니다.

public class ServerGUI { 
    public volatile static ArrayList<Client> users; 
    public static DefaultListModel<String> model = new DefaultListModel<String>(); 
    static Client clientReg; 

    public static void register(Client client) { 
     clientReg = client; 
     users.add(clientReg); 
     model.addElement(clientReg.username); 
     ServerView.userList.setModel(model); 
     ChatView.userList.setModel(model); 
    } 
} 

-

클라이언트 클래스

public class Client { 
    String username; 
    Socket socket; 
    PrintWriter out; 
    Scanner in; 

    public Client (String username, Socket socket, PrintWriter out, Scanner in) { 
     this.username = username; 
     this.socket = socket; 
     this.out = out; 
     this.in = in; 
    } 
} 

ServerGUI 클래스 : 여기

내 (관련) 코드 채팅보기 클래스

public class ChatView extends JFrame { 
    public JPanel contentPane; 
    public static JList<String> userList = new JList<String>(); 
    public static JTextArea chatOutput; 
    private JTextField inputField; 

    public ChatView() { 
     setResizable(false); 
     setTitle("Chat GUI"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setBounds(100, 100, 550, 475); 
     contentPane = new JPanel(); 
     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     setContentPane(contentPane); 
     contentPane.setLayout(null); 

     JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP); 
     tabs.setBounds(0, 0, 535, 435); 
     contentPane.add(tabs); 

     JPanel chatViewer = new JPanel(); 
     tabs.addTab("Chat", null, chatViewer, null); 
     chatViewer.setLayout(null); 

     // Code that makes up the chatViewer JPanel 

     JPanel userListPane = new JPanel(); 
     tabs.addTab("User List", null, userListPane, null); 
     userListPane.setLayout(null); 

     JLabel label = new JLabel("User List:"); 
     label.setBounds(10, 10, 510, 20); 
     userListPane.add(label); 

     userList.setModel(new AbstractListModel<String>() { 
      public String getElementAt(int index) { 
       return ServerGUI.model.get(index); 
      } 

      public int getSize() { 
       return ServerGUI.model.size(); 
      } 
     }); 
     userList.setValueIsAdjusting(true); 
     userList.setLayoutOrientation(JList.HORIZONTAL_WRAP); 
     userList.setBounds(10, 40, 510, 395); 

     userListPane.add(userList); 
    } 
} 

대부분의 프로그래밍은 스스로 가르쳤으므로 잘못된 형식이 있으면 알려 주시면 수정 해 드릴 수 있습니다.

+1

null 레이아웃을 사용하지 마십시오. 이 사이트에서 Swing Q/A를 읽은 적이 있다면, 이것은 매우 좋은 이유 때문에 권장되지 않는다는 것을 이미 알고있을 것입니다. –

+0

userListPane이 다른 탭에 추가되었습니다. 내가 실수로 선택한 코드에이를 추가하는 것을 잊었습니다 – bh34e5

+1

그래서 JList가 작동합니까? 탭에서 볼 수 있습니까? 하지만 다시 말하지만 null 레이아웃을 사용하지 마십시오. 대신 JList의 가시 행 수를 설정하고 프로토 타입 요소를 제공하여 JLists가 항상 JScrollPane 내에 표시되어야하므로 JScrollPane 내에서 자체 표시된 크기를 설정합니다. 어디에서나 setBounds를 제거하고 레이아웃 관리자를 사용하는 방법을 배웁니다. –

답변

2

OK, 난 당신이 정적 필드와 메소드를 통해에 '공유'모델을 시도하고 방법 :

userList.setModel(new AbstractListModel<String>() { 
    public String getElementAt(int index) { 
     return ServerGUI.model.get(index); 
    } 

    public int getSize() { 
     return ServerGUI.model.size(); 
    } 
}); 

을이 작동하지 않습니다, 어떻게 클라이언트와 서버 전송 정보가 없습니다. 예를 들어, 클라이언트가 사용할 수있는 서버 정적 필드와 메소드를 가지고 있지만 실제 서버 클래스와 인스턴스는 완전히 다른 JVM에서 실행됩니다. 보통 다른 머신에서 실행되므로 얻는 데이터는 다릅니다. 실제 서버 객체의 실제 상태와 정적 클래스 상태를 서버 자체에 반영하지만 올바른 객체/클래스의 단순한 그림자입니다.

제안 :

  • 당신의 클라이언트에 대한 표준 목록 모델을 사용하고, 사용하고있는 코드를 삭제, 이것이 당신이 정보를 전송하는 진정한 클라이언트/서버 코드 인 경우는
  • 작동하지 않습니다 소켓을 통해 클라이언트가 소켓을 통해 서버에서 업데이트를 가져와야합니다. 우리는 어떻게 연결하는지 알지 못한다. 소켓 이외의 특정 권장 사항을 제시 할 수 없다. 소켓에서 데이터를 얻는다.
  • 그런 다음 백그라운드 스레드에서 수행한다. 즉, 클라이언트는 소켓 데이터를 스윙 이벤트 스레드
  • 그러나이 정보를 사용하여 클라이언트의 목록 모델 ()을 이벤트 스레드로 업데이트하십시오. 이를 수행하는 한 가지 방법은 프로세스/게시 방법 쌍을 사용하여 SwingWorker<Void, String>을 사용하는 것입니다.
+0

나는 단지 명료하게하고 싶다 : 당신이'DefaultListModel' 대신'ListModel'을 사용하도록 추천하고 있습니다. 프로그래밍에 익숙하지 않은 나는 스윙 이벤트 스레드에서 벗어 났는지 어떻게 알 수 없으므로 어떻게 알 수 있습니까? – bh34e5

+0

@ bh34e5 : 전혀 그렇지 않습니다. DefaultListModel를 포함한 ListModel로부터 파생 한 클래스를 사용합니다. –