重绘时文本字段变形

Text Field Deforming on Repaint

我有一个非常简单的 JFrame(它只包含一个文本字段和我画的很多东西),尽管每当调用 repaint() 时文本字段都会发生变化。我很确定它是 repaint(),因为即使当我将帧从一个显示器拖到另一个显示器时,以及每当我在代码中调用它时,它都会发生。

当我 运行 程序时它开始正常:

但是,每当调用 repaint() 时,都会发生这种情况:

如果我开始在该字段中键入内容,其余内容会立即弹出并正常工作。最终,我的最终目标是将框架的大部分重置为在 paintComponent() 中绘制的内容,同时仍然使文本字段可见。

我对图形和绘画比较陌生,非常感谢任何帮助!

编辑

在创建 SSCCE 时,我发现文本字段的问题是由我的 paintComponent 方法中的 Graphics2D 方法旋转引起的。我不知道为什么会这样,但我可以解决它并认为该问题已解决。

现在,我遇到了一个新问题:我的 paintComponent 方法被调用了太多次。下面是这个问题的 SSCCE,我希望事情发生的顺序是:

  1. 调用 paintComponent()
  2. (按下按钮时)调用 repaint()
  3. (按下按钮时,但在重绘之后)调用 paintStuff()

这一切都发生了,但是之后 paintComponent 以某种方式被调用,擦除 paintStuff() 绘制的所有内容。

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class tester extends JFrame {

    private JPanel contentPane;
    private JButton button;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    tester frame = new tester();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public tester() {
        setBounds(100, 100, 450, 300);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        contentPane = new JPanel(){
            public void paintComponent(Graphics g1) {
                System.out.println("draw rectangle - should be first");
                super.paintComponent(g1);

                g1.drawRect(50,50,50,50);
            }
        };
        contentPane.setLayout(null);
        setContentPane(contentPane);

        button = new JButton("Click me!");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("repaint - should be second");
                repaint();

                paintStuff(contentPane.getGraphics());
            }
        });
        button.setBounds(10, 11, 95, 20);
        contentPane.add(button);
    }

    public void paintStuff(Graphics g){
        System.out.println("draw circle - should be last");
        g.drawOval(100,100,10,10);
    }

}
paintStuff(contentPane.getGraphics());

不,不要使用 getGraphics() 方法进行绘画。要重新绘制组件,您只需使用:

contentPane.repaint();

然后将 drawOval(...) 语句移动到 paintComponent() 方法。

如果您想有条件地绘制椭圆,则需要为您的自定义绘画创建一个布尔值 属性。然后代码看起来像:

super.paintComponent(g1);

g1.drawRect(50,50,50,50);

if (drawOval)
    g1.drawOval(100,100,10,10);    

然后在您的 class 中创建一个方法,例如:

public void setDrawOval(Boolean drawOval)
{
    this.drawOval = drawOval;
    repaint();
}

因此在 ActionListener 中您只需使用:

contentPane.setDrawOval(true);