2013-01-16 38 views
1

我写的一个小游戏,使用SwingGUI,我遇到了一个问题。我发布了截图,以便您更好地掌握情况。摇摆的定位问题

enter image description here

起初我只有针对我使用的GridLayout板上。

但是,我需要添加一个面板来显示分数,所以我放弃了GridLayout而倾向于GridBagLayout。我正确定位了分数的新JPanel,并在其中添加了2 JTextArea以显示结果。

事情是,每当一个玩家会做出一个动作(因此董事会重新绘制以反映其新状态),文本区域会闪烁并部分被董事会覆盖(请参阅截图)。任何想法可能是什么问题?我已经设置了所有组件的首选大小,并尝试使用setOpaque,但它无济于事。

主布局持有者的代码。

public class BoardLayout extends JFrame implements ModelObserver { 

    /** 
    * {@value} 
    */ 
    private static final long serialVersionUID = 5834762299789973250L; 

    /** 
    * {@value} 
    */ 
    private static final int RESULTS_PANEL_HEIGHT = 100; 

    private final BoardEventsListener eventsListener; 

    private final ResultsLayout resultsLayout; 

    private class CellMouseListener implements MouseListener { 

     private final int cellIndex; 

     public CellMouseListener(final int index) { 
      cellIndex = index; 
     } 

     @Override 
     public void mouseClicked(final MouseEvent event) { 
      eventsListener.onCellSelected(cellIndex); 
     } 

     @Override 
     public void mouseEntered(final MouseEvent event) { 
      // blank 
     } 

     @Override 
     public void mouseExited(final MouseEvent event) { 
      // blank 
     } 

     @Override 
     public void mousePressed(final MouseEvent event) { 
      // blank 
     } 

     @Override 
     public void mouseReleased(final MouseEvent event) { 
      // blank 
     } 

    } 

    public BoardLayout(final BoardEventsListener listener) throws HeadlessException { 
     this(listener, "", null); 
    } 

    public BoardLayout(GraphicsConfiguration graphicsConfiguration) { 
     this(null, "", graphicsConfiguration); 
    } 

    public BoardLayout(final BoardEventsListener listener, String title, 
      GraphicsConfiguration graphicsConfiguration) { 
     super(title, graphicsConfiguration); 

     eventsListener = listener; 

     setLayout(new GridBagLayout()); 
     setBoardSize(); 
     populateCells(); 
     resultsLayout = attachResultsLayout(); 

     resultsLayout.setOpaque(true); 

     setVisible(true); 
    } 

    private ResultsLayout attachResultsLayout() { 
     final ResultsLayout resultsLayout = new ResultsLayout(Game.BOARD_COLUMN_COUNT 
       * BoardCellLayout.WIDTH_BOARD_CELL, RESULTS_PANEL_HEIGHT); 
     final GridBagConstraints constraints = new GridBagConstraints(); 
     constraints.gridwidth = GridBagConstraints.REMAINDER; 
     constraints.gridheight = GridBagConstraints.REMAINDER; 
     constraints.gridx = 0; 
     constraints.gridy = 8; 
     getContentPane().add(resultsLayout, constraints, 64); 
     return resultsLayout; 
    } 

    private void setBoardSize() { 
     final Dimension boardDimension = getBoardDimension(); 
     setMinimumSize(boardDimension); 
     setSize(boardDimension); 
     setResizable(false); 
    } 

    private void populateCells() { 
     final Container container = getContentPane(); 
     for (int i = 0; i < Game.BOARD_ROW_COUNT; ++i) { 
      for (int j = 0; j < Game.BOARD_COLUMN_COUNT; ++j) { 
       final BoardCellLayout currentCell = new BoardCellLayout(); 
       final int cellIndex = i * Game.BOARD_COLUMN_COUNT + j; 
       final GridBagConstraints constraints = new GridBagConstraints(); 
       constraints.gridx = j; 
       constraints.gridy = i; 
       container.add(currentCell, constraints, cellIndex); 
       currentCell.setOpaque(true); 
       currentCell.addMouseListener(new CellMouseListener(cellIndex)); 
      } 
     } 
    } 

    private Dimension getBoardDimension() { 
     final Dimension boardDimension = new Dimension(Game.BOARD_COLUMN_COUNT 
       * BoardCellLayout.WIDTH_BOARD_CELL, (Game.BOARD_ROW_COUNT + 1) 
       * BoardCellLayout.HEIGHT_BOARD_CELL); 
     return boardDimension; 
    } 

    public BoardLayout(String title) throws HeadlessException { 
     this(null, title, null); 
    } 

    @Override 
    public void setVisible(final boolean isVisible) { 
     super.setVisible(isVisible); 
     setBackground(Color.WHITE); 
     pack(); 
    } 

