简体   繁体   中英

Java JApplet: Why aren't my components appearing on screen?

So I've got this challenge to make one of those spirograph drawrings in an applet. The problem is, I'm new to Java and have absolutely no idea how to get any components appearing on the screen. I'm hoping someone can just add an extra line of code to fix this, though I'm really grateful for any answers :)

import javax.swing.JApplet;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Toolkit;


public class SpaceCadets3_WB extends JApplet {

int numOfPoints = 1080;
int[] x = new int[numOfPoints];
int[] y = new int[numOfPoints];
int x1, x2, y1, y2, width, height, animationSleep = 0;
int R = 75;
int r = 10;
int O = 75;
JTextField changeNumOfPoints = new JTextField(15);

public SpaceCadets3_WB() {

}

public void start() {
    this.setSize(600, 600);
    this.setBackground(new Color(100,100,255));
    this.getContentPane().setLayout(null);
    this.getContentPane().add(changeNumOfPoints);
    changeNumOfPoints.setVisible(true);
    changeNumOfPoints.setLocation(width - changeNumOfPoints.getSize().width - 25, 25);
    }

public void calculatePoints(){
    width = SpaceCadets3_WB.this.getWidth();
    height = SpaceCadets3_WB.this.getHeight();
    for(int t = 0; t<numOfPoints; t++){
        x[t] = (int) ((R+r)*Math.cos(t) - (r+O)*Math.cos(((R+r)/r)*t) + width/2);
        y[t] = (int) ((R+r)*Math.sin(t) - (r+O)*Math.sin(((R+r)/r)*t) + height/2);
    }
}

public void paint(Graphics g){
    g.setColor(Color.RED);
    calculatePoints();
    for(int i = 0; i<numOfPoints;i++){
        x1 = x[i];
        x2 = x[i+1];
        y1 = y[i];
        y2 = y[i+1];
        g.drawLine(x1, y1, x2, y2);

        try {
            Thread.sleep(animationSleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
}

Your sleeping the paint method, something you should never do. It's bad to call Thread.sleep(...) on the Swing event thread, but it's a sin to do it in any painting method. So now the applet can't draw. Remember that any painting method must do nothing but painting, and must do it blazingly fast. It shouldn't do any program logic, it shouldn't directly do animation, it should just paint. Use a Swing timer as any similar question will show you how to do.

Also, never draw directly in the applet but instead in the paintComponent method of a JPanel that the applet holds.

So create your JPanel, override its paintComponent method, and draw using fields of the class. Then change the state of those fields in your Timer and call repaint() on the JPanel.


Edit And yes, you should avoid using null layouts as that's preventing you from easily and adequately adding components to your GUI. Instead in this situation, a FlowLayout, the default layout for JPanel, would work great.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;

import javax.swing.*;

@SuppressWarnings("serial")
public class SpaceCadets extends JApplet {
   @Override
   public void init() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               SpaceCadetsPanel panel = new SpaceCadetsPanel();
               getContentPane().add(panel);
               setSize(SpaceCadetsPanel.PREF_W, SpaceCadetsPanel.PREF_H);
            }
         });
      } catch (InvocationTargetException | InterruptedException e) {
         e.printStackTrace();
      }
   }
}

@SuppressWarnings("serial")
class SpaceCadetsPanel extends JPanel {
   public static final int PREF_W = 600;
   public static final int PREF_H = 600;
   public final static int TOTAL_POINTS = 1080;
   private static final int R = 75;
   private static final int R2 = 10;
   private static final int O = 75;
   private static final Color DRAW_COLOR = Color.RED;
   private static final int ANIMATION_DELAY = 20;
   private Point[] pts;
   private JSpinner pointCountSpinner = new JSpinner(new SpinnerNumberModel(
         800, 100, 1080, 1));
   private JButton doItButton = new JButton(new DoItBtnAction("Do It!"));
   private BufferedImage bufImg = new BufferedImage(PREF_W, PREF_H,
         BufferedImage.TYPE_INT_ARGB);
   private Timer timer;
   public int imageIndex;
   private CalcWorker calcWorker;
   public Graphics2D g2;

   public SpaceCadetsPanel() {
      System.out.println(pointCountSpinner.getEditor().getClass());
      add(pointCountSpinner);
      add(doItButton);
      setBackground(Color.white);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (bufImg != null) {
         g.drawImage(bufImg, 0, 0, this);
      }
   }

   class DoItBtnAction extends AbstractAction {
      public DoItBtnAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         imageIndex = 0;
         if (timer != null && timer.isRunning()) {
            timer.stop();
         }
         if (g2 != null) {
            g2.dispose();
         }
         pts = new Point[0];
         bufImg = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
         g2 = bufImg.createGraphics();
         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
         g2.setColor(DRAW_COLOR);
         int totalPoints = 0;
         totalPoints = ((Integer) pointCountSpinner.getValue()).intValue();

         timer = new Timer(ANIMATION_DELAY, new TimerListener(totalPoints));
         calcWorker = new CalcWorker(totalPoints);
         calcWorker.addPropertyChangeListener(new CalcWorkerListener());
         calcWorker.execute();
      }
   }

   class CalcWorker extends SwingWorker<Point[], Void> {
      private int totalPoints;

      public CalcWorker(int totalPoints) {
         this.totalPoints = totalPoints;
      }

      @Override
      protected Point[] doInBackground() throws Exception {
         Point[] pts2 = new Point[totalPoints];
         for (int i = 0; i < pts2.length; i++) {
            int x = (int) ((R + R2) * Math.cos(i) - (R2 + O)
                  * Math.cos(((R + R2) / R2) * i) + PREF_W / 2);
            int y = (int) ((R + R2) * Math.sin(i) - (R2 + O)
                  * Math.sin(((R + R2) / R2) * i) + PREF_H / 2);
            pts2[i] = new Point(x, y);
         }
         return pts2;
      }
   }

   class CalcWorkerListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
            try {
               pts = calcWorker.get();
               timer.start();
            } catch (InterruptedException | ExecutionException e) {
               e.printStackTrace();
            }
         }
      }
   }

   class TimerListener implements ActionListener {
      private int totalPoints;

      public TimerListener(int totalPoints) {
         this.totalPoints = totalPoints;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         int x1 = pts[imageIndex].x;
         int y1 = pts[imageIndex].y;
         int x2 = pts[imageIndex + 1].x;
         int y2 = pts[imageIndex + 1].y;
         g2.drawLine(x1, y1, x2, y2);
         repaint();
         imageIndex++;

         if (imageIndex == totalPoints - 1) {
            ((Timer) e.getSource()).stop();
         }

      }
   }
}

Which displays as,

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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