当我尝试在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();
}
}
答案 0 :(得分:3)
不要覆盖paint()
。而是将JPanel
添加到JFrame
并覆盖paintComponent(g)
调用super
方法。即使您覆盖paint()
来电super.paint()
(当然,最好使用paintComponnet()
)
答案 1 :(得分:2)
您不应该覆盖paint()
方法,而是向JPanel
添加JFrame
并覆盖JPanel's
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
}
}
另外如果您注意到,我使用了SwingUtlities.invokeLater()
方法,并在那里调用了Oval构造函数。我这样做是因为Swing是线程不安全的,所以你应该在Event Dispatcher Thread中调用任何与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.