2015-12-02 3 views
0

Я использовал дважды связанные списки, чтобы создать эту движущуюся синусовую кривую (код может быть чрезвычайно примитивным и дезорганизованным, но это всего лишь первый черновик, и я едва знаю, как использовать Swing.):Перемещение кривой синуса в Swing/AWT GUI

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

Однако программа не работает очень плавно. Есть ли какие-либо предложения, чтобы заставить его работать быстрее и плавно?

+0

Вы можете сделать прямо одно из следующих действий: возьмите 'class list {...}' из метода рисования. то instanciate объект только один раз, за ​​пределами метода краски ... ах ждать, что это слишком сложно ответить в комментарии, я отправлю ответ ... –

+0

жаль, что я так медленно отвечал ... @AndrewThompson указал из многих вопросов мой ответ выглядит сейчас очень плохим ... спасибо, что ты это сделал^^^ –

ответ

4

нормально есть некоторые недостатки, которые должны быть исправлены ^^

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) не делают вещи сложно: просто вычислить п (х) = у во время краски ^^
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 вместо холста (вам придется перезаписать 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 
     } 
    } 
} 
+0

Хороший ответ, стоит потратить на это время. –

+0

Имея такой ответ от меня, я очень горжусь! что будет мотивировать меня потратить больше времени на SO снова =) Большое вам спасибо! –

4
public class DisplayGraphics extends Canvas{ 

не смешивать свинг и AWT. Компоненты Swing (все, что есть JComponent) по умолчанию имеют двойной буфер. Это помогает избежать отрывистого рендеринга.

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

Всякий раз, когда мы переопределяем любой метод краски, мы должны немедленно вызвать метод super, чтобы стереть исходный чертеж. Но для Swing мы переопределили paintComponent(Graphics) вместо paint(Graphics).

Установка цвета переднего плана должна выполняться в конструкторе один раз, а затем оставлена ​​одна. Вызов его снова вызывает краску!

this.setSize(720,440); 

И это другой вещь, которая будет вызывать перерисовку!

Кроме того, лучше, чтобы переопределить размер getPreferredSize() метода и pack() окна верхнего уровня, который содержит это .. Любую информацию, сайт, книгу, которую вы использовали, найти новую & лучшей версии. Этот код показывает неправильную практику в слишком многих важных частях.

Есть ли какие-либо предложения, чтобы сделать его быстрее и более гладким?

Используйте компонент Swing (например, JPanel) вместо Canvas. Внесите изменения & переопределите методы, упомянутые выше. Создайте Swing Timer, который вызывает repaint() в части цикла.

См. Performing Custom Painting & How to Use Swing Timers для улучшения учебных ресурсов.

Смежные вопросы