【问题标题】:Trying to create a program that draws an ellipse using parametric equation, but the lines aren't showing. Why? (Java)试图创建一个使用参数方程绘制椭圆的程序,但没有显示线条。为什么? (爪哇)
【发布时间】:2015-08-25 23:43:13
【问题描述】:

我正在尝试创建一个程序,该程序使用参数方程可以在线条之间绘制线条并创建一个椭圆。这是我的代码:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;

import javax.swing.JFrame;


public class test extends JFrame{

    ArrayList<Line2D> lines = new ArrayList<>();
    public test(){
        this.setTitle("test");
        this.setSize(800, 600);
        this.setLocationRelativeTo(null);
        this.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        drawCircle(3,3.0,3.0);

        this.setVisible(true);


        System.out.println(lines.size());
    }

    public void drawCircle(int radio, double xCenter, double yCenter) {
        double t = 0;
        double xPoint;
        double yPoint;
        double xActual = xCenter;
        double yActual = yCenter + radio*Math.sin(0);
        t += 0.01;

        while(t < 360) {
            xPoint = xCenter + radio*Math.cos(t);
            yPoint = yCenter + radio*Math.sin(t);

           lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));
           this.repaint();

            t += 0.01;
            xActual = xPoint;
            yActual = yPoint;
        }
    }

     public void paint(Graphics g) {
         super.paint(g);

         for(Line2D s : lines){
             ((Graphics2D) g).draw(s);
         }
     }
}

我没有收到任何错误,但这些线条似乎没有出现在框架中。我做错了什么?

【问题讨论】:

  • 您的示例甚至无法编译

标签: java


【解决方案1】:

欢迎来到精彩的世界,了解为什么不应该从 JFrame 扩展以及为什么不应该覆盖 paint 的顶级容器,例如 JFrame

主要问题是,框架有边框。如果您覆盖JFramepaint 并在0x0 处绘制,您实际上将在框架下进行绘制。您的圆圈(比例为 3)足够小,可以完全绘制在窗口的标题栏下方。

请参阅 How to get the EXACT middle of a screen, even when re-sizedHow can I set in the midst?Java AWT drawString() does not display on window 了解此问题的示例以及为什么不应该覆盖顶级容器的 paint

相反,使用JPanel 之类的组件并覆盖它的paintComponent 并将您的自定义绘画放置在那里。然后将其放在JFrame 的实例中,例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test extends JFrame {

    public static void main(String[] args) {
        new Test();
    }

    public Test() throws HeadlessException {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Test");
                frame.add(new TestPane());
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        ArrayList<Line2D> lines = new ArrayList<>();

        public TestPane() {
            drawCircle(3, 3.0, 3.0);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setColor(Color.RED);
            System.out.println(lines.size());
            for (Line2D s : lines) {
                g2d.draw(s);
            }
            g2d.dispose();
        }

        public void drawCircle(int radio, double xCenter, double yCenter) {
            double t = 0;
            double xPoint;
            double yPoint;
            double xActual = xCenter;
            double yActual = yCenter + radio * Math.sin(0);
            t += 0.01;

            while (t < 360) {
                xPoint = xCenter + radio * Math.cos(t);
                yPoint = yCenter + radio * Math.sin(t);

//              System.out.println(xActual + "x" + yActual + "x" + xPoint + "x" + yPoint);
                lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));

                t += 0.01;
                xActual = xPoint;
                yActual = yPoint;
            }
        }
    }

}

您的下一个问题将是,0x0(或足够接近它)是圆的中心点。您需要能够在生成形状时计算x/y 偏移量,以便圆的上/左角位于0x0

例如,在测试您的代码时,我将radio 增加到100(看看它是否有任何不同,这就是我发现您在框架下绘画的方式)并且它生成了类似.. .

【讨论】:

  • 效果很好。谢谢!我会阅读您建议的内容,因为我不太明白为什么它不能使用 JFrame 进行绘制,而我之前已经完成了。
  • 查看thisthis 示例,了解为什么覆盖顶级容器的paint 通常是个坏主意
【解决方案2】:

在任何情况下都应在paintComponent(Graphics) 中进行摇摆绘图,而不是在article 中描述的paint。我建议您使用JPanel 或任何其他非顶级组件进行绘画——这是常见的习惯。 还有

...
lines.add(new Line2D.Double(xActual, yActual, xPoint, yPoint));
this.repaint();
...

这个重绘调用会导致一些非常丑陋的行为,并且非常浪费资源(每个添加的形状 36000 次无用的重绘)。

【讨论】:

  • 调用 repaint() 方法有什么问题?
  • @rasperryPi 在你的情况下,什么都没有,因为窗口没有显示。
  • “首先你在绘画之前没有设置任何颜色” - 不正确。 Graphics 上下文通常设置为在调用绘制方法之前设置组件的前景色。然而,这可能会通过后续调用链中的其他绘制方法来改变,但在我的简单测试中,它是黑色的。 “在任何情况下都应在 paintComponent(Graphics) 中进行摇摆绘图” - 虽然这是可取且强烈推荐的,但在某些情况下并非如此,此外,JFrame 没有 @ 987654328@方法。
  • @rasperryPi 在这个精确的例子中,实际上没有问题,正如 MadProgrammer 已经评论的那样。但是如果你重用这段代码来显示更多的形状,你将有 36000 次重绘,如果你只是添加一个形状,这是没有用的,而且相当浪费资源
  • 我还鼓励您尝试将您的建议添加到 OP 的代码中,看看它们是否有效,因为此时,这并不能回答 OP 的问题 ;)
【解决方案3】:

创建一个 Graphics2D 对象。它有助于。例如:

Graphics2D g2 = (Graphics2D)g;

完成后,您需要设置颜色。你没有这样做。示例:

g2.setColor(Color.BLACK);

也只是一个提示,覆盖paintComponent(Graphics g),不要覆盖paint()。

【讨论】:

  • setColorGraphics 的属性
  • 这似乎没有帮助:/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 2021-01-24
  • 1970-01-01
相关资源
最近更新 更多