图形未出现在Java Jframe画布中

图形未出现在Java Jframe画布中,java,Java,我试图在一个Jframe中画一个藤蔓,但是当我运行程序时,图形没有出现。这个想法是,一个“藤”是随机产生的,可以随机分支到其他“藤”。如果有人能帮忙,我将不胜感激 import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; public class Vine extends JPanel

我试图在一个Jframe中画一个藤蔓,但是当我运行程序时,图形没有出现。这个想法是,一个“藤”是随机产生的,可以随机分支到其他“藤”。如果有人能帮忙,我将不胜感激

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

    public class Vine extends JPanel {
        public void paint(Graphics g, int a, int b, int c)
          {
            super.paint(g);
            g.setColor(Color.BLACK);
            g.drawLine(10, 10, 100, 100);
            grow(g, a, b, c);
          }
        public Boolean TF(){
            Boolean A;
            int B = ((int)Math.random()+1);
            if (B==1){
                A = true;
            } else {
                A = false;
            }
            return A;
        }
        public void grow(Graphics g, int a, int b, int c){
            int x = a;
            int y = b;
            int age = c;
            for (int i=0; i<= age; i++) {
                if (TF()) {
                    if (TF()) {
                        grow(g, x, y, ((age-i)/2));
                    }
                }
                if (TF()){
                    if (TF()){
                        g.drawLine(x, y, (x+1), y);
                        x++;
                    } else {
                        g.drawLine(x, y, (x-1), y);
                        x++;
                    }
                } else {
                    g.drawLine(x, y, x, (y+1));
                    y++;
                }
            }
        }
        public static void main(String[] args)
          {
            JFrame f = new JFrame("Vine");
            f.setBounds(300, 300, 200, 120);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Vine panel = new Vine();
            Container c = f.getContentPane();
            panel.setBackground(Color.WHITE);
            c.add(panel);
            f.setResizable(true);
            f.setVisible(true);
          }
    }
