2013-10-10 6 views
1

저는 프로젝트에서 임의의 모양을 그리는 화면 보호기를 만들고 있습니다. 몇 가지 질문이 있지만 지금 당면한 주요 관심사는 모양을 화면에 표시하고 모양을 만든 후에 사라지지 않게하는 것입니다. 여기 내 코드가있다. 나는 어떤 루프도 사용할 수 없으며 내가 가지고있는 것의 기능을 변경하려고하지 않는다. (아마도 shapeDrawn을 제외하고).Java에서 그려진 도형을 사라지게 유지하는 방법은 무엇입니까?

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

public class ScreenSaver2 extends JPanel implements ActionListener { 
    private JFrame frame = new JFrame("FullSize"); 
    private Rectangle rectangle; 
    boolean full; 


    protected void paintComponent(Graphics g) { 
     int r = (int)(Math.random() * 255); 
     int gr = (int)(Math.random() * 255); 
     int b = (int)(Math.random() * 255); 
     Color color = new Color(r, gr, b); 
     int width = 10 + (int)(Math.random() * 40); 
     int height = 10 + (int)(Math.random() * 40); 
     int x = (int)(Math.random() * (getWidth() - width)); 
     int y = (int)(Math.random() * (getHeight() - height)); 
     int whichShape = (int)(Math.random() * 3); 
     int shapesDrawn = 0; 

     super.paintComponent(g); 
     if (shapesDrawn >= 30) { 
      shapesDrawn = 0; 
     } 

     switch (whichShape) { 
     case 0: 
      g.setColor(color); 
      g.drawLine(x, y, x + width, y + height); 
      shapesDrawn++; 
      break; 
     case 1: 
      g.setColor(color); 
      g.drawRect(x, y, width, height); 
      shapesDrawn++; 
      break; 
     case 2: 
      g.setColor(color); 
      g.drawRoundRect(x, y, width, height, 25, 25); 
      shapesDrawn++; 
      break; 
     case 3: 
      g.setColor(color); 
      g.drawOval(x, y, width, height); 
      shapesDrawn++; 
      break; 
     } 

    } 


    ScreenSaver2() { 
     // Remove the title bar, min, max, close stuff 
     frame.setUndecorated(true); 
     // Add a Key Listener to the frame 
     frame.addKeyListener(new KeyHandler()); 
     // Add this panel object to the frame 
     frame.add(this); 
     // Get the dimensions of the screen 
     rectangle = GraphicsEnvironment.getLocalGraphicsEnvironment() 
     .getDefaultScreenDevice().getDefaultConfiguration().getBounds(); 
     // Set the size of the frame to the size of the screen 
     frame.setSize(rectangle.width, rectangle.height); 
     frame.setVisible(true); 
     // Remember that we are currently at full size 
     full = true; 
     // set and initialize timer 
     Timer t = new Timer(500, this); 
     t.setDelay(500); 
     t.start(); 

    } 

    // This method will run when any key is pressed in the window 
    class KeyHandler extends KeyAdapter { 
     public void keyPressed(KeyEvent e) { 
      // Terminate the program. 
      if (e.getKeyChar() == 'x') { 
       System.out.println("Exiting"); 
       System.exit(0); 
      } 
      // Change background color 
      else if (e.getKeyChar() == 'r') { 
       System.out.println("Change background color"); 
       setBackground(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256))); 
       repaint(); 
      } 
      // Resize to half-screen 
      else if (e.getKeyChar() == 'z') { 
       System.out.println("Resizing"); 
       frame.setSize((int)rectangle.getWidth()/2, (int)rectangle.getHeight()); 
      } 
     } 
    } 

    public void actionPerformed(ActionEvent e) { 
     repaint(); 
    } 

    public static void main(String[] args) { 
     ScreenSaver2 obj = new ScreenSaver2(); 
    } 
} 
+0

왜 루프를 사용할 수 없습니까? – nhgrif

+0

@nhgrif 바보 같은 할당에 대한 제한 사항입니다 : P – MadProgrammer

+0

당신은 계속 임의의 모양으로 repaint()를 호출하고 있습니다. 그러나 오래된 페인트를 유지하고 싶습니다. ~^ \t 공개 무효의 actionPerformed (ActionEvent의 전자)과 같은 것을 – Sage

답변

7

