2016-11-11 7 views
1

저는 Java에 익숙하지 않고 스스로 배우고 있습니다. 나는이 시점에서 붙어있어. 아주 기본적인 페인트 응용 프로그램을 만들었지 만 내 친구는 모든 것을 하나의 * .java 파일에 넣었으므로 처음 프로그래머라고 말할 수 있습니다. 객체 지향 프로그래밍을 사용하지 않았기 때문에 D : So 나는 내 코드를 여러 파일로 나누기로했다. 그러나 이제는 코드가 작동하지 않습니다 (분명히).자바 : 페인트 응용 프로그램, 코드가 작동하지 않습니다, 내가 뭘 잘못하고있어?

그래서 프로그램 (JFrame)에 대한 창을 만드는 Main.java 파일이 있고 그 JFrame 안에는 BorderLayout.WEST에 2 개의 패널이 있고 CENTER에 secong이 있습니다.

Main.java 파일 (공용 클래스 메인) :

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

public class Main { 

    private Paint myPaint; 
    private menuSideBar sidePanel; 

Main(){ 

    JFrame ramka = new JFrame("Paint Application"); 

    sidePanel = new menuSideBar(); //this is the sidebar 
    myPaint = new Paint(); // this is the drawing board 

    ramka.getContentPane().add(sidePanel, BorderLayout.WEST); 
    ramka.getContentPane().add(myPaint, BorderLayout.CENTER); 
    ListenForWindow lForWindow = new ListenForWindow(); 
    ramka.addWindowListener(lForWindow); 
    ramka.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
    ramka.setSize(1400, 800); 
    ramka.setLocationRelativeTo(null); 
    ramka.setVisible(true); 

} 

private class ListenForWindow implements WindowListener{ 

    public void windowOpened(WindowEvent e) { 
    } 

    public void windowClosing(WindowEvent e) { 
     int closing = JOptionPane.showConfirmDialog(null, "Exit program?", "Exit", JOptionPane.YES_NO_OPTION); 
     if (closing == JOptionPane.YES_OPTION){ 
      System.exit(0); 
     } 
    } 

    public void windowClosed(WindowEvent e) { 
    } 

    public void windowIconified(WindowEvent e) { 
    } 

    public void windowDeiconified(WindowEvent e) { 
    } 

    public void windowActivated(WindowEvent e) { 
    } 

    public void windowDeactivated(WindowEvent e) { 
    } 

} 


public static void main(String[] args){ 
    new Main(); 
} 

} 

.WEST에 하나와 .CENTER의 하나는 메인 드로잉 보드 (버튼 등 포함) 사이드 바있다 그럼 난 파일 Paint.java (공용 클래스 페인트)에서 드로잉 보드를 가지고 :

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.image.BufferedImage; 
import javax.swing.*; 

public class Paint extends JComponent { 

private static final long serialVersionUID = 1L; 
private BufferedImage bimage; 
private Graphics2D g2; 
private int whichShape; 
private int oldX, oldY, newX, newY; 
private int w, h; 
private Color cColor; 

Paint() { 


    ListenForMouse lForMouse = new ListenForMouse(); 
    this.addMouseListener(lForMouse); 
    this.addMouseMotionListener(lForMouse); 

} 

public void paintComponent(Graphics g){ 


    if (bimage == null){ 
     bimage = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB); 
     g2 = (Graphics2D) bimage.getGraphics(); 
     g2.setBackground(Color.WHITE); 
     g2.setColor(Color.BLACK); 
     clear(); 
    } 

    g.drawImage(bimage, 0, 0, null); 
} 

public void clear(){ 
    g2.clearRect(0, 0, getSize().width, getSize().height); 
    repaint(); 
} 


public void draw(){ 

    w = newX - oldX; 
    h = newY - oldY; 

    if (w<0){ 
     w = w * (-1); 
    } 
    if (h<0){ 
     h = h * (-1); 
    } 


    switch (whichShape) { 

    case 1: 
     check(); 
     g2.drawRect(oldX, oldY, w, h); 
     repaint(); 
     break; 
    case 2: 
     check(); 
     g2.drawRoundRect(oldX, oldY, w, h, 40, 40); 
     repaint(); 
     break; 
    case 3: 
     check(); 
     g2.drawOval(oldX, oldY, w, h); 
     repaint(); 
     break; 
    case 4: 
     check(); 
     g2.fillRect(oldX, oldY, w, h); 
     repaint(); 
     break; 
    case 5: 
     check(); 
     g2.fillRoundRect(oldX, oldY, w, h, 20, 20); 
     repaint(); 
     break; 
    case 6: 
     check(); 
     g2.fillOval(oldX, oldY, w, h); 
     repaint(); 
     break; 
    } 
} 



public void rectangle(){ 

    whichShape = 1; 

} 

public void roundedrectangle(){ 
    whichShape = 2; 
} 

public void oval(){ 
    whichShape = 3; 
} 

