2017-04-07 10 views
2

내 borderlayout 안에 theGrid 배열에서 참조하는 JPanels가 있습니다. 별도의 함수에서 JPanel의 모양을 변경하고자하므로 특정 JPanel을 그려야하는 방식을 변경합니다. 문제는 인스턴트 메시징 (JPanel)의 새로운 버전을 페인트하는 방법을 알지 못한다는 것입니다.BorderLayout 내에서 JPanels를 다시 그리는 방법

다른 질문을 보았습니다. mainPanel 또는 contentPane에서 .revalidate, .validate, .repaint() 등을 사용해 보았습니다. 그렇지 않으면 두 버전 모두에서 생성 된 JPanel의 새 버전을 가져 오지 못합니다. 에.

I 설정 그리드 아래의 생성자에서

와 같은 클래스에있는 점을 추가하여 그리드를 업데이트 할 생각입니다 아래 그것은 JFrame의

public class GraphicDisplay extends JFrame { 

     private static int ROWS = 6; 
     private static int COLS = 7; 
     private JPanel[][] theGrid = new JPanel[ROWS][COLS]; 
     private JPanel mainPanel = new JPanel(new GridLayout(ROWS, COLS)); 
     private Container contentPane; 

     public GraphicDisplay() { 
      for (int i = 0; i < theGrid.length; i++) { //Initialize theGrid (with blanks) 
       for (int j = 0; j < theGrid[i].length; j++) { 
        theGrid[i][j] = new JPanel(); 
       } 
      } 

      //add them to the JFrame 
      contentPane = getContentPane(); 
      contentPane.setLayout(new BorderLayout()); 

      JPanel boardElements = new JPanel(); 
      boardElements.setLayout(new BoxLayout(boardElements, BoxLayout.Y_AXIS)); //vertical layout for the two parts, theGrid itself and then the 
      // button which goes underneath, 

      final int SPACE = 3; 
      final Color COLORCHOICE = Color.BLACK; 


      mainPanel.setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE)); 
      mainPanel.setBackground(COLORCHOICE); 
      JPanel[][] panels = new JPanel[ROWS][COLS]; 
      for (int i = 0; i < panels.length; i++) { 
       for (int j = 0; j < panels[i].length; j++) { 
        panels[i][j] = new JPanel(new GridLayout(1, 1, 1, 1)); 
        panels[i][j].setBackground(COLORCHOICE); 
        panels[i][j].setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE)); 

        mainPanel.add(panels[i][j]); 


        panels[i][j].add(theGrid[i][j]); 


       } 
      } 
      //adding the grid to the vertical layout 
      boardElements.add(mainPanel); 
      //adding the button which will go directly under the grid 
      boardElements.add(new JButton("Button")); 

      contentPane.add(boardElements, BorderLayout.CENTER); 

     } 

기능의 나머지 부분에 맞는 방법 점 3,3

public void addDotToGrid() { 
        //theGrid[3][3] reference was added to the panels array which is part of the layout, so I would of thought by changing the value of it here would then change this JPanel on the UI 
        theGrid[3][3] = new JPanel() { 
         public void paintComponent(Graphics g) { 
          //g.setColor(Color.RED); 
          int y = 0; 
          int diameter = getWidth() -10; 
          int x = (getWidth()/2) - (diameter/2); 
          super.paintComponent(g); 
          Graphics2D g2d = (Graphics2D)g; 
          // Assume x, y, and diameter are instance variables. 
          Ellipse2D.Double circle = new Ellipse2D.Double(x, y, diameter, diameter); 
          g2d.fill(circle); 

         } 
        }; 


} 
GraphicDisplay 객체가 생성되는 다른 클래스

주요 방법

public static void main(String[] args) { 

      GraphicDisplay display2 = new GraphicDisplay(); 
      display2.setSize(600, 600); 
      display2.setVisible(true); 
      display2.addDotToGrid(); 
     } 
01,235 (그러나 문제는 어떤 가시적 변화를 보이지 않는) 16,

문제는 그리드가 표시되지만 addDotToGrid()는 아무 것도 변경하지 않고 점은

+0

의 적절한 사이즈 아이를 가지지 않는 JPanel는, 0 × 0 픽셀에 그 경계가있는 경우는 인 세트가됩니다. JPanel 서브 클래스의 getPreferredSize()를 오버라이드 (override) 해, 타원을 적응시키는 크기를 돌려줍니다. – VGR

답변

4

