【问题标题】:Drawing multiple lines with Java用Java画多条线
【发布时间】:2020-09-30 05:14:09
【问题描述】:

我正在学习计算机图形学,想用 Java Swing 画线。我想画多条线,它们会留下随机的颜色和随机的 x 和 y 点。我可以用这段代码顺利地画一条线:

package tugas1;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Tugas1 extends JPanel{
    
    public static int time = 0;
    public static int x1,y1,x2,y2;
    Color randomcolor;
    public Tugas1() {
        this.x1 = (int) (Math.random()*1280);
        this.y1 = (int) (Math.random()*720);
        this.x2 = (int) (Math.random()*1280);
        this.y2 = (int) (Math.random()*720);
        randomcolor = new Color((float)Math.random(),(float)Math.random(),(float)Math.random());
        // Inisialisasi timer untuk animasi
        javax.swing.Timer timer = new javax.swing.Timer(10, new ActionListener() {
          public void actionPerformed(ActionEvent e) {
              //menambah value variabel time secara berkala
              time++;
              repaint();
          }
       });
        timer.start();
    }
    
    public void garis(Graphics g, int xa, int ya, int xb, int yb){
        int count = 0;
      
        int a = xa;
        int b = ya;
        int dxa = ((xb - xa));
        int dya = ((yb - ya));
        g.setColor(randomcolor);
        if(dxa==0){
            if(dya > 0) {
                while(ya != yb && time>=count) {
                    ya++;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            } else {
                while(ya != yb && time>=count) {
                    ya--;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            }
        } else if(dya==0){
            if(dxa > 0) {
                while(xa != xb&& time>=count) {
                    xa++;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            } else {
                while(xa != xb&& time>=count) {
                    xa--;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            }
        } else{
            dxa = Math.abs(dxa);
            dya = Math.abs(dya);
            int pk = (dya < dxa) ? 2*dya - dxa : 2*dxa - dya;
            int dp = (dya < dxa) ? 2*(dya-dxa) : 2*(dxa-dya);

            boolean opr1 = (xa > xb);
            boolean opr2 = (ya > yb);

            while(xa != xb && ya != yb && time>=count) {
                if(pk > 0) {
                    if(opr1) xa-=1;
                    else xa+=1;

                    if(opr2) ya-=1;
                    else ya+=1;
                    pk += dp;
                }
                else {
                    if (dya < dxa) pk = pk + 2 * dya;
                    else pk = pk + 2 * dxa;
                    if(dxa>dya){
                        if(opr1) xa-=1;
                        else xa+=1;
                    }
                    else {
                        if(opr2) ya-=1;
                        else ya+=1;
                    }
                }
                g.drawLine(a,b,xa,ya);
                a = xa;
                b = ya;
                count++;
            }
        }
    }
    
    public void paintComponent(Graphics g) {
       super.paintComponent(g);
       this.setBackground(Color.BLACK);
       garis(g, x1, y1, x2, y2);
    }
    
    public static void main(String[] args) {
        JFrame fr = new JFrame("Gambar");
        fr.setSize(1280,720);      
        Tugas1 panelGambar = new Tugas1();
        fr.getContentPane().add(panelGambar);
        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fr.setVisible(true);
    }   
}

但是当我尝试通过单击按钮创建多行时,比如说 100 行,我的按钮不起作用(它只创建一行,并且动画消失了)。这是我创建多行的代码行:

package tugas1;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

public class Tugas1 extends JPanel{

    public static int time = 0;
    public static int x1,y1,x2,y2;
    Color randomcolor;
    public Tugas1(int x1, int y1, int x2, int y2, Color color) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.randomcolor = color;
        // Inisialisasi timer untuk animasi
        javax.swing.Timer timer = new javax.swing.Timer(10, new ActionListener() {
          public void actionPerformed(ActionEvent e) {
              //menambah value variabel time secara berkala
              time++;
              repaint();
          }
       });
        timer.start();
    }

    public final LinkedList<Tugas1> line = new LinkedList<Tugas1>();
    
    public void garis(Graphics g, int xa, int ya, int xb, int yb){
        int count = 0;
      
        int a = xa;
        int b = ya;
        int dxa = ((xb - xa));
        int dya = ((yb - ya));
        g.setColor(randomcolor);
        if(dxa==0){
            if(dya > 0) {
                while(ya != yb && time>=count) {
                    ya++;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            } else {
                while(ya != yb && time>=count) {
                    ya--;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            }
        } else if(dya==0){
            if(dxa > 0) {
                while(xa != xb&& time>=count) {
                    xa++;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            } else {
                while(xa != xb&& time>=count) {
                    xa--;
                    g.drawLine(a,b,xa,ya);
                    count++;
                }
            }
        } else{
            dxa = Math.abs(dxa);
            dya = Math.abs(dya);
            int pk = (dya < dxa) ? 2*dya - dxa : 2*dxa - dya;
            int dp = (dya < dxa) ? 2*(dya-dxa) : 2*(dxa-dya);

            boolean opr1 = (xa > xb);
            boolean opr2 = (ya > yb);

            while(xa != xb && ya != yb && time>=count) {
                if(pk > 0) {
                    if(opr1) xa-=1;
                    else xa+=1;

                    if(opr2) ya-=1;
                    else ya+=1;
                    pk += dp;
                }
                else {
                    if (dya < dxa) pk = pk + 2 * dya;
                    else pk = pk + 2 * dxa;
                    if(dxa>dya){
                        if(opr1) xa-=1;
                        else xa+=1;
                    }
                    else {
                        if(opr2) ya-=1;
                        else ya+=1;
                    }
                }
                g.drawLine(a,b,xa,ya);
                a = xa;
                b = ya;
                count++;
            }
        }
    }
    
    public void addLine(int x1, int y1, int x2, int y2, Color color) {
        line.add(new Tugas1(x1, y1, x2, y2, color)); 
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        this.setBackground(Color.BLACK);
        for (Tugas1 lines : line){
           garis(g, lines.x1, lines.y1, lines.x2, lines.y2);
        } 
    }
    
    public static void main(String[] args) {
        JFrame fr = new JFrame("Gambar");
        fr.setSize(1280,720);      
        final Tugas1 panelGambar = new Tugas1(0,0,0,0, Color.WHITE);
        fr.getContentPane().add(panelGambar);
        JPanel buttonsPanel = new JPanel();
        JButton startButton = new JButton("Start");
        buttonsPanel.add(startButton);
        fr.getContentPane().add(buttonsPanel, BorderLayout.PAGE_END);
        
        startButton.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                for(int i= 0; i<100; i++){
                    int x1 = (int) (Math.random()*1280);
                    int y1 = (int) (Math.random()*720);
                    int x2 = (int) (Math.random()*1280);
                    int y2 = (int) (Math.random()*720);
                    Color randomColor = new Color((float)Math.random(), (float)Math.random(), (float)Math.random());
                    panelGambar.addLine(x1, y1, x2, y2, randomColor);
                }
            }
            
        });
        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fr.setVisible(true);
    }   
}

也许有一种方法可以保持绘制的线条不会消失,并且所有线条都被绘制为代码的第一个模板

【问题讨论】:

  • 使用某种List 并存储您想要在其中绘制的所有“线条”。然后在调用paintComponent 时,遍历List 并绘制每一行
  • 我推荐 Java Collections TrailPerforming Custom PaintingPainting in AWT and SwingJava 2D Graphics Trail 作为一些宝贵的资源——尤其是关于 2D 图形轨迹中“形状”的决定
  • @MadProgrammer "使用某种List" 代码声明了List,例如public final LinkedList&lt;Tugas1&gt; line = new LinkedList&lt;Tugas1&gt;();。 OP 对属性以及它们应该附加到什么/应该如何存储它们非常困惑。关于本教程的好建议,如果 OP 这样做了,他们希望能理解为什么设置 BG 颜色应该在构造函数中完成,而不是在绘制方法中完成。
  • 请参阅:Custom Painting Approaches 以获取帮助您入门的基本工作示例。它演示了如何将有关要绘制的对象的信息存储在自定义对象中。

标签: java swing graphics


【解决方案1】:
public static int x1,y1,x2,y2;
  1. 不要使用static 属性,除非你能解释为什么它们需要被声明为静态的。
  2. 这些属性被声明为Tugas1 类的一部分。这是一个面板。它不需要这些属性,这是问题的一部分。删除它们。
  3. 将 4 个数字和颜色包装在 POJO 中(我们称之为 ColoredLine)并将它们添加到 LinkedList&lt;ColoredLine&gt;
  4. 然后迭代那个列表并依次绘制每个列表。

【讨论】:

  • 好的,谢谢.. 现在我的代码可以正常工作了,但它可以像在绘制完一条线后再画一条线一样工作吗?
  • “画完一条线后,它可以像画另一条线一样工作吗?” 我不确定你的意思。 DYM认为每条线都应该在很短的间隔后绘制?还有什么?
  • "DYM 表示每条线都应该在很短的时间间隔后绘制?还有别的吗?" 我的意思是可以逐行绘制吗?像队列。在第一条线绘制完成之前,第二条线不会绘制。
  • 当然,但它会采用更复杂的逻辑,或者采用不同的方法(具有类似不同但不太复杂的逻辑)将每条添加的线绘制到BufferedImage。两者都将基于使用 Swing Timer 来绘制后面的线条。太复杂了,无法评论。我建议您提出一个新问题并在您所做的任何尝试中添加minimal reproducible example
猜你喜欢
  • 1970-01-01
  • 2012-12-31
  • 2016-07-09
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2021-01-09
相关资源
最近更新 更多