2017-05-15 5 views
0

Jbutton을 클릭하여 JPanel에 도형을 그릴 연습을하고 있지만 할 수 없습니다. 웹 서핑을하는 데 5 시간이 걸렸지 만 할 방법을 찾을 수 없습니다. 이것은 내가하고 싶은 것입니다. "직사각형"버튼을 클릭하면 버튼 아래에 사각형이 나타나고 "원"버튼을 클릭하면 원이 나타납니다.ActionListener를 사용하여 JPanel에서 모양을 그리는 방법은 무엇입니까?

import javax.swing.*; 
    import java.awt.*; 
    import java.awt.event.*; 

    class Shape extends JFrame { 
     JButton rec, circle; 
     static String botSelected; 
     Shape(){ 
      frameSet(); 
     } 

     void frameSet(){ 
      JFrame frame = new JFrame(); 
      frame.setVisible(true); 
      frame.setSize(600,300); 
      rec = new JButton ("Rectangle"); 
      circle = new JButton("Circle"); 
      JPanel panel = new JPanel(); 
      frame.add(panel); 
      panel.add(rec); 
      panel.add(circle); 
      Click clk = new Click(); 
      rec.addActionListener(clk); 
      circle.addActionListener(clk); 
     } 

     public void paint (Graphics g){ 
      super.paint(g); 
      if (botSelected.equals("Rectangle")) 
       g.fillRect(50,50,50,50); 
      else if (botSelected.equals("Circle")) 
       g.fillOval(50,50,50,50); 
     } 

     public static void main (String [] arg){ 
      Shape s = new Shape(); 
     } 
    } 

    class Click implements ActionListener{ 
     public void actionPerformed (ActionEvent e){ 
      Shape.botSelected = e.getActionCommand(); 
     } 
    } 
+0

변경 사항을 표시하려면 다시 칠할 필요가 있습니다. 이 코드는 많은 나쁜 습관으로 산재 해 있습니다. 왜 JFrame을 확장하고 있습니까? awt, 즉'java.awt.Shape' 클래스이기 때문에 클래스 이름을'Shape '로해서는 안된다. – matt

+0

내가 할 수있는 첫 번째 일은 [Painting in Swing] (http : // www. oracle.com/technetwork/java/painting-140037.html) 및 [사용자 정의 페인팅 수행] (https://docs.oracle.com/javase/tutorial/uiswing/painting/)을 참조하십시오. 일반적인 권장 사항으로 '정적'을 피할 것입니다. 객체 간 통신을위한 해결책이 아닙니다. – MadProgrammer

답변

1

내가 할 것이 첫 번째 것은 더 나은 도장 공정의 작동 방식을 이해하는 Painting in SwingPerforming custom painting을 통해 읽기를 가지고있다.

다음으로 JFrame은 그림을 그리는 데 나쁜 선택임을 이해해야합니다. 왜? 그것이 다층 구조이기 때문입니다.

RootPane

JFrame

는이 JLayeredPane contentPane, glassPaneJMenuBar하고 예에서, 그것은 또한 JPanel 포함이 포함 된 JRootPane가 포함되어 있습니다.

glassPane의 (기본값) 예외는 모든 이들 구성 요소가 불투명합니다.

paint 메서드에서 그려진 그림을 표시 할 수는 있지만 다른 구성 요소 중 하나라도 페인트하면 깨끗하게 지워집니다. 스윙 구성 요소는 실제로 서로 독립적으로 칠할 수 있기 때문에 먼저 부모 페인트를 사용하십시오.

더 나은 해결 방법은 JPanel에서 시작하여 paintComponent 메서드를 재정의하는 것입니다. 때 페인트주기를 트리거 단순성, 나는 또한 repaint 전화, 귀하의 경우, 그것은 actionPerformed 방법은 구성 요소의 속성에 액세스 할 수 있습니다뿐만 아니라,이 클래스에 대한 ActionListener을 구현하는 것이 좋습니다 및 거라고 들어

UI를 업데이트하려고합니다.

+0

감사합니다. 나는이 glassPane에 대해 몰랐다. 나는 그것에 대해 더 많이 읽어야한다. –

1

다음은 코드에서 파생 된 예제입니다.

@MadProgrammer가 말한대로 JFrame을 확장하지 마십시오.

  • botSelected에 null이 아닌 값을 제공하거나 paintComponent에 대한 첫 번째 호출은 지금 당신에게 NullPointerException

  • 클래스를 줄 것이다 다음 예에서

    , 여기에 주요 변경 사항은 JPanel을 확장하고 사용자 지정 그림의 경우 paintComponent을 바꿉니다.

  • ActionListener은 익명 클래스입니다. 별도의 클래스가 필요하지 않으며, 더 이상 정적 Shape

  • botSelected에서 필드에 직접 액세스 할 수 없습니다 원인

(점 이상 참조).

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; 

class Shape extends JPanel { 
    JButton rec, circle; 
    String botSelected = "";// don't let it be null, it would make paintComponent crash on startup 

    Shape() { 
     frameSet(); 
    } 

    void frameSet() { 
     JFrame frame = new JFrame(); 
     frame.setVisible(true); 
     frame.setSize(600, 300); 
     rec = new JButton("Rectangle"); 
     circle = new JButton("Circle"); 

     frame.add(this); 
     this.add(rec); 
     this.add(circle); 
     // anonymous class, has access to fields from the outer class Shape 
     ActionListener clk = new ActionListener() { 
      public void actionPerformed(final ActionEvent e) { 
       botSelected = e.getActionCommand(); 
       repaint(); 
      } 

     }; 
     rec.addActionListener(clk); 
     circle.addActionListener(clk); 
    } 

    //custom painting of the JPanel 
    @Override 
    public void paintComponent(final Graphics g) { 

     super.paintComponent(g); 
     if (botSelected.equals("Rectangle")) { 
      g.fillRect(50, 50, 50, 50); 
     } else if (botSelected.equals("Circle")) { 
      g.fillOval(50, 50, 50, 50); 
     } 
    } 

    public static void main(final String[] arg) { 
     Shape s = new Shape(); 
    } 

} 
+0

고맙습니다. 나는 많이 배웠다. –

+0

JFrame 확장이 작동하지 않지만 Jpanel이 작동하는 이유는 아직 명확하지 않습니다. 그리고 "this"가 버튼을 추가하는 방법을 설명합니다. 그리고 왜 main String에서 최종 String을 사용합니까? 이 부분에 대해 더 자세히 읽을 수있는 곳은 어디입니까? TNX –

+0

'JFrame'은 고유 한 내용인'JPanel'을 가지고 있습니다.'JFrame'에서'paint'를 오버라이드하려고하면 아무런 도움이되지 않을 것입니다. 클래스 자체가'JPanel'이므로'this'는'Shape' JPanel'자신, 그래서 당신은 단순히 this.add ...로 물건을 추가 할 수 있습니다. – Berger

관련 문제