Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JFrame中使用paint()时出错_Java_Swing - Fatal编程技术网

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时,它的工作正常吗??