下午在查Fourier近似时,在网页上看到一个小程序,给定一些函数,可以将傅里叶近似的结果用图像显示,可以和用户交互,如下图,一目了然(如果大学教育能多多地使用这种方式,那么学生会更能接受)。一时好奇,就想看看源代码,同时想把这个小程序保存在本地。
网页的地址是http://www.jhu.edu/signals/fourier2/index.html,通过查看网页的源代码,发现有这么一段
<center>
<table bgcolor="E0E0E0" border="1">
<tr>
<td>
<applet archive = FourierNew.jar code = FourierNew width = 480 height = 400></applet>
</td>
</tr>
</table>
</center>
1. 可以判断小程序代码在 FourierNew.jar 中,并且FourierNew.jar和网页在同一目录下,在地址栏中输入http://www.jhu.edu/signals/fourier2/FourierNew.jar 即可下载到FourierNew.jar.
2. 解压以后得到很多.class文件,可以使用jad + net.sf.jadclipse_3.3.0.jar将.class文件反编译得到相应的java文件,具体方法参见这里。这个演示小程序的java源代码见附录。
另外,有几个notes
1. Applet应用程序没用main方法,代之以public void init(); public void start(); public void stop(); public void destroy();
2. 在编写Applet程序时,首先必须引入java.applet.Applet包.
3. 编写一Applet程序时,一个类必须继承自Applet类,之后要复写里面的paint(Graphics g)方法.
4. Applet程序不能单独运行,必须嵌套在HTML中才可以使用。
5. 批量编译javac, 反编译jad,如 jad -o -r -s java -d src org/**/*.class,以及javac **.java
6. CODE=AppleFile提供包含Applet类的经编译后的扩展名为.class的文件
7. 可以将编译后的所有.class的文件打包成.jar文件,用 archive = FourierNew.jar提供,像本文开头那段html.
8. Applet既可以打开网页的方式执行,亦可以在命令行下用appletviewer FileNmae.htm执行
附录 :
//FourierNew.java
import java.applet.Applet;
import java.awt.*;
public class FourierNew extends Applet
{
public FourierNew()
{
}
public void init()
{
GridBagLayout gridbaglayout = new GridBagLayout();
GridBagConstraints gridbagconstraints = new GridBagConstraints();
Panel panel = new Panel();
Panel panel1 = new Panel();
Panel panel2 = new Panel();
panel2.setBackground(Color.lightGray);
setLayout(gridbaglayout);
setSize(480, 400);
gridbagconstraints.fill = 1;
gridbagconstraints.gridx = 0;
gridbagconstraints.weightx = 1.0D;
gridbagconstraints.weighty = 1.0D;
gridbaglayout.setConstraints(panel, gridbagconstraints);
add(panel);
gridbagconstraints.weighty = 1.0D;
gridbaglayout.setConstraints(panel1, gridbagconstraints);
add(panel1);
panel.setLayout(new BorderLayout());
panel1.setLayout(new BorderLayout());
SigPanel sigpanel = new SigPanel();
panel.add(sigpanel, "Center");
SigControls sigcontrols = new SigControls(sigpanel);
panel.add(sigcontrols, "East");
panel.add(panel2, "North");
FourierControls fouriercontrols = new FourierControls(sigpanel);
panel1.add(fouriercontrols, "North");
MagPanel magpanel = new MagPanel();
panel1.add(magpanel, "Center");
sigpanel.setControls(fouriercontrols, magpanel);
}
}
//MagPanel.java
import java.awt.*;
class MagPanel extends Panel
{
public MagPanel()
{
setup = false;
setBackground(Color.white);
}
public Dimension minimumSize()
{
return new Dimension(150, 90);
}
public void paint(Graphics g)
{
if(!setup)
{
fImage = createImage(getSize().width, getSize().height);
fGraphics = fImage.getGraphics();
setup = true;
}
fGraphics.clearRect(0, 0, getSize().width, getSize().height);
byte byte0 = 5;
byte byte1 = 5;
int i = getSize().width / 2 + 5;
int j = i - 5;
fGraphics.setColor(Color.lightGray);
fGraphics.drawLine(byte1, 0, byte1, getSize().height);
fGraphics.drawLine(0, getSize().height - 4, j, getSize().height - 4);
fGraphics.drawLine(i, 0, i, getSize().height);
fGraphics.drawLine(i, getSize().height - 4, getSize().width, getSize().height - 4);
fGraphics.drawLine(i - 2, 4, i + 2, 4);
fGraphics.setColor(Color.black);
if(fMag != null)
{
for(int k = 0; k <= fCoefs; k++)
{
if(byte1 + byte0 * k <= j)
{
fGraphics.setColor(Color.red);
fGraphics.drawLine(byte1 + byte0 * k, getSize().height - 4, byte1 + byte0 * k, getSize().height - 4 - fMag[k]);
fGraphics.drawLine(byte1 + byte0 * k + 1, getSize().height - 4, byte1 + byte0 * k + 1, getSize().height - 4 - fMag[k]);
}
fGraphics.setColor(Color.blue);
fGraphics.drawLine(i + byte0 * k, getSize().height - 4, i + byte0 * k, getSize().height - 4 - fPhase[k]);
fGraphics.drawLine(i + byte0 * k + 1, getSize().height - 4, i + byte0 * k + 1, getSize().height - 4 - fPhase[k]);
}
}
fGraphics.setColor(Color.black);
fGraphics.drawString("Magnitude spectrum", byte1 + 5, 13);
fGraphics.drawString("Phase spectrum", i + 5, 13);
g.drawImage(fImage, 0, 0, this);
}
public void set(int ai[], int ai1[], int i)
{
fMag = ai;
fPhase = ai1;
fCoefs = i;
repaint();
}
public void update(Graphics g)
{
paint(g);
}
int fMag[];
int fPhase[];
boolean setup;
int fSigLength;
int fAmplitude;
int fCoefs;
Image fImage;
Graphics fGraphics;
}
//SigControls.java
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class SigControls extends Panel
implements ActionListener
{
public SigControls(SigPanel sigpanel)
{
rect = new Button("Rectangular Pulse");
bipulse = new Button("Bipolar Pulse");
saw = new Button("Sawtooth");
tri = new Button("Triangle");
exp = new Button("Exponential");
noise = new Button("Noise");
clear = new Button("Clear");
panel = sigpanel;
setLayout(new GridLayout(8, 2, 5, 5));
setBackground(Color.lightGray);
add(rect);
add(bipulse);
add(saw);
add(tri);
add(exp);
add(noise);
add(new Label());
add(clear);
rect.addActionListener(this);
bipulse.addActionListener(this);
saw.addActionListener(this);
tri.addActionListener(this);
exp.addActionListener(this);
noise.addActionListener(this);
clear.addActionListener(this);
}
public void actionPerformed(ActionEvent actionevent)
{
if(actionevent.getActionCommand().equals("Exponential"))
panel.doDecay();
else
if(actionevent.getActionCommand().equals("Noise"))
panel.doNoise();
else
if(actionevent.getActionCommand().equals("Rectangular Pulse"))
panel.doPulse();
else
if(actionevent.getActionCommand().equals("Bipolar Pulse"))
panel.doDoublePulse();
else
if(actionevent.getActionCommand().equals("Triangle"))
panel.doTriangle();
else
if(actionevent.getActionCommand().equals("Sawtooth"))
panel.doSawtooth();
else
if(actionevent.getActionCommand().equals("Clear"))
panel.clear();
}
public Insets insets()
{
return new Insets(3, 3, 3, 3);
}
Button rect;
Button bipulse;
Button saw;
Button tri;
Button exp;
Button noise;
Button clear;
SigPanel panel;
}
//Signal.java
import java.awt.*;
class Signal
{
public Signal(int i, int j, FourierControls fouriercontrols, MagPanel magpanel)
{
fourier = false;
fSigLength = i;
fAmplitude = j / 2;
fFourierControls = fouriercontrols;
fMagPanel = magpanel;
x = new int[fSigLength];
approxX = new int[fSigLength];
doPulse();
}
public void Drag(int i, int j, int k, int l)
{
if(k == i)
return;
changed();
if(i > k)
{
int i1 = i;
i = k;
k = i1;
i1 = j;
j = l;
l = i1;
}
for(int j1 = i; j1 <= k; j1++)
x[j1] = fAmplitude - (j + ((l - j) * (j1 - i)) / (k - i));
}
public void Draw(Graphics g)
{
g.setColor(Color.lightGray);
g.drawLine(0, fAmplitude, fSigLength, fAmplitude);
g.drawLine(fSigLength / 2, 0, fSigLength / 2, fAmplitude * 2);
g.setColor(Color.black);
g.drawString("One period of x(t)", 3, 13);
g.setColor(Color.blue);
for(int i = 1; i < fSigLength; i++)
g.drawLine(i - 1, fAmplitude - x[i - 1], i, fAmplitude - x[i]);
if(fourier)
{
g.setColor(Color.red);
for(int j = 1; j < fSigLength; j++)
g.drawLine(j - 1, fAmplitude - approxX[j - 1], j, fAmplitude - approxX[j]);
}
}
public void Modify(int i, int j)
{
changed();
x[i] = fAmplitude - j;
}
public void changed()
{
fourier = false;
fFourierControls.disablePlusMinus();
fMagPanel.set(null, null, 0);
}
public void doDecay()
{
double d = Math.sqrt(fAmplitude);
double d1 = (-Math.log(d) * 2D) / (double)fSigLength;
for(int i = 0; i < fSigLength; i++)
x[i] = (int)(d * Math.exp(d1 * (double)(i - fSigLength / 2)));
changed();
}
public void doDoublePulse()
{
for(int i = 0; i < fSigLength; i++)
if(i > (2 * fSigLength) / 3 && i < (fSigLength * 5) / 6)
x[i] = (int)(0.80000000000000004D * (double)fAmplitude);
else
if(i > fSigLength / 6 && i < fSigLength / 3)
x[i] = (int)(-0.80000000000000004D * (double)fAmplitude);
else
x[i] = 0;
changed();
}
public void doNoise()
{
for(int i = 0; i < fSigLength; i++)
if(i % 8 == 0)
x[i] = (int)(Math.random() * 2D * (double)fAmplitude - (double)fAmplitude);
else
x[i] = x[i - 1] + (int)(Math.random() * 6D - 3D);
changed();
}
public void doPulse()
{
for(int i = 0; i < fSigLength; i++)
if(i > (3 * fSigLength) / 7 && i < (fSigLength * 4) / 7)
x[i] = (int)(0.80000000000000004D * (double)fAmplitude);
else
x[i] = (int)(-0.80000000000000004D * (double)fAmplitude);
changed();
}
public void doSawtooth()
{
for(int i = 0; i < fSigLength; i++)
x[i] = (int)(0.80000000000000004D * ((((double)(float)fAmplitude * 2D) / (double)fSigLength) * (double)(i - fSigLength / 2)));
changed();
}
public void doTriangle()
{
for(int i = 0; i < fSigLength; i++)
x[i] = (int)(0.80000000000000004D * ((double)fAmplitude - (((double)fAmplitude * 4D) / (double)fSigLength) * (double)Math.abs(i - fSigLength / 2)));
changed();
}
public void getCoefs(TextArea textarea)
{
textarea.setText(" Magnitude: Phase:\n");
for(int i = 0; i <= fCoefs; i++)
{
String s = String.valueOf(mag[i]);
String s1 = String.valueOf(phase[i]);
if(s.length() > 5)
s = s.substring(0, 6);
if(s1.length() > 5)
s1 = s1.substring(0, 5);
textarea.appendText(i + ". " + s + "\t " + s1 + "\n");
}
}
public void go(int i)
{
fCoefs = i;
double d = 6.2831853071795862D / (double)fSigLength;
double ad[] = new double[i + 1];
double ad1[] = new double[i + 1];
mag = new double[i + 1];
phase = new double[i + 1];
for(int j = 0; j < fSigLength; j++)
ad[0] += (double)x[j] * d;
ad[0] /= 6.2831853071795862D;
ad1[0] = 0.0D;
mag[0] = Math.abs(ad[0]) / 2D;
phase[0] = ad[0] < 0.0D && Math.abs(ad[0]) >= 1.0000000000000001E-005D ? 3.1415926535897931D : 0.0D;
double d1 = mag[0];
for(int k = 1; k <= i; k++)
{
for(int l = 0; l < fSigLength; l++)
{
double d2 = (double)(k * (l - fSigLength / 2)) * d;
double d3 = (double)x[l] * d;
ad[k] += d3 * Math.cos(d2);
ad1[k] += d3 * Math.sin(d2);
}
ad[k] /= 3.1415926535897931D;
ad1[k] /= 3.1415926535897931D;
mag[k] = Math.sqrt(ad[k] * ad[k] + ad1[k] * ad1[k]);
phase[k] = Math.atan((ad1[k] - ad1[k - 1]) / (ad[k] - ad[k - 1]));
if(ad[k] < 0.0D)
phase[k] = phase[k] + 3.1415926535897931D;
if(phase[k] <= 0.10000000000000001D)
phase[k] = 0.0D;
if(mag[k] > d1)
d1 = mag[k];
}
int ai[] = new int[i + 1];
int ai1[] = new int[i + 1];
for(int i1 = 0; i1 <= i; i1++)
{
if(mag.length == 1)
{
if(mag[i1] <= 1.0D)
ai[i1] = 0;
else
ai[i1] = (int)((mag[i1] * (double)(fMagPanel.getSize().height - 8)) / (2D * d1));
} else
{
ai[i1] = (int)((mag[i1] * (double)(fMagPanel.getSize().height - 8)) / d1);
}
ai1[i1] = (int)((phase[i1] * (double)(fMagPanel.getSize().height - 8)) / 6.2831853071795862D);
}
for(int j1 = 0; j1 < fSigLength; j1++)
{
double d4 = (double)(j1 - fSigLength / 2) * d;
double d5 = ad[0];
for(int k1 = 1; k1 <= i; k1++)
{
double d6 = (double)k1 * d4;
d5 += ad[k1] * Math.cos(d6) + ad1[k1] * Math.sin(d6);
}
approxX[j1] = (int)d5;
}
fMagPanel.set(ai, ai1, i);
fourier = true;
}
public void zero()
{
for(int i = 0; i < fSigLength; i++)
x[i] = 0;
changed();
}
int fSigLength;
int fAmplitude;
int x[];
int approxX[];
double mag[];
double phase[];
boolean fourier;
FourierControls fFourierControls;
MagPanel fMagPanel;
int fCoefs;
}
// SigPanel.java
import java.awt.*;
import java.awt.event.*;
class SigPanel extends Panel
implements MouseListener, MouseMotionListener
{
public SigPanel()
{
prevX = 0;
prevY = 0;
setup = false;
setBackground(Color.white);
addMouseListener(this);
addMouseMotionListener(this);
}
public void clear()
{
signal.zero();
repaint();
}
public void doDecay()
{
signal.doDecay();
repaint();
}
public void doDoublePulse()
{
signal.doDoublePulse();
repaint();
}
public void doNoise()
{
signal.doNoise();
repaint();
}
public void doPulse()
{
signal.doPulse();
repaint();
}
public void doSawtooth()
{
signal.doSawtooth();
repaint();
}
public void doTriangle()
{
signal.doTriangle();
repaint();
}
public void getCoefs(TextArea textarea)
{
signal.getCoefs(textarea);
}
public void go(int i)
{
signal.go(i);
repaint();
}
public Dimension minimumSize()
{
return new Dimension(300, 100);
}
public void mouseClicked(MouseEvent mouseevent)
{
signal.Modify(mouseevent.getX(), mouseevent.getY());
prevX = mouseevent.getX();
prevY = mouseevent.getY();
repaint();
}
public void mouseDragged(MouseEvent mouseevent)
{
signal.Drag(prevX, prevY, mouseevent.getX(), mouseevent.getY());
prevX = mouseevent.getX();
prevY = mouseevent.getY();
repaint();
}
public void mouseEntered(MouseEvent mouseevent)
{
}
public void mouseExited(MouseEvent mouseevent)
{
}
public void mouseMoved(MouseEvent mouseevent)
{
}
public void mousePressed(MouseEvent mouseevent)
{
}
public void mouseReleased(MouseEvent mouseevent)
{
}
public void paint(Graphics g)
{
if(!setup)
{
signal = new Signal(getSize().width, getSize().height, fFourierControls, fMagPanel);
fImage = createImage(getSize().width, getSize().height);
fGraphics = fImage.getGraphics();
setup = true;
}
fGraphics.clearRect(0, 0, getSize().width, getSize().height);
signal.Draw(fGraphics);
g.drawImage(fImage, 0, 0, this);
}
public void setControls(FourierControls fouriercontrols, MagPanel magpanel)
{
fFourierControls = fouriercontrols;
fMagPanel = magpanel;
}
public void update(Graphics g)
{
paint(g);
}
Signal signal;
int prevX;
int prevY;
boolean setup;
FourierControls fFourierControls;
MagPanel fMagPanel;
Image fImage;
Graphics fGraphics;
}
//CoefFrame.java
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
class CoefFrame extends Frame
implements WindowListener
{
public CoefFrame(String s)
{
super(s);
addWindowListener(this);
}
public void windowActivated(WindowEvent windowevent)
{
}
public void windowClosed(WindowEvent windowevent)
{
}
public void windowClosing(WindowEvent windowevent)
{
dispose();
}
public void windowDeactivated(WindowEvent windowevent)
{
}
public void windowDeiconified(WindowEvent windowevent)
{
}
public void windowIconified(WindowEvent windowevent)
{
}
public void windowOpened(WindowEvent windowevent)
{
}
FourierControls fPanel;
}
//FourierControls
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class FourierControls extends Panel
implements ActionListener
{
public FourierControls(SigPanel sigpanel)
{
fNumCoefs = 10;
fCoefField = new TextField("10", 3);
fPlusButton = new Button("+");
fMinusButton = new Button("-");
fShowCoefsButton = new Button("Table");
calculate = new Button("Calculate");
panel = sigpanel;
setLayout(new FlowLayout());
setBackground(Color.lightGray);
add(new Label("Fourier series coefficients:"));
add(fCoefField);
add(calculate);
fWin = new CoefFrame("Fourier Series Coefficients");
fWin.setLayout(new BorderLayout());
fTextArea = new TextArea(fNumCoefs, 50);
fTextArea.setEditable(false);
fTextArea.setFont(new Font("Courier", 0, 12));
fWin.add("Center", fTextArea);
fWin.resize(300, 200);
Point point = location();
fWin.move(point.x + 50, point.y + 50);
disablePlusMinus();
add(new Label(" "));
add(fMinusButton);
add(fPlusButton);
add(new Label(" "));
add(fShowCoefsButton);
fMinusButton.addActionListener(this);
fPlusButton.addActionListener(this);
fShowCoefsButton.addActionListener(this);
calculate.addActionListener(this);
}
public void actionPerformed(ActionEvent actionevent)
{
if(actionevent.getActionCommand().equals("Calculate"))
try
{
panel.go(fNumCoefs = Integer.parseInt(fCoefField.getText()));
panel.getCoefs(fTextArea);
fPlusButton.enable();
fShowCoefsButton.enable();
if(fNumCoefs >= 1)
fMinusButton.enable();
}
catch(NumberFormatException _ex) { }
else
if(actionevent.getActionCommand().equals("Table"))
{
panel.getCoefs(fTextArea);
fWin.show();
} else
if(actionevent.getActionCommand().equals("+"))
{
fCoefField.setText((new Integer(++fNumCoefs)).toString());
panel.go(fNumCoefs);
panel.getCoefs(fTextArea);
fMinusButton.enable();
} else
if(actionevent.getActionCommand().equals("-") && fNumCoefs >= 1)
{
fCoefField.setText((new Integer(--fNumCoefs)).toString());
panel.go(fNumCoefs);
panel.getCoefs(fTextArea);
if(fNumCoefs == 0)
fMinusButton.disable();
}
}
public void disablePlusMinus()
{
fPlusButton.disable();
fMinusButton.disable();
fShowCoefsButton.disable();
fTextArea.setText("");
}
SigPanel panel;
int fNumCoefs;
TextField fCoefField;
Button fPlusButton;
Button fMinusButton;
Button fShowCoefsButton;
Button calculate;
TextArea fTextArea;
Window fWin;
}
(来源 http://blog.csdn.net/zhaoyl03/article/details/8810940)