【问题标题】:Java JApplet: Why aren't my components appearing on screen?Java JApplet:为什么我的组件没有出现在屏幕上?
【发布时间】:2014-10-21 16:45:10
【问题描述】:

所以我遇到了这个挑战,要在一个小程序中制作其中一个螺旋计绘图。问题是,我是 Java 新手,完全不知道如何让任何组件出现在屏幕上。我希望有人可以添加一行额外的代码来解决这个问题,尽管我非常感谢任何答案:)

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

    }
}
}

【问题讨论】:

标签: java swing user-interface applet japplet


【解决方案1】:

你睡觉的油漆方法,你应该永远不要做的事情。在 Swing 事件线程上调用 Thread.sleep(...) 是不好的,但在任何绘画方法中这样做都是一种罪过。所以现在小程序无法绘制。请记住,任何绘画方法都必须只做绘画,并且必须以极快的速度完成。它不应该做任何程序逻辑,它不应该直接做动画,它应该只是绘画。使用 Swing 计时器,因为任何类似的问题都会告诉您如何操作。

此外,切勿直接在小程序中绘制,而是在小程序所拥有的 JPanel 的 paintComponent 方法中进行绘制。

因此,创建您的 JPanel,覆盖其paintComponent 方法,并使用该类的字段进行绘制。然后更改 Timer 中这些字段的状态并在 JPanel 上调用 repaint()。


编辑 是的,您应该避免使用空布局,因为这会妨碍您轻松且充分地将组件添加到您的 GUI。相反,在这种情况下,JPanel 的默认布局 FlowLayout 会很好用。

例如:

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

      }
   }
}

显示为,

【讨论】:

  • 哇,谢谢你的回答!老实说,我并不是 100% 完成了大部分工作,但至少我知道接下来的 2 小时我要弄清楚什么!然后这只是添加几个 JSlider 的简单任务(例如,允许用户更改原点偏移以及内半径和外半径)......哦,尝试添加多个 JSlider 并不是那么简单的任务以视觉上吸引人的方式着色。但再次感谢您的回答!
  • “尝试以视觉上吸引人的方式添加多种颜色并不是那么简单的任务。” 我会选择使用与设计相同的中心的RadialGradientPaint .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多