Java 在JFrame中使用paint()时出错
当我尝试在Java 在JFrame中使用paint()时出错,java,swing,Java,Swing,当我尝试在JFrame中绘制一个椭圆形时,paint()方法不起作用,但是当我将JFrame更改为Frame时,就可以了。你能解释一下这个问题吗 import java.awt.Graphics; import java.awt.Window; import javax.swing.JFrame; public class Oval extends JFrame { public Oval() { // this.setLocationRelativeTo(null
JFrame
中绘制一个椭圆形时,paint()方法不起作用,但是当我将JFrame
更改为Frame
时,就可以了。你能解释一下这个问题吗
import java.awt.Graphics;
import java.awt.Window;
import javax.swing.JFrame;
public class Oval extends JFrame
{
public Oval()
{
// this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setSize(400, 400);
}
public void paint(Graphics g)
{
g.drawOval(40, 40, 40, 40);
}
public static void main(String []args)
{
new Oval();
}
}
paint()
。相反,将JPanel
添加到JFrame
并覆盖paintComponent(g)
super
方法。即使覆盖了paint()
调用super.paint()
(当然最好使用paintcomponent()
)你不应该重写
paint()
方法,而是在你的JFrame
中添加一个JPanel
,重写JPanel的paintComponent()
方法,在JPanel上绘制你的东西
下面是一个演示:
import javax.swing.*;
import java.awt.*;
public class Oval extends JFrame
{
public Oval()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
OvalPanel ovalPanel = new OvalPanel(100); // SIZE of oval is 100
ovalPanel.setPreferredSize(new Dimension(400, 400));
add(ovalPanel);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new Oval();
}
});
}
}
class OvalPanel extends JPanel
{
private final int SIZE;
public OvalPanel(final int size)
{
this.SIZE = size;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g); // Call the super class's paintComponent so that it does its appropriate rendering first.
g.drawOval((getWidth() - SIZE) >> 1, (getHeight() - SIZE) >> 1, SIZE, SIZE); // Center the oval
}
}
另外,如果您注意到,我使用了swingutites.invokeLater()
方法,并在那里调用了椭圆构造函数。我之所以这么做是因为Swing是线程不安全的,因此您应该在事件分派器线程中调用任何与Swing相关的方法,该线程负责处理任何与Swing相关的内容,invokeLater()
方法就是这样做的
注意:如果您使用的是JDK 8,那么可以将SwingUtilities.invokeLater()
语句编写为:
SwingUtilities.invokeLater(Oval::new); // That's JDK 8 Method reference feature.
您可能想知道为什么不应该直接在paint()
方法中进行操作。原因与调用paint()
方法的方式有关。您可以看到,RepaintManager
负责处理所有基于Swing的组件的绘制,当调用paint()
方法时,它依次调用paintComponent()
、paintChildren()
和paintBorder()
方法paintComponent()
是处理任何基于组件的渲染的最佳位置,这就是为什么建议这样做的原因。但是,即使以下代码也可以工作:
import javax.swing.*;
import java.awt.*;
public class Oval extends JFrame
{
public Oval()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 400);
setLocationRelativeTo(null);
setVisible(true);
}
public void paint(Graphics g)
{
super.paint(g); // Calling the super class's paint method first.
// so that it handles its rendering.
g.drawOval(40, 40, 40, 40);
}
public static void main(String[] args)
{
new Oval();
}
}
甚至调用方法的顺序在Swing中也很重要。比如:
setSize(400, 400); // Setting the size of JFrame first.
setLocationRelativeTo(null); // Locating the JFrame based on its size then.
setVisible(true); // Finally its made visible
以上工作均按预期进行。但以下内容无法正确显示结果:
setVisible(true); // JFrame is already made visible
setLocationRelativeTo(null); // This first locates the JFrame based on its (0, 0) size
setSize(400, 400); // Then its size is increased. Not as expected as the JFrame appears shifted from center.
一组注释:a)无关:-相反,重写getter以返回比默认情况下计算的大小更合适的大小提示b)paintComponent的实现违反了面板的约定,即使用完全不透明的颜色填充其所有区域color@kleopatra:我已经根据你的评论更新了我的答案,希望它们能满足您提到的两种编码实践。谢谢。+1,谢谢!尽管(挑剔了一点:-):严格来说,您的getXXSize实现违反了方法契约(没有返回以前可能设置的xx)@kleopatra:现在更新了答案。我认为现在任何吹毛求疵的做法都不会奏效D+1,感谢您在此链接中的回答。this.setVisible(true);这个。设置大小(400400);当我使用frame而不是Jframe时,它的工作正常吗??