public void filledrectangle(){ 
    whichShape = 4; 
} 

public void filledroundedrectangle(){ 
    whichShape = 5; 
} 

public void filledoval(){ 
    whichShape = 6; 
} 

public void colorChooser(){ 
    cColor = JColorChooser.showDialog(null, "Choose color", Color.black); 
    g2.setColor(cColor); 
} 


public void check(){ 
    if (oldX > newX){ 
     int z; 
     z = oldX; 
     oldX = newX; 
     newX = z; 
    } 
    if (oldY > newY){ 
     int z; 
     z = oldY; 
     oldY = newY; 
     newY = z; 
    } 
} 



public class ListenForMouse implements MouseListener, MouseMotionListener{ 

    public void mouseDragged(MouseEvent e) { 

    } 

    public void mouseMoved(MouseEvent e) { 
    } 

    public void mouseClicked(MouseEvent e) { 
    } 

    public void mousePressed(MouseEvent e) { 

     if (whichShape == 1 || whichShape == 2 || whichShape == 3 || whichShape == 4 || whichShape == 5 || whichShape == 6){ 
      oldX = e.getX(); 
      oldY = e.getY();  
     } 

    } 

    public void mouseReleased(MouseEvent e) { 

     if (whichShape == 1 || whichShape == 2 || whichShape == 3 || whichShape == 4 || whichShape == 5 || whichShape == 6){ 
     newX = e.getX(); 
     newY = e.getY(); 
     draw(); 
     } 

    } 

    public void mouseEntered(MouseEvent e) { 
    } 

    public void mouseExited(MouseEvent e) { 
    } 

} 

} 

나중에 menuSideBar.java 파일 (공용 클래스 menuSideBar)에 사이드 바는,이,이 클래스는 4 다른 읽

수업 (내가 추가하고 싶은 4 가지 메뉴가 있습니다, 여기에 하나의 예를 보여 드리겠습니다) :

import javax.swing.*; 

public class menuSideBar extends JPanel { 

    private static final long serialVersionUID = 1L; 
    sideBar1 sb1; 
    //sideBar2 sb2; 
    //sideBar3 sb3; 
    //sideBar4 sb4; 

menuSideBar(){ 


    this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 

    sb1 = new sideBar1(); 
    //sb2 = new sideBar2(); 
    //sb3 = new sideBar3(); 
    //sb4 = new sideBar4(); 

    this.add(sb1); 
    //this.add(sb2); 
    //this.add(sb3); 
    //this.add(sb4); 


} 
} 

그리고이 sideBar1.java 파일 (공용 클래스 sideBar1가) Paint.java 파일의 방법을 참조 ActionListener를 가진 JButton의이 포함되어

이제
import javax.swing.*; 
import javax.swing.border.Border; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 


public class sideBar1 extends JPanel { 

private static final long serialVersionUID = 1L; 
Paint myPaint; 

JButton pencilBut, brushBtn, bckpaintBtn, eraserBtn, textBtn, rectBtn, roundedrectBtn, ovalBtn, frectBtn, fovalBtn, froundedrectBtn, lineBtn; 

sideBar1(){ 


    Border border = BorderFactory.createTitledBorder("Paint"); 
    this.setBorder(border); 
    this.setLayout(new GridLayout(0,3)); 
    myPaint = new Paint(); 

    ListenForButton lForButton = new ListenForButton(); 

    pencilBut = new JButton("pencil"); 
    pencilBut.addActionListener(lForButton); 
    brushBtn = new JButton("brush"); 
    brushBtn.addActionListener(lForButton); 
    bckpaintBtn = new JButton("background paint"); 
    bckpaintBtn.addActionListener(lForButton); 
    eraserBtn = new JButton("eraser"); 
    eraserBtn.setIcon(icon_eraser); 
    eraserBtn.addActionListener(lForButton); 
    textBtn = new JButton("text"); 
    textBtn.addActionListener(lForButton); 
    lineBtn = new JButton("line"); 
    lineBtn.addActionListener(lForButton); 
    rectBtn = new JButton("rectangle"); 
    rectBtn.addActionListener(lForButton); 
    roundedrectBtn = new JButton("rounded rectangle"); 
    roundedrectBtn.addActionListener(lForButton); 
    ovalBtn = new JButton("oval"); 
    ovalBtn.addActionListener(lForButton); 
    frectBtn = new JButton("filled rectangle"); 
    frectBtn.addActionListener(lForButton); 
    froundedrectBtn = new JButton("filled rounded rectangle"); 
    froundedrectBtn.addActionListener(lForButton); 
    fovalBtn = new JButton("filled oval"); 
    fovalBtn.addActionListener(lForButton); 



    this.add(pencilBut); 
    this.add(brushBtn); 
    this.add(bckpaintBtn); 
    this.add(eraserBtn); 
    this.add(textBtn); 
    this.add(lineBtn); 
    this.add(rectBtn); 
    this.add(roundedrectBtn); 
    this.add(ovalBtn); 
    this.add(frectBtn); 
    this.add(froundedrectBtn); 
    this.add(fovalBtn); 





} 

public class ListenForButton implements ActionListener{ 

