Java Repaint()重新定位按钮

Java Repaint()重新定位按钮,java,swing,Java,Swing,我正在编写一个Java程序,它将根据按下的按钮绘制一个圆或矩形。虽然它确实绘制了给定的形状,但在绘制时它会在窗口的左上角(很可能是0,0)创建新按钮。我是否违反了绘画()或重绘()的某些规则 这是我的班级: import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JBut

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

这是我的班级:

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();
}
}
这与
重绘
几乎没有关系,一切都与你违反绘画常规有关

首先看一看,了解绘画作品的更多细节

paint
通过调用
paintComponent
paintBorder
paintChildren
来委派其职责。当您重写
paint
并未能调用它的
super
方法时,您就违反了这一职责,最终会出现像现在这样的问题

图形
上下文是Swing组件之间的共享资源。在绘制周期中绘制的每个组件都会获得相同的
图形。这意味着,首先要做的事情之一是为组件绘制
图形
上下文。这通常是通过不再调用的
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);
        }    
    }
但当我这样做的时候,以前画的东西被抹掉了

是的,这就是绘画的工作原理。这是破坏性的。每次执行绘制过程时,您都需要重新绘制组件在该时间点的整个状态

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

  • 将所有内容绘制到背景缓冲区(图像)并绘制
  • 将重新绘制上下文所需的“命令”存储在某种
    列表中
  • 这两方面的例子都有很多,与
    重新绘制有关,与违反绘画常规有关

    首先看一看,了解绘画作品的更多细节

    paint
    通过调用
    paintComponent
    paintBorder
    paintChildren
    来委派其职责。当您重写
    paint
    并未能调用它的
    super
    方法时,您就违反了这一职责,最终会出现像现在这样的问题

    图形
    上下文是Swing组件之间的共享资源。在绘制周期中绘制的每个组件都会获得相同的
    图形。这意味着,首先要做的事情之一是为组件绘制
    图形
    上下文。这通常是通过不再调用的
    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);
            }    
        }
    
    但当我这样做的时候,以前画的东西被抹掉了

    是的,这就是绘画的工作原理。这是破坏性的。每次执行绘制过程时,您都需要重新绘制组件在该时间点的整个状态

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

  • 将所有内容绘制到背景缓冲区(图像)并绘制
  • 将重新绘制上下文所需的“命令”存储在某种
    列表中

  • 这两种方法都有很多例子

    我可以问一下为什么不使用某种形式的布局管理器吗?这背后的动机将是让你的按钮和绘画居住在各自的布局。这样,当调用repaint时,它只在特定的布局部分调用它。为了澄清,我可以问一下为什么不使用某种形式的布局管理器吗?这背后的动机将是让你的按钮和绘画居住在各自的布局。这样,当调用repaint时,它只在特定的布局部分调用它。