2014-03-08 4 views
1

Im в процессе обучения графическому интерфейсу на Java. Im делает этот очень простой графический интерфейс, который буквально масштабирует размер круга каждые 5 миллисекунд, а затем, когда ширина и высота достигают определенного числа, он масштабируется и продолжает выполнять этот процесс. Мне удалось заставить круг появиться на экране, но по какой-то странной причине его не масштабировать.Как анимировать круг

public class circle extends JPanel implements ActionListener { 



    Timer tm = new Timer(5, this); 

    int XDiameter = 20; 
    int YDiameter = 20; 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
g.setColor(Color.GREEN); 
     g.fillOval(40, 40, XDiameter, YDiameter); 

     tm.start(); 
    } 



    @Override 
    public void actionPerformed(ActionEvent e) { 

     SuperSizeCircle(); 
     repaint(); 

    } 

    public void SuperSizeCircle(){ 
     while(true){ 
      XDiameter = XDiameter + 2; 
      YDiameter = YDiameter + 2; 
      if(XDiameter > 200 && YDiameter > 200){ 
       XDiameter --; 
       YDiameter --; 
      }else if(XDiameter < 20 && YDiameter < 20){ 
      XDiameter ++; 
      YDiameter ++; 
     } 
     } 
    } 

} 

Основной класс:

public class main { 



public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    JFrame frame = new JFrame("Circle enlarger"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(400,400); 
    frame.setVisible(true); 

    circle co = new circle(); 
    frame.add(co); 

} 

}

+0

Таймер перерисовывает Графический интерфейс пользователя каждые 5 Миллис для вас. Вы не должны иметь бесконечный цикл в 'SuperSizeCircle()' (который должен быть назван 'superSizeCircle()'). –

+0

Добавить 'co', _then_' setVisible() ' –

ответ

2
  1. while(true) никогда не хорошо в Swing анимации. Бросьте его в окно и попрощайтесь с ним навсегда. Возьмите это из своего метода. Вам это не нужно. Таймер заботится о «перекручивания»

  2. Не запускайте Timer в методе paintComponent. Сделайте это в конструкторе.

  3. Вы должны запустить свои приложения Swing в Thread Dispatch Thread путем упаковки вашего кода в SwingUtilities.invokeLater... См. Initial Threads для более подробной информации.

  4. Вы должны установить видимую рамку после, добавив все компоненты.

  5. if заявления в вашем SuperSizeCircle() беспорядок друг с другом, если вы посмотрите на логику. Вот почему вам нужно продолжать добавлять. Это не выглядит правильным для меня. Вместо этого нам флаг (булево), чтобы определить, следует ли увеличить или уменьшить

    boolean grow = true; 
    
    public void SuperSizeCircle() { 
    
        if (XDiameter >= 200) { 
         grow = false; 
        } 
        if (XDiameter <= 20) { 
         grow = true; 
        } 
    
        if (grow) { 
         XDiameter += 2; 
         YDiameter += 2; 
        } else { 
         XDiameter -= 2; 
         YDiameter -= 2; 
        } 
    } 
    

enter image description here

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class CirclePanel extends JPanel implements ActionListener { 

    Timer tm = new Timer(15, this); 

    boolean grow = true; 

    int XDiameter = 20; 
    int YDiameter = 20; 

    public CirclePanel() { 
     tm.start(); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.setColor(Color.GREEN); 
     g.fillOval(50, 50, XDiameter, YDiameter); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     SuperSizeCircle(); 
     repaint(); 

    } 

    public void SuperSizeCircle() { 

     if (XDiameter >= 200) { 
      grow = false; 
     } 
     if (XDiameter <= 20) { 
      grow = true; 
     } 

     if (grow) { 
      XDiameter += 3; 
      YDiameter += 3; 
     } else { 
      XDiameter -= 3; 
      YDiameter -= 3; 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame frame = new JFrame("Circle enlarger"); 
       CirclePanel co = new CirclePanel(); 
       frame.add(co); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setSize(300, 300); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Wow thanks. Не думал о написании метода superSizeCircle таким образом. У меня есть пара вопросов: Как программа знает, как рисовать круг? Im не явным образом вызывает метод paintComponent. Почему плохо поддерживать бесконечный цикл в графическом интерфейсе? Это потому, что это ресурс? Почему логика в моей петле увеличивает/уменьшает масштаб круга? Я пытаюсь думать как робот и честно не могу найти «лазейку», которая не заставит меня следовать этим наборам команд. В любом случае, спасибо за помощь. Он отлично работает: D – user3323950

+0

Каждый 'JComponent' неявно называет его собственным методом' paintComponent'. То, что вы делаете, переопределяет функциональность 'default' метода' JPanel 'paintComponent'.Его плохо держать бесконечный цикл, потому что вы заблокируете программу от выполнения других функций. В вашем случае внешний вид никогда не выйдет из метода. Я не уверен в вашей логике, это выглядело неправильно. Посмотри на это. Он будет расти, но как только он доберется до 200, он все равно будет расти, потому что ваше увеличение на два и уменьшение на 1 –

1

Вот JavaFX решение, основанное, как раз для изменения.

smallbig

import javafx.animation.ScaleTransition; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Circle; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class CircleScaler extends Application { 

    private static final double MIN_RADIUS = 10; 
    private static final double MAX_RADIUS = 100; 
    private static final double PANE_SIZE = 2 * (MIN_RADIUS + MAX_RADIUS); 
    private static final double SCALE_FACTOR = MAX_RADIUS/MIN_RADIUS; 
    private static final Duration SCALE_DURATION = Duration.seconds(3); 

    @Override 
    public void start(Stage stage) { 
     final Circle circle = new Circle(MIN_RADIUS, Color.CRIMSON); 

     final StackPane root = new StackPane(circle); 
     root.setPrefSize(PANE_SIZE, PANE_SIZE); 

     stage.setScene(new Scene(root, Color.PALETURQUOISE)); 
     stage.show(); 

     animateCircle(circle); 
    } 

    private void animateCircle(Circle circle) { 
     ScaleTransition scaler = new ScaleTransition(
       SCALE_DURATION, 
       circle 
     ); 
     scaler.setFromX(1); 
     scaler.setToX(SCALE_FACTOR); 
     scaler.setFromY(1); 
     scaler.setToY(SCALE_FACTOR); 

     scaler.setAutoReverse(true); 
     scaler.setCycleCount(ScaleTransition.INDEFINITE); 
     scaler.play(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Для более сложных анимированных кругов JavaFX см james-d's animation of 300 balls.

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