    @Override 
    public void actionPerformed(ActionEvent e) { 


     if (e.getSource() == brushBtn){ 

     } else if (e.getSource() == bckpaintBtn){ 

     } else if (e.getSource() == eraserBtn){ 

     } else if (e.getSource() == textBtn){ 

     } else if (e.getSource() == lineBtn){ 

     } else if (e.getSource() == rectBtn){ 
      System.out.println("rectangle"); 
      myPaint.rectangle(); 
     } else if (e.getSource() == roundedrectBtn){ 
      myPaint.roundedrectangle(); 
     } else if (e.getSource() == ovalBtn){ 
      myPaint.oval(); 
     } else if (e.getSource() == frectBtn){ 
      myPaint.filledrectangle(); 
     } else if (e.getSource() == froundedrectBtn){ 
      myPaint.filledroundedrectangle(); 
     } else if (e.getSource() == fovalBtn){ 
      myPaint.filledoval(); 
     } 


    } 

} 


} 

, 내가 부드럽게의 코드의 모든 부하를 실행할 때, 모든 패널과 내부의 모든 구성 요소를 볼 수 있지만 버튼을 클릭해도 아무런 변화가 없습니다. 나는 그것이 상속과 관련이 있다고 생각합니다. 또는 실제로 몇 가지 질문이 있습니다.

  1. 정확하게 이해 했습니까? 코드를 여러 * .java 파일로 나눠서 모든 클래스를 동일한 패키지에있는 다른 파일에 포함시켜야합니까? 또는 하나의 * .java 파일에 다양한 클래스를 포함해야합니까? (후자의 옵션이 좋다면, 누군가가 내 코드의 일부를 수정할 수 있습니까? 그래서 상속을 적절하게 통합하는 법을 알고 있습니까?) 일부 클래스는 JPanels와 JComponents를 확장합니다. 모델 (?)을 사용하여 JPanels 등 (보기) 확장하기
  2. Main.java 파일을 읽는 것이 좋습니다. menuSideBar.java 파일을 다른 파일에있는 JPanels로 가져 와서 sideBar1.java 안에있는 menuSideBar.java 패널을 읽으시겠습니까? 아니면 내가 어떤 패널 정의해야하는 메인 클래스의 어떤 패널로 전환?
  3. 왜 내가 잘못 뭐하는 거지의 sideBar1.java?를 JButton의의 ActionListener를 읽는하지 Paint.java입니까?

감사합니다 죄송합니다. 당신에게 분명하지만, 책이나 튜토리얼에있는 모든 예제는 매우 간단한 상속 예제와 아주 단순한 예제를 가지고 있으며 어떻게 든 간단한 예제를 코드로 옮길 수 없다. 고맙습니다!

답변

2

당신이 가장 많이 필요로하는 문제는 당신이 필요할 때만 두 개의 그림 객체를 생성한다는 것입니다. 이 항목을 직접 확인하려면이 페이지에서 new Paint()이 몇 번이나 있는지 검색하십시오. 코드에서 한 번만보아야하며 두 번 볼 수 있습니다.

왜이 점이 중요합니까? 하나의 Paint 객체는 GUI에 표시되고 다른 객체는 표시되지 않지만 ActionListener에서 버튼을 누르면 해당 객체가 호출됩니다.표시되지 않은 객체에 대한 메소드 호출은 표시된 객체에서 보이는 응답으로 변환되지 않습니다.

잘못된 해결책은 페인트 변수를 정적으로 만들어 모든 곳에서 공유하는 것입니다. 당신이 OOP의 이점을 잃고 버그의 위험을 증가시키는 것은 잘못된 것입니다. 시각화 된 Paint 객체의 참조를 필요한 곳에있는 ActionListener에 전달하여 하나의 Paint 객체 만 생성하고 표시되는 것과 동일한 Paint 객체의 수신기에서 메서드를 호출하는 것이 좋습니다.

보다 구체적인이 변경이 행

sidePanel = new menuSideBar(); //this is the sidebar 
myPaint = new Paint(); // this is the drawing board 

:

myPaint = new Paint(); // call this first 
sidePanel = new menuSideBar(myPaint); // and pass it in 

를 사이드 바 생성자에서 (클래스가 사이드 바를 변경한다)를 사용 파라미터 :

public sideBar(Paint myPaint) { 
    this.myPaint = myPaint; 
    // .... all other constructor code 
} 

및 사이드 바에서 new Paint() 제거하십시오.

+0

고맙습니다! 나는 당신의 제안을 따랐고 지금은 모든 것이 완벽하게 작동합니다 !!! 고맙습니다! – Dominika