오히려 직접 Graphics 콘텍스트에 paintComponent 내의 각각의 새로운 형태를 그림보다 제의 형상을 렌더링하고 Graphics 문맥이 페인트 백킹 버퍼를 사용한다.

이렇게하면 새 도형이 렌더링 될 때마다 간단한 카운터를 유지하면됩니다.

paintComponent이 많은 이유 때문에 호출 될 수 있기 때문에 이는 또한 번거롭습니다. 많은 것을 제어하지 않기 때문에 프로그램에서 타이머 틱이 실제로 발생하기 전에 더 많은 모양을 그리는 것이 가능할 수 있습니다. ..

는 예를 들어 당신이 남아있는 유일한 선택은 필요에 따라 각 변화를 칠 수있는에 역행 버퍼를 만드는 것입니다

업데이트되었습니다. 이렇게하면 페인트 사이클 사이에 각 변경 사항이 저장됩니다. 그런 다음 단순히

super.paintComponent(g); 
if (shapesDrawn >= 30) { 
    shapesDrawn = 0; 
} 

...

private BufferedImage img; 

//... 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2d = (Graphics2D) g.create(); 
    // Create the backing buffer 
    // This is a little cheat, creating a new image when the number of shapes 
    // exceeds the requirements, but it saves messing about with clearing 
    // a alpha image ;) 
    if (img == null || shapesDrawn >= 30) { 
     img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); 
     shapesDrawn = 0; 
    } else if (img.getWidth() != getWidth() || img.getHeight() != img.getHeight()) { 
     // Update the backing buffer to meet the requirements of the changed screen size... 
     BufferedImage buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); 
     Graphics2D gbuffer = buffer.createGraphics(); 
     gbuffer.drawImage(img, 0, 0, this); 
     gbuffer.dispose(); 
     img = buffer; 
    } 

    // Get a reference to the backing buffers graphics context... 
    Graphics2D gbuffer = img.createGraphics(); 

    // Paint the shapes to the backing buffer... 
    int r = (int) (Math.random() * 255); 
    int gr = (int) (Math.random() * 255); 
    int b = (int) (Math.random() * 255); 
    Color color = new Color(r, gr, b); 
    int width = 10 + (int) (Math.random() * 40); 
    int height = 10 + (int) (Math.random() * 40); 
    int x = (int) (Math.random() * (getWidth() - width)); 
    int y = (int) (Math.random() * (getHeight() - height)); 
    int whichShape = (int) (Math.random() * 3); 
    int shapesDrawn = 0; 

    switch (whichShape) { 
     case 0: 
      gbuffer.setColor(color); 
      gbuffer.drawLine(x, y, x + width, y + height); 
      shapesDrawn++; 
      break; 
     case 1: 
      gbuffer.setColor(color); 
      gbuffer.drawRect(x, y, width, height); 
      shapesDrawn++; 
      break; 
     case 2: 
      gbuffer.setColor(color); 
      gbuffer.drawRoundRect(x, y, width, height, 25, 25); 
      shapesDrawn++; 
      break; 
     case 3: 
      gbuffer.setColor(color); 
      gbuffer.drawOval(x, y, width, height); 
      shapesDrawn++; 
      break; 
    } 
    // Dispose of the buffers graphics context, this frees up memory for us 
    gbuffer.dispose(); 
    // Paint the image to the screen... 
    g2d.drawImage(img, 0, 0, this); 
    g2d.dispose(); 
} 

은 아마도 내가 지금까지 먹어 본 최악의 조언을

변화를주고 ... 화면이 페인트 수 있습니다 ..

if (shapesDrawn >= 30) { 
    super.paintComponent(g); 
    shapesDrawn = 0; 
} 
+0

오늘 아침 교수님과 이야기를 나누었고 모든 것을 paintComponent로 옮기라고 구체적으로 말했습니다. 작동하지만 셰이프가 화면에 나타나지 않아 카운터가 작동하는지 알 수 없습니다. – Ryel

+0

또한 @MadProgrammer 그것은 기본적으로 당신이 나를 도울 수있는 모든 것을 휴지통에 넣어야하기 때문에 좌절했다 – Ryel

+0

'paintComponent'가 호출 될 때마다 그래픽 컨텍스트가 지워질 것입니다. 이것은 예상되는 기능입니다. 루프를 사용하면 화면에 그림을 그리기 전에 출력을 먼저 버퍼에 페인팅하는 것이 유일한 선택입니다. – MadProgrammer

관련 문제