Repaint()重定位按钮

时间:2018-07-10 21:40:07

标签: java swing

我正在编写一个Java程序,该程序将根据按下的按钮绘制一个圆形或矩形。虽然确实绘制了给定的形状,但在绘制时会在窗口的左上角(最有可能是((0,0)))创建新按钮。我是否违反了paint()/ repaint()的某些规则?

这是我的课程:

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

import javax.swing.JButton;
import javax.swing.JPanel;
public class Components extends JPanel implements ActionListener
{
  String em="Nothing";
  public Components()
{
    JButton c=new JButton("Rectangle");
    JButton b=new JButton("Circle");
    b.addActionListener(this);
    c.addActionListener(this);
    add(c, 0);
    add(b, 1);
    setBackground(Color.WHITE);
    setVisible(true);
}

public void actionPerformed(ActionEvent e)
{
    if(e.getActionCommand().equals("Rectangle"))
    {
        em="Rectangle";
        repaint();
    }
    else
    {
        em="Circle";
        repaint();
    }
}

public void paint(Graphics g)
{
    if(em.equals("Rectangle"))
    {
        g.drawRect(50, 50, 50, 50);
    }
    else if(em.equals("Circle"))
    {
        g.drawOval(50, 50, 50, 50);
    }

}

}

以及不太重要的JFrame类:

import java.awt.Graphics;

import javax.swing.JFrame;
public class Wndw extends JFrame
{
    public Wndw()
    {
        setTitle("Hello");
        setSize(400, 400);
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        add(new Components());
    }

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

1 个答案:

答案 0 :(得分:2)

repaint与(很少)有关,而与您违反绘画程序的一切有关

首先查看Performing Custom PaintingPainting in AWT and Swing,以详细了解绘画的工作原理。

paint通过调用paintComponentpaintBorderpaintChildren来委派职责。当您覆盖paint并无法调用它的super方法时,您将失去责任,最终会遇到像现在这样的问题。

Graphics上下文是Swing组件之间的共享资源。在绘制周期中绘制的每个组件都具有相同的Graphics。这意味着,应该做的第一件事之一是,Graphics上下文应为组件准备以在其上绘制。通常是通过paintComponent方法来完成的,而您不再调用该方法

要做的第一件事是停止覆盖paint,而通常建议覆盖paintComponent,这会限制您的总体责任并降低引入更多问题的风险。

接下来,在进行任何自定义绘画之前,请致电super.paintComponent ...

public class Components extends JPanel implements ActionListener
{
    //....
    @Overrride
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if(em.equals("Rectangle"))
        {
            g.drawRect(50, 50, 50, 50);
        }
        else if(em.equals("Circle"))
        {
            g.drawOval(50, 50, 50, 50);
        }    
    }
  

但是当我这样做时,以前的绘画会被删除

是的,这就是绘画的工作方式。这是破坏性的。每当执行绘制过程时,都应按该时间点重新绘制组件的整个状态。

如果希望保留以前绘制的内容,则有两个基本选择。

  1. 将所有内容绘制到后备缓冲区(图像)并绘制
  2. 以某种List的形式存储从头开始重绘上下文的“命令”

两者都有很多例子