    @Override 
    public void onModelChanged(Collection<Cell> changedCells, final int whiteDiscsCount, 
      final int blackDiscsCount) { 
     for (final Cell cell : changedCells) { 
      final BoardCellLayout boardCell = getCellAt(cell.getIndex()); 
      boardCell.take(cell.getOwner()); 
     } 
     resultsLayout.onResultChanged(whiteDiscsCount, blackDiscsCount); 

    } 

    @Override 
    public void onNextMovesAcquired(Collection<Cell> nextMoves) { 
     clearCellHighlight(); 
     for (final Cell cell : nextMoves) { 
      final BoardCellLayout boardCell = getCellAt(cell.getIndex()); 
      boardCell.highlight(); 
     } 
    } 

    private void clearCellHighlight() { 
     final Container container = getContentPane(); 
     for (int i = 0; i < container.getComponentCount() - 1; ++i) { 
      final BoardCellLayout boardCellLayout = (BoardCellLayout) container.getComponent(i); 
      boardCellLayout.clearHighlight(); 
     } 
    } 

    private BoardCellLayout getCellAt(final int index) { 
     final Container container = getContentPane(); 
     return (BoardCellLayout) container.getComponent(index); 
    } 
} 

面板的代码,拿着结果:

public class ResultsLayout extends JPanel { 

    /** 
    * {@value} 
    */ 
    private static final long serialVersionUID = 8379710427718395507L; 

    private final ResultsTextView whiteTextView; 

    private final ResultsTextView blackTextView; 

    public ResultsLayout(final int width, final int height) { 
     super(new GridLayout(2, 1)); 

     setVisible(true); 

     final Dimension dimension = new Dimension(width, height); 
     setMinimumSize(dimension); 
     setPreferredSize(dimension); 
     setSize(dimension); 

     whiteTextView = new ResultsTextView(Player.WHITE); 
     blackTextView = new ResultsTextView(Player.BLACK); 

     add(whiteTextView, 0); 
     add(blackTextView, 1); 
    } 

    public void onResultChanged(final int whiteDiscsCount, final int blackDiscsCount) { 
     whiteTextView.setDiscCount(whiteDiscsCount); 
     blackTextView.setDiscCount(blackDiscsCount); 
    } 

} 

的JTextArea中的代码,拿着结果:

public class ResultsTextView extends JTextArea { 

    /** 
    * {@value} 
    */ 
    private static final long serialVersionUID = -6354085779793155063L; 

    /** 
    * {@value} 
    */ 
    public static final String BACKGROUND_COLOR = "#066f02"; 

    private static final int START_DISCS_NUMBER = 2; 

    private final Player player; 

    public ResultsTextView(final Player player) { 
     super(); 
     setEditable(false); 

     setBackground(Color.decode(BACKGROUND_COLOR)); 

     this.player = player; 
     setText(player.toString() + " result is: " + START_DISCS_NUMBER); 

     final Dimension dimension = new Dimension(100, 20); 
     setPreferredSize(dimension); 
     setMinimumSize(dimension); 
     setMaximumSize(dimension); 
    } 

    public void setDiscCount(final int discCount) { 
     setText(player.toString() + " result is:" + discCount); 
    } 

} 
+0

很多,但没有你使用的代码,没有任何对你有用的代码。 – MadProgrammer

+0

编辑我的答案:)谢谢! – asenovm

+0

为了更快得到更好的帮助,请发布[SSCCE](http://sscce.org/)。 –

回答

1

问题是,我没有使用SwingUtilities.invokeLater用于更新GUI和这是造成的闪烁。我开始使用它,现在都很好:)

+0

这是确保唯一的方法。 – trashgod

2

添加乐谱面板让我想到一个MVC模式其中游戏板和得分均为次浏览听同一游戏模型。一个example引用也有一个基于网格的游戏,可能会提供一些洞察设计和布局。特别是,RCStatus查看,在BorderLayout.NORTHRCInfo查看,在BorderLayout.SOUTH,每听RCModel。游戏面板占用BorderLayout.CENTER

您提供的片段的几个注意事项:

  • 让你的主视图扩展JPanel,并把它添加到JFrame实例。

  • 不要试图用单个布局来解决每个问题。

  • 考虑extends MouseAdapter高于implements MouseListener

  • 重新考虑setXxxSize()

+2

同意,用你的底部面板分开你的板面板。让他们成为相应的面板;并使用'BorderLayout.CENTER'和'BorderLayout.SOUTH'将它们添加到容器中,将底部面板的首选大小设置为'new Dimension(0,preferredHeight);' – rtheunissen

+0

@ paranoid-android :好点;感谢您的评论。引用的例子直接呈现网格;作为另一种选择,这个[游戏](https://sites.google.com/site/drjohnbmatthews/buttons)使用s'GridLayout'按钮。 – trashgod

+0

谢谢!我开始使用BorderLayout,虽然问题在其他地方:) – asenovm