繁体   English   中英

在Swing / AWT GUI中移动正弦曲线

[英]Moving sine curve in Swing/AWT GUI

我使用双向链表来创建此移动的正弦曲线(代码可能非常原始且杂乱无章,但这只是初稿,我几乎不知道如何使用Swing。):

import java.awt.*;  
import javax.swing.JFrame;  

public class DisplayGraphics extends Canvas{  

    public void paint(Graphics g) {   

        setForeground(Color.RED);  
        this.setSize(720,440);

        class list {
            int pos;
            list next; 
            list prev;

            list(){
                int pos;
                list next ;
                list prev;
            }

            list(int pos){
                this.pos = pos;
            }

            list(int pos, list next){
                this.pos = pos;
                this.next = next;
            }


            public void setpos(int pos){
                this.pos= pos;
            }

            public void setnext(list next){
                this.next= next;
                next.prev=this;
            }

            public void display(list head){
                list tracker = head;
                int y;
                //displays the sincurve momentarily
                for (int i = 1;i<721; i++){
                    y = (int)(Math.sin(Math.toRadians(tracker.pos))*200)+200;
                    g.fillOval(i,y,3,3);
                    tracker = tracker.next;
                }  
            }
        }

        list temp = new list();
        temp.setpos(1);
        list head = temp;

        for (int i =2; i<720; i++){
            list thing = new list();
            thing.setpos(i);
            temp.setnext(thing);
            temp = thing;

        }
        list tail = new list(720);
        temp.setnext(tail);
        tail.setnext(head);

        //creates the moving display
        boolean run = true;
        while(run==true){
            head.display(head);

            //try {
                //Thread.sleep(10);

            //} catch(InterruptedException ex) {
               // Thread.currentThread().interrupt();
            //}
            g.clearRect(0, 0, getWidth(), getHeight());
            head = head.next ;  
       }
    }

    public static void main(String[] args) {  
        DisplayGraphics m=new DisplayGraphics(); 

        JFrame f=new JFrame();  
        f.add(m);  
        f.setSize(720,400);  
        //f.setLayout(null);  
        f.setVisible(true);  
    }      
}  

但是,该程序运行得不太顺利。 有什么建议可以使其运行更快,更流畅吗?

好的,有一些缺陷必须纠正^^

1)通过线程触发绘画

//set isRunning=false to stop repaint
private boolean isRunning = true;
private void startUpdateThread(){
    Runnable r = new Runnable() {
        public void run() {

            while(isRunning){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //repaint calls the paint(Graphics g)-method
            repaint();
            }
        }
    };

    Thread t = new Thread(r);
    t.setDaemon(true);
    t.start();
}

2)不要使事情变得复杂:只需在绘制^^时计算f(x)= y
3)只做必须做的事情:不要在每次绘画时都设置大小

private int xCount = 0;
public void paint(Graphics g) {

    //setSize(...)

    xCount = xCount + 1;
    for (int dx = 1; dx < 721; dx++) {

        int x = (xCount%721)+dx;
        int y = (int) (Math.sin(Math.toRadians(x)) * 200) + 200;
        g.fillOval(dx, y, 3, 3);
    }
}

还剩什么? 您的设置^^

public static void main(String[] args) {
    DisplayGraphic m = new DisplayGraphic();
    m.startUpdateThread();
    m.setSize(720, 440);

    JFrame f = new JFrame();
    f.add(m);
    f.setSize(720, 400);
    f.setVisible(true);
}

您可能想看看缓冲...如果您不喜欢这样做,只需使用JPanel而不是Canvas(您将不得不覆盖paintComponent(Graphics g)而不是paint(Graphics g)

public class DisplayGraphic extends JPanel {

    private int xCount = 0;
    public void paintComponent(Graphics g) {        
        super.paintComponent(g);
        //...
        //same as paint in above
        }
    }
}
public class DisplayGraphics extends Canvas{

不要混合使用Swing和AWT。 默认情况下,Swing组件(任何为JComponent )都是双缓冲的。 这有助于避免渲染混乱。

public void paint(Graphics g) { 
    setForeground(Color.RED);

每当我们重写任何paint方法时,都应立即调用super方法以删除原始图形。 但是对于Swing,我们将重写paintComponent(Graphics)而不是paint(Graphics)

设置前景色应在构造函数中完成一次,然后再单独设置。 再次调用它会触发绘画!

this.setSize(720,440);

这是另一件事,将触发重新粉刷!

此外,最好是覆盖的大小getPreferredSize()方法和pack()包含它..任何信息,网站,书你已经用顶层窗口,找到一个新的&比较好版本。 此代码在许多重要部分中都显示了不良做法。

有什么建议可以使其运行更快,更流畅吗?

使用Swing组件(例如JPanel )代替Canvas 进行更改并覆盖上述方法。 创建一个Swing Timer ,在循环部分中调用repaint()

有关更好的学习资源,请参见执行自定义绘画如何使用摆动计时器

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM