2016-03-19 9 views
0

Я новичок в Java Swing, и я работал над созданием игры Connect 4, которая поддерживает многопользовательскую систему через сервер с gameRoom. Я работаю над этой конкретной проблемой почти 2 дня, и при ее решении возникли такие проблемы, как прекращение использования Thread.sleep и тщательное тестирование, что объект Game передается правильно на сервер и с сервера.Java Swing 2D массив панелей, не перекраивающихся с помощью таймеров Swing

Способ, которым я сконструирован, состоит в том, что каждое перемещение передается с помощью команды перемещения модели. Чтобы обновить GUI, сервер отправляет обратно новый объект Game в модель и помечает атрибут контроллера setRepaint как истинный. Затем таймер периодически проверяет, является ли этот атрибут истинным и вызывает метод repaintGrid().

После многих часов попыток заставить это работать, я не могу заставить игровые панели перекрашивать.

Некоторые моменты, которые могут помочь:

  • Если я выйти из приложения и перезапустить его с объектом игры, что уже есть ходы на него, панели окрашены. Проблема заключается в методе repaint.

  • Модель статична и получает ее. Атрибут игры обновляется каждый раз, когда вызывается Connect4App.model.getGameFromServer(). Не уверен, что это вызовет проблемы, но если я распечатаю панели, которые перекрашиваются как красные/синие, я могу проверить, что игровой объект успешно обновляется сервером на каждой итерации.

  • Иерархия кадров следующая: GuiMain является контейнером для игрыPanel, который имеет gridlayout, каждый из которых заполняется панелью GridPanel. В сетчатых панелей, по существу, слоты для токенами Connect4 игры и те из них, которые я пытаюсь обновить в методе repaintGrid

    import java.awt.GridLayout; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.awt.event.MouseAdapter; 
    import java.awt.event.MouseEvent; 
    import javax.swing.JPanel; 
    import javax.swing.Timer; 
    
    public class GameController { 
    
    MouseAdapter me; 
    private JPanel gamePanel; 
    private boolean setRepaint = false; 
    
    /** 
    * Constructor for the Game Controller. Takes in a view and a model 
    * 
    * @param view 
    * @param model 
    */ 
    public GameController() { 
        setupGridPanels(); 
        setupMouseAdapter(); 
        Connect4App.frame.setContentPane(Connect4App.guiMain); 
        Connect4App.frame.setTitle("Game View"); 
        goIntoTimer(); 
    
    } 
    
    /** 
    * Repaint Boolean used by timer. Set to true by external program 
    */ 
    public void setRepaint() { 
        this.setRepaint = true; 
    } 
    
    /** 
    * Swing Timer which checks if it needs to repaint every 8 seconds and if 
    * so, calls repaintGrid 
    */ 
    private void goIntoTimer() { 
        Timer timer = new Timer(50, new ActionListener() { 
         @Override 
         public void actionPerformed(ActionEvent e) { 
          Connect4App.model.getGameFromServer(); 
    
          if (setRepaint == true) { 
           repaintGrid(); 
           setRepaint = false; 
          } 
    
         } 
        }); 
        timer.setRepeats(true); 
        timer.setDelay(8000); 
        timer.start(); 
    
    } 
    
    /** 
    * Sets up the Initial Game Panels in the Connect4App.guiMain panel 
    */ 
    private void setupGridPanels() { 
        this.gamePanel = new JPanel(); 
        this.gamePanel.removeAll(); 
    
        // setting up the layout for, the game board. 
        this.gamePanel.setLayout(new GridLayout(0, Connect4App.model.getGame().getGrid()[0].length)); 
    
        int numberOfRows = Connect4App.model.getGame().getGrid().length; 
        int numberOfColumns = Connect4App.model.getGame().getGrid()[0].length; 
    
        for (int r = 0; r < numberOfRows; r++) { 
         for (int c = 0; c < numberOfColumns; c++) { 
          Connect4App.guiMain.setCircleArc(r, c, new GridPanel(r, c)); 
          this.gamePanel.add(Connect4App.guiMain.getCircleArcs()[r][c]); 
         } 
        } 
        Connect4App.guiMain.add(this.gamePanel); 
    } 
    
    /** 
    * Sets up the mouse pressed event handleres for every panel 
    */ 
    private void setupMouseAdapter() { 
        MouseAdapter mc = new MouseAdapter() { 
    
         @Override 
         public void mousePressed(MouseEvent mc) { 
    
          GridPanel cell = (GridPanel) mc.getSource(); 
    
          // this is the column that should go in the MakeMove message 
          int column = cell.getColumn(); 
          int row = cell.getRow(); 
    
          if (Connect4App.model.getGame().getGrid()[row][column].getState() == 0) { 
           System.out.println("attempting to make move"); 
           Connect4App.model.makeMove(column); 
          } 
         } 
        }; 
    
        for (int r = 0; r < Connect4App.model.getGame().getGrid().length; r++) { 
         for (int c = 0; c < Connect4App.model.getGame().getGrid()[0].length; c++) { 
          Connect4App.guiMain.getCircleArcs()[r][c].addMouseListener(mc); 
         } 
        } 
    } 
    
    void repaintGrid() { 
    
        // --> This is supposed to be working 
        System.out.println("repainting"); 
    
        for (int r = 0; r < Connect4App.model.getGame().getGrid().length; r++) { 
         for (int c = 0; c < Connect4App.model.getGame().getGrid()[0].length; c++) { 
          Connect4App.guiMain.getCircleArcs()[r][c].validate(); 
          Connect4App.guiMain.getCircleArcs()[r][c].repaint(); 
         } 
        } 
    } 
    } 
    

Любая помощь будет оценена :-D

+0

Похоже, что использование статичности может быть проблемой. Также может возникнуть проблема между потоками, читающими/записывающими переменную состояния – MadProgrammer

+0

Спасибо за ваш ответ @MadProgrammer. Я тестировал и кажется, что состояние обновляется должным образом в точке, когда метод paintComponent вызывается repaint: -s – mageofzema

+0

Можете ли вы распечатать сообщение об отладке внутри циклов? (Кроме того, я могу ошибаться, но вы уверены, что 'validate()' правильный? Как насчет 'revalidate()' или 'invalidate()'? Это время, так как я сделал что-то вроде этого.) –

ответ

0

Оказывается, у меня возникла проблема с отправкой одного и того же объекта назад и четвертым через objectoutputstream (состояние игры) без реселлинга потоков, и поэтому это заставляло клиента не получать обновления все время. Переработанный код выше работал. Закрывая нить, еще раз спасибо.