당신은 당신의 theGrid 배열에 의해 개최 JPanel을 변경하고있는 그리드의 추가가되지 않습니다, 그러나 이것은 더있다 GUI에 표시된 JPanels에 영향을 미치고 변수와 참조 또는 객체 간의 주요 차이점을 가져옵니다. 변수가 참조하는 객체를 변경하면 이전에 참조 된 객체에는 아무런 영향을 미치지 않습니다. 귀하의 솔루션은 그리드에 의해 개최 JPanel을 변경하는 것입니다.

이렇게하는 한 가지 방법은 모두 원하는 그림을 그리는 boolean으로 제어 할 수있는 paintComponent 메서드를 모두 제공 한 다음 관심있는 패널의 부울 변수를 변경하는 것입니다.

이것이 내 GUI라면 JLabels의 그리드를 만들고 간단하게 ImageIcons를 바꿀 수 있습니다. 원하는 곳에서 - 가능한 한 간단하게 유지하십시오! 예를

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class MyGridEg extends JPanel { 
    private static final int SPACE = 6; 
    private static final int ROWS = 6; 
    private static final int COLS = 7; 
    private static final int IMG_W = 80; 
    private static final int SML_GAP = 3; 
    private static final Color IMG_BACKG = new Color(240, 240, 240); 
    private static final String TITLE = "Click on a Cell"; 

    private JLabel[][] labelGrid = new JLabel[ROWS][COLS]; 
    private Icon blankIcon = createIconDisk(new Color(0, 0, 0, 0)); 
    private Icon redIcon = createIconDisk(Color.RED); 

    public MyGridEg() { 
     MyMouse myMouse = new MyMouse(); 
     JPanel gridHolder = new JPanel(new GridLayout(ROWS, COLS, SPACE, SPACE)); 
     gridHolder.setBackground(Color.BLACK); 
     for (int i = 0; i < labelGrid.length; i++) { 
      for (int j = 0; j < labelGrid[i].length; j++) { 
       JLabel label = new JLabel(blankIcon); 
       label.addMouseListener(myMouse); 
       labelGrid[i][j] = label; 
       gridHolder.add(label); 
      } 
     } 
     gridHolder.setBorder(BorderFactory.createLineBorder(Color.black, SPACE)); 

     JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER); 
     titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 20)); 

     JButton clearButton = new JButton(new ClearAction("Clear")); 
     JPanel btnPanel = new JPanel(); 
     btnPanel.add(clearButton); 

     setLayout(new BorderLayout()); 
     add(gridHolder, BorderLayout.CENTER); 
     add(btnPanel, BorderLayout.PAGE_END); 
     add(titleLabel, BorderLayout.PAGE_START); 
    } 

    private Icon createIconDisk(Color color) { 
     BufferedImage img = new BufferedImage(IMG_W, IMG_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setBackground(IMG_BACKG); 
     g2.clearRect(0, 0, IMG_W, IMG_W); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(color); 
     int x = SML_GAP; 
     int y = x; 
     int width = IMG_W - 2 * x; 
     int height = IMG_W - 2 * y; 
     g2.fillOval(x, y, width, height); 
     g2.dispose(); 
     return new ImageIcon(img); 
    } 

    private class MyMouse extends MouseAdapter { 
     @Override 
      public void mousePressed(MouseEvent e) { 
       JLabel selected = (JLabel) e.getSource(); 
       Icon icon = selected.getIcon() == blankIcon ? redIcon : blankIcon; 
       selected.setIcon(icon); 
      } 
    } 

    private class ClearAction extends AbstractAction { 
     public ClearAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      for (JLabel[] labelRow : labelGrid) { 
       for (JLabel cell : labelRow) { 
        cell.setIcon(blankIcon); 
       } 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     MyGridEg mainPanel = new MyGridEg(); 

     JFrame frame = new JFrame("MyGridEg"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

이 코드의 핵심 내용은

내가 JLabels 또는 JPanel의 스와핑 아니에요 오히려 내가 JLabels을 동일하게 유지하고있어,하지만 자신의 상태를 변경하고 있다는 점이다. 내가 2D 배열, labelGrid에 의해 개최 JLabels의 상태를 변경하면 나는 clearButton하는 JButton가 호출 ClearAction 클래스에서와 마찬가지로이 방법은, 이것은, 뷰의 변화에 ​​반영됩니다 :

private class ClearAction extends AbstractAction { 
    public ClearAction(String name) { 
     super(name); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     for (JLabel[] labelRow : labelGrid) { 
      for (JLabel cell : labelRow) { 
       cell.setIcon(blankIcon); 
      } 
     } 
    } 
} 
+0

큰 반응을 보내 주셔서 감사합니다. – Alex