2013-02-14 2 views
3

단순한 숙제를하려고합니다. 문 개체가 열려 있는지 여부를 표시하는 텍스트 줄을 표시합니다. 그 밑에는 (drawRect를 사용하여) 시각적으로 표현합니다. 하단에는 문을 열거 나 닫을 수있는 두 개의 버튼이있어서 텍스트와 사각형을 변경합니다.BorderLayout을 사용하여 JFrame에 그래픽 추가하기

편집 : 컴파일 된 지금 제공 할 수있는 코드의 목록 :

import java.awt.BorderLayout; 
    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Graphics; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 

    import javax.swing.JButton; 
    import javax.swing.JFrame; 
    import javax.swing.JPanel; 
    import javax.swing.JTextField; 

    public class Test { 

    public static void main(String[] args) { 

     // Creates new JFrame called frame, with title "Door" 
     // (displayed at top of screen). 
     JFrame frame = new JFrame ("Door"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     TempDoorPanel panel = new TempDoorPanel(); 
     frame.add(panel); 
     frame.pack(); 
     frame.setVisible(true); 

     } 
    } 

    class Door { 

    private String state; 
    private String message; 

    Door (String state) { 
     this.state = state; 
     message = "The door is currently closed."; 
    } 

    public boolean isOpen() { 
     return state.equals ("open"); 
    } 

    public boolean isClosed() { 
     return state.equals ("closed"); 
    } 

    public void setState(String state) { 
     this.state = state; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void open() { 
     if (state.equals("open")) { 
      message = "The door is already open."; 
     } 
     else { 
      state = "open"; 
      message = "The door has been opened."; 
     } 
    } 

    public void drawOpenDoor (Graphics page) { 
     page.drawRect(100, 100, 100, 100); 
    } 
    } 

    class TempDoorPanel extends JPanel { 

    private Door door; 
    private JTextField currentStateOfDoor; 
    private JButton openDoor; 

    public TempDoorPanel() { 
     super.setLayout(new BorderLayout()); 
     door = new Door("closed"); 
     super.setBackground(Color.blue); 
     super.setPreferredSize(new Dimension (360, 400)); 

     currentStateOfDoor = new JTextField(14); 
     currentStateOfDoor.setText(door.getMessage()); 
     super.add(currentStateOfDoor, BorderLayout.NORTH); 

     openDoor = new JButton("Open Door"); 

     class openDoorListener implements ActionListener { 
      public void actionPerformed (ActionEvent event) { 
       door.open(); 
       repaintText(); 
      } 
     } 

     openDoorListener openlistener = new openDoorListener(); 
     openDoor.addActionListener(openlistener); 

     JPanel holder = new JPanel(); 
     holder.add(openDoor); 
     super.add(holder, BorderLayout.SOUTH); 
    } 

    private void repaintText() { 
     currentStateOfDoor.setText(door.getMessage()); 
     // These methods are from Door class. 
    } 

    public void paintComponent (Graphics page) { 
     super.paintComponent(page); 
     if (door.isOpen()) 
      door.drawOpenDoor(page); 
     // isOpen is a boolean method from Door class. 
    } 
} 

작동 무엇 :

  • 버튼이 BorderLayout.SOUTH, 다른 후 하나, 화면에 적절한 장소에 나타납니다.
  • JTextField가 BorderLayout.NORTH
  • 에 표시됩니다. 마지막으로 파란색 영역이 화면 중앙의 올바른 위치에 나타납니다.

것은 내가 해결하기 위해 노력하고있어 :

  • 내가 얼마나 제대로 그 파란색 영역의 중앙에 사각형을 표시 할 생각이 없다. 사각형의 좌표와 크기를 변경해 보았습니다. 사각형의 크기와 크기는 전혀 변경되지 않았습니다. 나는 그것을 drawRect (100, 100, 100, 100)로 만들 수 있고 아무것도 변경하지 않는다.
  • 사각형이 현재 JTextField의 왼쪽 위 모서리 뒤에 숨겨져 있지만 BorderLayout으로 이동하는 방법을 알 수 없다는 것도 알고 있습니다.

질문 :

  • 가 어떻게 BorderLayout를의 사각형을 배치합니까?
  • 레이아웃에서 drawrect()를 통해 그려지는 사각형의 크기를 어떻게 조정합니까?
+1

이 [SSCCE]를 생성하십시오 (http://sscce.org) 하나의 사본을 필요로하고 우리는 가서 내가 간단하게 만들려면 새 프로젝트, 새로운 클래스와 새로운 주 등을 만들 필요가 이제 붙여 넣기하는 너와 같은 이름의 클래스를 만들고 코드를 복사하여 붙여 넣으십시오. 하지만 나도 게으름 뱅이 다 : P 또한 에러를 포함해서는 안된다. 즉, 'door.isOpen()'이 메소드를 포함하지 않았기 때문에 에러를 내고있다. –

+0

팁을 주셔서 감사합니다. –

+0

사각형은 JTextField에 의해 덮여 있기 때문에 다음과 같이 시도하십시오 :'page.drawRect (100, 100, 10, 10);' –

답변

4

JTextField에 그려진 JPanel에 구성 요소를 추가 했으므로 도면을 덮을 수 있습니다.

솔루션 :

1) 중 하나가 그리는하는

이상

2) 같은 JPanel에 구성 요소를 추가하지 말라 당신의 drawRect(..) 방법에 JTextField 높이를 확인하여이를 보상 그게 도움이되지 않는 한.

그래서 기본적으로 내가 만든 당신의 TempDoorPanel 새로운 JPanel 우리가 지금 drawRect(0,0,10,10)를 사용하고 JPaneldrawingPanel의 왼쪽 상단 모서리에 표시됩니다 그리기 패널BorderLayout.CENTER에 추가합니다.

  • 또한 오히려 getPreferredSize()을 무시하고 도면에 맞게 Dimension의를 반환 JPanelsetPreferredSize 전화 해달라고.

  • 포인트 2 번을 사용하여이 예를 참조 단순히 예를

repaint()를 호출하는 클래스의 paintComponent 외부를 호출하려면 다음

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class Test { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame("Door"); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

       TempDoorPanel panel = new TempDoorPanel(); 
       frame.add(panel); 
       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
class Door { 

    private String state; 
    private String message; 

    public Door(String state) { 
     this.state = state; 
     message = "The door is currently closed."; 
    } 

    public void drawOpenDoor(Graphics page) { 
     page.setColor(Color.GREEN); 
     page.drawRect(0, 0, 10, 10); 
    } 
} 

class TempDoorPanel extends JPanel { 

    private Door door; 
    private JTextField currentStateOfDoor; 
    private JButton openDoor; 

    public TempDoorPanel() { 
     super.setLayout(new BorderLayout()); 
     door = new Door("closed"); 

     currentStateOfDoor = new JTextField(14); 
     //AcurrentStateOfDoor.setText(door.getMessage()); 
     super.add(currentStateOfDoor, BorderLayout.NORTH); 

     openDoor = new JButton("Open Door"); 

     final JPanel drawingPanel = new JPanel() { 
      @Override 
      protected void paintComponent(Graphics grphcs) { 
       super.paintComponent(grphcs); 
       // if (door.isOpen()) { 
       door.drawOpenDoor(grphcs); 
       // } 
       // isOpen is a boolean method from Door class. 

      } 
     }; 
     drawingPanel.setBackground(Color.blue); 
     add(drawingPanel); 

     class openDoorListener implements ActionListener { 

      public void actionPerformed(ActionEvent event) { 
       //door.open(); 
       repaintText(); 
       drawingPanel.repaint();//so paint component of drawing panel is called 
      } 
     } 

     openDoorListener openlistener = new openDoorListener(); 
     openDoor.addActionListener(openlistener); 

     JPanel holder = new JPanel(); 
     holder.add(openDoor); 
     super.add(holder, BorderLayout.SOUTH); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(300, 300); 
    } 

    private void repaintText() { 
     // currentStateOfDoor.setText(door.getMessage()); 
     // These methods are from Door class. 
    } 
} 
+0

invokeLater Runnable 등의 부분이 없어도이를 수행 할 수 있습니까? 나는 그것이 나의 대학이 나에게 주었고 그들이 변화가 필요하다는 아무런 징후도주지 않았기 때문에 물어 본다. (나는 실제로 실행 가능한 것이 무엇인지 모른다). 관계없이, 고맙습니다. –

+0

그것은 변경해야합니다 (예. 빠져 나갈 수는 있지만 나중에 문제가 발생합니다). 모든 Swing 구성 요소는'SwingUtilties.invokeLater (Runnable r)'을 통해'Event Dispatch Thread'에서 생성되고 조작되어야합니다. 여기 [동시성의 동시성] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)에서 읽으십시오. 그래서 기본적으로 당신의 대학은 스윙 모범 사례를 고수하지 않습니다. –

+0

나는 할 것이다! 한 가지 더. paintComponent가 자동으로 실행된다는 것을 알고 있습니다 (수동으로 재정의 할 수 있음에도 불구하고). 하지만 그것이 자동으로 실행되는 API에서는 찾을 수 없습니다. 내가 궁금한 이유는 자동으로 실행되는 다른 것을 찾고 싶다. 어제 일을 시작했을 때 GraphicsComponent 객체를 paintComponent 클래스에 전달할 필요가 없다는 것을 알아 내는데 몇 시간이 걸렸습니다. 왜 그것이 자동이고 다른 것이 자동인가? –

3

당신이를 핸들러 너의 청자와 가진 문 오프닝 사건;

class openDoorListener implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
    door.open(); 
    repaintText(); 
    } 
} 

실제로 패널을 다시 그리는 호출이 없습니다. 따라서 패널의 paintComponent() 메소드가 호출되지 않고 door.drawOpenDoor()이 호출되지 않습니다. 단추를 클릭 한 다음 프레임의 크기를 조정하여이를 테스트 할 수 있습니다. 크기를 조정하면 패널이 자동으로 다시 칠하고 빙고 들어가 문이 나타납니다.

ActionListener에 repaint()에 대한 호출을 추가하여이 문제를 해결할 수 있습니다.

class openDoorListener implements ActionListener { 
    public void actionPerformed(ActionEvent event) { 
    door.open(); 
    repaintText(); 
    repaint(); // requests that the panel be repainted 
    } 
} 
+0

이것에 감사합니다. 갑자기 모든 것이 작동합니다. 저를 죽이는 것은이 자동 통화입니다. 너 같은 사람들이 내가 그렇게해야만한다고 말하지 않으면, 나는 생각하지 않았을 것이다. –

+0

+1 yup 또 다른 문제 OP가 repaint()를 호출하지 않습니다. –

관련 문제