导入java.awt.Color;
导入java.awt.Container;
导入java.awt.Graphics;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类JPanel{
公共空隙油漆(图形g、内部a、内部b、内部c)
{
超级油漆(g);
g、 设置颜色(颜色为黑色);
g、 抽绳(10、10、100、100);
生长(g,a,b,c);
}
公共布尔TF(){
布尔A;
int B=((int)Math.random()+1);
如果(B==1){
A=真;
}否则{
A=假;
}
返回A;
}
公共空间增长(图形g、整数a、整数b、整数c){
int x=a;
int y=b;
int age=c;

对于(int i=0;i,这里有很多实现问题。您可以覆盖JPanel的
paintComponent
,在其中进行绘制。下面是一个快速修复程序,演示如何完成此操作。我对您的实现进行了大量更改,以解决这些问题,以便您能够了解情况

注意:这是一个快速解决方案。因此,代码质量较低,一些OOP概念被忽略。只需完成此过程,了解其工作原理并实现您自己的代码

说明:

您必须调用JPanel类的
repaint
方法使其自身重新绘制。它也会将LinkedList中的所有行绘制到面板(请参阅实现)。重新绘制后,创建一个新的随机行并将其添加到LinkedList。下次将绘制它

然后我们必须对此设置动画。因此我在
Vine
类中实现了
runnable
接口。当我们将此Vine对象(面板)添加到
线程和
start()时,将调用
run
方法
线程。我们需要永远运行它。因此,在
运行
方法中添加一个循环。然后每次调用运行方法时,
重新绘制
面板
。此动画太快,因此添加
线程.sleep()
以减慢动画速度

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.util.LinkedList;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Line {//Line class to store details of lines

    int x1, y1, x2, y2;

    public Line(int x1, int y1, int x2, int y2) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }
}

class Vine extends JPanel implements Runnable {//implements runnable to animate it

LinkedList<Line> lines = new LinkedList<>();//LinkedList to store lines

int x = 10;
int y = 10;
Line line;

public Boolean TF() {
    Boolean A;
    int B = (int) (Math.random() * 2 + 1);//logical error fixed
    if (B == 1) {
        A = true;
    } else {
        A = false;
    }
    return A;
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(Color.BLACK);

    for (Line line : lines) {//paint all lines in the LinkedList
        g.drawLine(line.x1, line.y1, line.x2, line.y2);
    }

    //Create and add a next line
    if (TF()) {
        if (TF()) {
            line = new Line(x, y, (x + 1), y);
            lines.add(line);
            x++;
        } else {
            line = new Line(x, y, (x - 1), y);
            lines.add(line);
            x++;
        }
    } else {
        line = new Line(x, y, x, (y + 1));
        lines.add(line);
        y++;
    }
}

private static Vine panel;

public static void main(String[] args) {
    JFrame f = new JFrame("Vine");
    f.setSize(300, 300);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel = new Vine();
    Container c = f.getContentPane();
    panel.setBackground(Color.WHITE);
    c.add(panel);
    f.setResizable(true);
    f.setVisible(true);
    panel.start();//start the animation(thread)
}

private void start() {
    Thread thread = new Thread(this);
    thread.start();
}

@Override
public void run() {
    while (true) {

        try {
            Thread.sleep(100);//slow down the animation
            panel.repaint();//then repaint the panel
        } catch (InterruptedException ex) {

        }
    }
}
}
导入java.awt.Color;
导入java.awt.Container;
导入java.awt.Graphics;
导入java.util.LinkedList;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
类Line{//Line类来存储行的详细信息
int-x1,y1,x2,y2;
公用线路(int x1、int y1、int x2、int y2){
这是1.x1=x1;
这是1.y1=y1;
这是0.x2=x2;
这1.y2=y2;
}
}
类Vine扩展了JPanel implements Runnable{//implements Runnable使其动画化
LinkedList lines=新建LinkedList();//用于存储行的LinkedList
int x=10;
int y=10;
线条;
公共布尔TF(){
布尔A;
int B=(int)(Math.random()*2+1);//修复了逻辑错误
如果(B==1){
A=真;
}否则{
A=假;
}
返回A;
}
@凌驾
受保护组件(图形g){
超级组件(g);
g、 设置颜色(颜色为黑色);
对于(行:行){//绘制LinkedList中的所有行
g、 抽绳(线x1、线y1、线x2、线y2);
}
//创建并添加下一行
if(TF()){
if(TF()){
直线=新线(x,y,(x+1),y);
行。添加(行);
x++;
}否则{
直线=新线(x,y,(x-1),y);
行。添加(行);
x++;
}
}否则{
直线=新线(x,y,x,(y+1));
行。添加(行);
y++;
}
}
私人静电屏;
公共静态void main(字符串[]args){
JFrame f=新的JFrame(“藤”);
f、 设置大小(300300);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
面板=新藤();
容器c=f.getContentPane();
面板.立根背景(颜色.白色);
c、 添加(面板);
f、 可设置大小(真);
f、 setVisible(真);
panel.start();//启动动画(线程)
}
私有void start(){
螺纹=新螺纹(此);
thread.start();
}
@凌驾
公开募捐{
while(true){
试一试{
Thread.sleep(100);//减慢动画速度
panel.repaint();//然后重新绘制面板
}捕获(中断异常例外){
}
}
}
}

此代码有几个问题:

  • 没有人调用
    paint(Graphics g,int a,int b,int c)
    方法。当您从这样的Swing组件继承时,有几个方法“自动”调用(其中有一个
    paint(Graphics g)
    方法)。但是要执行自定义绘制,通常应覆盖
    绘制组件(图形g)
    方法

  • 您正在绘制时生成随机数。这会产生一些奇怪的效果。最明显的效果是:当您调整帧的大小时(或发生导致重新绘制帧的其他情况时),将出现一个新的随机藤蔓。它与前一个藤蔓没有任何共同之处,在最好的情况下,会造成闪烁的混乱

  • 为了创建仍然是“随机”的可重复生成的结果,我通常建议不要使用
    Math.random()
    (事实上,我从来没有使用过它)。
    java.util.random
    类通常更可取。它允许创建可重复的随机数序列(这有助于调试),它提供了方便的方法,如
    Random 35; nextBoolean()
    ,这正是您可能希望通过(实现有些奇怪的)
    TF()
    方法实现的效果。这引出了下一点…:

  • 使用更好的变量和方法名称。命名变量,如中的
    c
    import java.awt.Color;
    import java.awt.Container;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.geom.Path2D;
    import java.util.Random;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class VinePainting
    {
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                @Override
                public void run()
                {
                    createAndShowGUI();
                }
    
                private void createAndShowGUI()
                {
                    JFrame f = new JFrame("Vine");
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    VinePanel panel = new VinePanel();
                    Container c = f.getContentPane();
                    panel.setBackground(Color.WHITE);
                    c.add(panel);
                    f.setSize(500, 500);
                    f.setLocationRelativeTo(null);
                    f.setVisible(true);
                }
            });
        }
    }
    
    
    class VinePanel extends JPanel
    {
        private static final Random RANDOM = new Random(0);
        private Path2D vine;
    
        @Override
        protected void paintComponent(Graphics gr)
        {
            super.paintComponent(gr);
            Graphics2D g = (Graphics2D)gr;
            if (vine == null)
            {
                vine = createVine(getWidth()/2, getHeight());
            }
            g.setColor(Color.BLACK);
            g.draw(vine);
        }
    
        private Path2D createVine(int x, int y)
        {
            Path2D path = new Path2D.Double();
            double angleRad = Math.toRadians(-90);
            grow(path, x, y, angleRad, 10.0, 0, 30);
            return path;
        }
    
        private static void grow(Path2D path, 
            double x, double y, double angleRad, 
            double stepSize, int step, int steps)
        {
            if (step == steps)
            {
                return;
            }
            path.moveTo(x, y);
    
            double dirX = Math.cos(angleRad);
            double dirY = Math.sin(angleRad);
            double distance = random(stepSize, stepSize + stepSize);
            double newX = x + dirX * distance;
            double newY = y + dirY * distance;
            path.lineTo(newX, newY);
    
            final double angleRadDeltaMin = -Math.PI * 0.2;
            final double angleRadDeltaMax =  Math.PI * 0.2;
            double progress = (double)step / steps;
            double branchProbability = 0.3;
            double branchValue = RANDOM.nextDouble();
            if (branchValue + 0.1 < branchProbability)
            {
                double angleRadDelta = random(angleRadDeltaMin, angleRadDeltaMax);
                double newAngleRad = angleRad + angleRadDelta;
                double newStepSize = (1.0 - progress * 0.1) * stepSize;
                grow(path, newX, newY, newAngleRad, newStepSize, step+1, steps);
            }
            double angleRadDelta = random(angleRadDeltaMin, angleRadDeltaMax);
            double newAngleRad = angleRad + angleRadDelta;
            double newStepSize = (1.0 - progress * 0.1) * stepSize;
            grow(path, newX, newY, newAngleRad, newStepSize, step+1, steps);
        }
    
        private static double random(double min, double max)
        {
            return min + RANDOM.nextDouble() * (max - min);
        }
    
    
    }
    
    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Vine implements Runnable {
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Vine");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            DrawingPanel panel = new DrawingPanel(400, 400);
            frame.add(panel);
    
            frame.pack();
            frame.setVisible(true);
    
            new GrowVine(panel, 400, 400).run();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Vine());
        }
    
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = -8460577623396871909L;
    
            private List<LineSegment> lineSegments;
    
            public DrawingPanel(int width, int height) {
                this.setPreferredSize(new Dimension(width, height));
                this.lineSegments = new ArrayList<>();
            }
    
            public void setLineSegments(List<LineSegment> lineSegments) {
                this.lineSegments = lineSegments;
                repaint();
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(Color.BLACK);
    
                for (int i = 0; i < lineSegments.size(); i++) {
                    LineSegment ls = lineSegments.get(i);
                    Point s = ls.getStartPoint();
                    Point e = ls.getEndPoint();
                    g.drawLine(s.x, s.y, e.x, e.y);
                }
            }
        }
    
        public class GrowVine implements Runnable {
    
            private int width;
            private int height;
    
            private DrawingPanel drawingPanel;
    
            private List<LineSegment> lineSegments;
    
            public GrowVine(DrawingPanel drawingPanel, int width, int height) {
                this.drawingPanel = drawingPanel;
                this.lineSegments = new ArrayList<>();
                lineSegments.add(new LineSegment(10, 10, width - 10, height - 10));
                this.width = width;
                this.height = height;
            }
    
            @Override
            public void run() {
                grow(width / 2, height / 2, 200);
                drawingPanel.setLineSegments(lineSegments);
            }
    
            public void grow(int a, int b, int c) {
                int x = a;
                int y = b;
                int age = c;
                for (int i = 0; i <= age; i++) {
                    if (coinFlip()) {
                        if (coinFlip()) {
                            grow(x, y, ((age - i) / 2));
                        }
                    }
    
                    if (coinFlip()) {
                        if (coinFlip()) {
                            lineSegments.add(new LineSegment(x, y, (x + 1), y));
                            x++;
                        } else {
                            lineSegments.add(new LineSegment(x, y, (x - 1), y));
                            x++;
                        }
                    } else {
                        lineSegments.add(new LineSegment(x, y, x, (y + 1)));
                        y++;
                    }
                }
            }
    
            private boolean coinFlip() {
                return Math.random() < 0.50D;
            }
    
        }
    
        public class LineSegment {
            private final Point startPoint;
            private final Point endPoint;
    
            public LineSegment(int x1, int y1, int x2, int y2) {
                this.startPoint = new Point(x1, y1);
                this.endPoint = new Point(x2, y2);
            }
    
            public Point getStartPoint() {
                return startPoint;
            }
    
            public Point getEndPoint() {
                return endPoint;
            }
    
        }
    
    }