2015-05-06 2 views
1

Как очистить одну фигуру от моего JFrame, не делая экран белым.Мигающая белая графика Java

import java.awt.AlphaComposite; 
import java.awt.BasicStroke; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.util.HashMap; 
import java.util.Map.Entry; 
import java.util.Random;` 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 


public class Frame extends JFrame { 
static Shape s; 
Graphics2D g2D; 
/** 
* 
*/ 
private static final long serialVersionUID = 7764273188525543212L; 
private JPanel contentPane; 
public Point startDrag = null, endDrag = null; 
HashMap<Shape, Color> shapes = new HashMap<Shape, Color>(); 
/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 
    Frame f = new Frame(); 
    f.setVisible(true); 
} 
/** 
* Create the frame. 
*/ 
public Frame() { 

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 450, 300); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    contentPane.setLayout(new BorderLayout(0, 0)); 
    setContentPane(contentPane); 
    addMouseListener(new MouseAdapter() { 

     @Override 
     public void mousePressed(MouseEvent e) { 
      startDrag = new Point(e.getX(), e.getY()); 
      endDrag = startDrag; 
      repaint(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      Shape s = makeRectangle(startDrag.x, startDrag.y, e.getX(), 
        e.getY()); 
      Color[] colors = {Color.MAGENTA, Color.CYAN, Color.RED, 
        Color.BLUE, Color.PINK, Color.yellow}; 
      Random r = new Random(); 
      int i = r.nextInt(colors.length - 1); 
      shapes.put(s, colors[i]); 
      endDrag = null; 
      startDrag = null; 
      repaint(); 
     } 

    }); 
    addMouseMotionListener(new MouseMotionAdapter() { 



     @Override 
     public void mouseDragged(MouseEvent e) { 
      endDrag = new Point(e.getX(), e.getY()); 
      repaint(); 

     } 
    }); 
} 
public void paint(Graphics g) { 
    Graphics2D g2 = (Graphics2D) g; 
    paintBackground(g2); 
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 
      0.50f)); 
    g2.setStroke(new BasicStroke(2)); 
    for (Entry<Shape, Color> s : shapes.entrySet()) { 

     g2.setPaint(Color.BLACK); 
     g2.draw(s.getKey()); 
     g2.setPaint(s.getValue()); 
     g2.fill(s.getKey()); 
    } 
    if (startDrag != null) { 
     if (endDrag != null) { 

      g2.setStroke(new BasicStroke(5.0f)); 
      g2.setColor(Color.darkGray); 

      s = makeRectangle(startDrag.x, startDrag.y, endDrag.x, 
        endDrag.y); 
      g2.draw(s); 
     } 

    } 
} 
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) { 
    return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), 
      Math.abs(x1 - x2), Math.abs(y1 - y2)); 
} 
private void paintBackground(Graphics2D g2) { 
    clear(g2); 
    g2.setPaint(Color.red); 
    g2.setStroke(new BasicStroke(0.4f)); 
    for (int i = 0; i < getSize().width; i += 10) { 
     Shape line = new Line2D.Float(i, 0, i, getSize().height); 
     g2.draw(line); 
    } 

    for (int i = 0; i < getSize().height; i += 10) { 
     Shape line = new Line2D.Float(0, i, getSize().width, i); 
     g2.draw(line); 
    } 

} 

private void clear(Graphics g) { 
    g.clearRect(0, 0, getWidth(), getHeight()); 

} 

} 

// If you try this code, just drag and let go to make a rectangle. 

Но когда я перетаскиваю, экран мигает белым, поэтому мне трудно понять, что я делаю. Есть ли способ сделать эту работу таким же образом, но это ускоряет JFrame быстрее, чем вы можете видеть?

+1

См. [Живопись в AWT и Swing] (http://www.oracle.com/technetwork/java/painting-140037.html) и [Выполнение пользовательской живописи] (http://docs.oracle.com/javase/tutorial/uiswing/painting /) для получения дополнительной информации о живописи в Swing – MadProgrammer

+0

@MadProgrammer Я знаю, как рисовать, но я просто хочу, чтобы она выглядела более гладкой. – Orion31

+2

Но вы не понимаете, как работает система. Компоненты верхнего уровня НЕ заполняются двойным буфером, это означает, что они красят DIRECTLY на устройство, по одному шагу за раз, что и вызывает проблемы. Вместо этого вы должны использовать компонент Swing и переопределить его 'paintComponent' (как предложено в документации), поскольку компоненты Swing имеют двойной буфер. Он также призывает вас отделить ваш код, что делает его более пригодным для повторного использования. – MadProgrammer

ответ

2

Не рисуйте непосредственно в JFrame. Вместо этого нарисуйте метод paintComponent(Graphics g) JPanel. Обязательно вызовите super.paintComponent(g) в пределах вашего переопределения. Это даст вам двойную буферизацию по умолчанию и может помочь некоторым мигать.

например,

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.Stroke; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Rectangle2D; 
import java.awt.image.BufferedImage; 
import java.util.LinkedHashMap; 
import java.util.Map; 
import java.util.Random; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class DrawPanel extends JPanel { 
    private static final int PREF_W = 450; 
    private static final int PREF_H = 300; 
    private static final int SMALL_SQR_SIZE = 10; 
    private static final Stroke STROKE_5 = new BasicStroke(5f); 
    private static final Stroke STROKE_2 = new BasicStroke(2f); 
    private static final Color[] COLORS = { Color.MAGENTA, Color.CYAN, Color.RED, 
     Color.BLUE, Color.PINK, Color.yellow }; 
    private Random random = new Random(); 
    private BufferedImage background; 
    private Map<Shape, Color> shapes = new LinkedHashMap<>(); // so order is maintained 
    private Shape drawingShape = null; 

    public DrawPanel() { 
     background = createBackground(); 
     MyMouseAdapater myMouseAdapater = new MyMouseAdapater(); 
     addMouseListener(myMouseAdapater); 
     addMouseMotionListener(myMouseAdapater); 
    } 

    private BufferedImage createBackground() { 
     BufferedImage bg = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = bg.createGraphics(); 
     g2.setPaint(Color.red); 
     // g2.setStroke(new BasicStroke(BASIC_STROKE_POINTS)); 
     for (int i = 0; i < PREF_W; i += SMALL_SQR_SIZE) { 
     g2.drawLine(i, 0, i, PREF_H); 
     } 

     for (int i = 0; i < PREF_H; i += SMALL_SQR_SIZE) { 
     g2.drawLine(0, i, PREF_W, i); 
     } 

     g2.dispose(); 
     return bg; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (background != null) { 
     g.drawImage(background, 0, 0, null); 
     } 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setStroke(STROKE_2); 
     for (Shape shape : shapes.keySet()) { 
     g2.setColor(Color.black); 
     g2.draw(shape); 
     g2.setColor(shapes.get(shape)); 
     g2.fill(shape); 
     } 
     if (drawingShape != null) { 
     g2.setStroke(STROKE_5); 
     g2.setColor(Color.DARK_GRAY); 
     g2.draw(drawingShape); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyMouseAdapater extends MouseAdapter { 
     private Point initP = null; 
     @Override 
     public void mousePressed(MouseEvent e) { 
     if (e.getButton() != MouseEvent.BUTTON1) { 
      return; 
     } 
     initP = e.getPoint(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
     if (initP == null) { 
      return; 
     } 
     Point p = e.getPoint(); 
     drawingShape = makeRectangle(p.x, p.y, initP.x, initP.y); 
     repaint(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
     if (initP == null) { 
      return; 
     } 
     Point p = e.getPoint(); 
     Shape newShape = makeRectangle(p.x, p.y, initP.x, initP.y); 
     shapes.put(newShape, COLORS[random.nextInt(COLORS.length)]); 

     drawingShape = null; 
     initP = null; 
     repaint();   
     } 

     private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) { 
     return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), 
       Math.abs(x1 - x2), Math.abs(y1 - y2)); 
     } 
    } 

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

     JFrame frame = new JFrame("DrawPanel"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

Обратите внимание, что я продлил JPanel, так что можно использовать его метод paintComponent, и я назвал супер метод. Я также использовал LinkedHashMap, чтобы сохранить порядок ввода Карты.

+0

Должен ли я использовать ' paintComponent (GetGraphics())? Как мне это сделать? – Orion31

+0

@ R.S: Нет - определенно нет. Вы захотите использовать объект Graphics, указанный в методе JVM. Подождите ... маленький пример. Также нарисуйте фоновое изображение в BufferedImage и покажите, что в paintComponent через 'g.drawImage (...)' –

+0

Должен ли я сделать JComponent или просто вызвать paintComponent в 'public void paint (Graphics g)' override? – Orion31

Смежные вопросы