重绘时文本字段变形
Text Field Deforming on Repaint
我有一个非常简单的 JFrame(它只包含一个文本字段和我画的很多东西),尽管每当调用 repaint() 时文本字段都会发生变化。我很确定它是 repaint(),因为即使当我将帧从一个显示器拖到另一个显示器时,以及每当我在代码中调用它时,它都会发生。
当我 运行 程序时它开始正常:
但是,每当调用 repaint() 时,都会发生这种情况:
如果我开始在该字段中键入内容,其余内容会立即弹出并正常工作。最终,我的最终目标是将框架的大部分重置为在 paintComponent() 中绘制的内容,同时仍然使文本字段可见。
我对图形和绘画比较陌生,非常感谢任何帮助!
编辑
在创建 SSCCE 时,我发现文本字段的问题是由我的 paintComponent 方法中的 Graphics2D 方法旋转引起的。我不知道为什么会这样,但我可以解决它并认为该问题已解决。
现在,我遇到了一个新问题:我的 paintComponent 方法被调用了太多次。下面是这个问题的 SSCCE,我希望事情发生的顺序是:
- 调用 paintComponent()
- (按下按钮时)调用 repaint()
- (按下按钮时,但在重绘之后)调用 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);
我有一个非常简单的 JFrame(它只包含一个文本字段和我画的很多东西),尽管每当调用 repaint() 时文本字段都会发生变化。我很确定它是 repaint(),因为即使当我将帧从一个显示器拖到另一个显示器时,以及每当我在代码中调用它时,它都会发生。
当我 运行 程序时它开始正常:
但是,每当调用 repaint() 时,都会发生这种情况:
如果我开始在该字段中键入内容,其余内容会立即弹出并正常工作。最终,我的最终目标是将框架的大部分重置为在 paintComponent() 中绘制的内容,同时仍然使文本字段可见。
我对图形和绘画比较陌生,非常感谢任何帮助!
编辑
在创建 SSCCE 时,我发现文本字段的问题是由我的 paintComponent 方法中的 Graphics2D 方法旋转引起的。我不知道为什么会这样,但我可以解决它并认为该问题已解决。
现在,我遇到了一个新问题:我的 paintComponent 方法被调用了太多次。下面是这个问题的 SSCCE,我希望事情发生的顺序是:
- 调用 paintComponent()
- (按下按钮时)调用 repaint()
- (按下按钮时,但在重绘之后)调用 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);