简体   繁体   English

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

[英]Moving sine curve in Swing/AWT GUI

I used doubly linked lists in order to create this moving sine curve (the code might be extremely primitive and disorganized but this is just a first draft and I barely know how to use Swing..): 我使用双向链表来创建此移动的正弦曲线(代码可能非常原始且杂乱无章,但这只是初稿,我几乎不知道如何使用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);  
    }      
}  

However, the program doesn't run very smoothly. 但是,该程序运行得不太顺利。 Are there any suggestions to make it run faster, and more smoothly? 有什么建议可以使其运行更快,更流畅吗?

ok there are some flaws that have to be corrected ^^ 好的,有一些缺陷必须纠正^^

1) trigger your painting via threads 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) don't make things complicated: just calculate f(x)=y during paint ^^ 2)不要使事情变得复杂:只需在绘制^^时计算f(x)= y
3) do only things in paint, that have to be done: don't set size everytime you paint 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);
    }
}

what's left? 还剩什么? your setup ^^ 您的设置^^

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);
}

you might want to take a look at buffering... if you don't like to do so, just use JPanel instead of Canvas (you'll have to overwrite paintComponent(Graphics g) instead of paint(Graphics g) ) 您可能想看看缓冲...如果您不喜欢这样做,只需使用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{

Don't mix Swing and AWT. 不要混合使用Swing和AWT。 Swing components (anything that is a JComponent ) are double buffered by default. 默认情况下,Swing组件(任何为JComponent )都是双缓冲的。 That helps avoid jerky rendering. 这有助于避免渲染混乱。

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

Whenever we override any paint method, we should immediately call the super method in order to erase the original drawing. 每当我们重写任何paint方法时,都应立即调用super方法以删除原始图形。 But for Swing we would override paintComponent(Graphics) instead of paint(Graphics) . 但是对于Swing,我们将重写paintComponent(Graphics)而不是paint(Graphics)

Setting the foreground color should be done in the constructor once, then left alone. 设置前景色应在构造函数中完成一次,然后再单独设置。 Calling it again triggers paint! 再次调用它会触发绘画!

this.setSize(720,440);

And that is another thing that will trigger a repaint! 这是另一件事,将触发重新粉刷!

Further, it is better to override the size of getPreferredSize() method and pack() the top level window that contains it.. Whatever information, site, book you have been using, find a new & better version. 此外,最好是覆盖的大小getPreferredSize()方法和pack()包含它..任何信息,网站,书你已经用顶层窗口,找到一个新的&比较好版本。 This code shows bad practices in too many of the important parts.. 此代码在许多重要部分中都显示了不良做法。

Are there any suggestions to make it run faster, and more smooth? 有什么建议可以使其运行更快,更流畅吗?

Use a Swing component (eg JPanel ) instead of the Canvas . 使用Swing组件(例如JPanel )代替Canvas Make the changes & override the methods mentioned above. 进行更改并覆盖上述方法。 Create a Swing Timer that calls repaint() in the loop part. 创建一个Swing Timer ,在循环部分中调用repaint()

See Performing Custom Painting & How to Use Swing Timers for better learning resources. 有关更好的学习资源,请参见执行自定义绘画如何使用摆动计时器

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

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