import java.awt.*; import java.awt.event.*; import java.lang.*; import java.lang.Math; import java.text.*; public class Spring2 extends java.applet.Applet implements Runnable { Canvas oscillators; Label xInitLabel, springKLabel, xInitS, springKS; Button Start, Reset; Thread runner; Scrollbar xInitscroll, springKscroll; int xInit, springK, xpos, xOrigin, yOrigin, springMid, springHi, springLo, wallX, EnLo, EnPE, EnKE; int[] springX = new int[12]; int[] springY = new int[12]; double xI, k, x, v, a, t, w, f, PE, KE, totalEnergy; Image offscreenImg; Graphics offscreenG; boolean startFlag; boolean pauseFlag; void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } public void init() { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); setLayout(gridbag); // initial position text buildConstraints(constraints, 0, 0, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label xInitLabel = new Label("Initial displacement from equilibrium (cm):", Label.CENTER); gridbag.setConstraints (xInitLabel, constraints); add(xInitLabel); // initial position scrollbar label buildConstraints(constraints, 2, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; xInitS = new Label("20", Label.LEFT); xInit = 20; gridbag.setConstraints (xInitS, constraints); add(xInitS); // initial position scrollbar buildConstraints(constraints, 1, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; xInitscroll = new Scrollbar(Scrollbar.HORIZONTAL, 20, 1, 10, 50); gridbag.setConstraints (xInitscroll, constraints); add(xInitscroll); // Spring constant text buildConstraints(constraints, 0, 1, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label springKLabel = new Label("Spring constant (N/m):", Label.CENTER); gridbag.setConstraints (springKLabel, constraints); add(springKLabel); // Spring constant scrollbar label buildConstraints(constraints, 2, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; springKS = new Label("20", Label.LEFT); springK = 20; gridbag.setConstraints (springKS, constraints); add(springKS); // Spring constant scrollbar buildConstraints(constraints, 1, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; springKscroll = new Scrollbar(Scrollbar.HORIZONTAL, 20, 1, 1, 50); gridbag.setConstraints (springKscroll, constraints); add(springKscroll); // Start button buildConstraints(constraints, 0, 2 , 1, 1, 0, 10); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Start = new Button(" Start "); gridbag.setConstraints (Start, constraints); add(Start); // Reset button buildConstraints(constraints, 1, 2 , 1, 1, 0, 10); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; Reset = new Button("Reset"); gridbag.setConstraints (Reset, constraints); add(Reset); // canvas buildConstraints(constraints, 0, 3, 3, 1, 0, 80); constraints.fill = GridBagConstraints.HORIZONTAL; oscillators = new Canvas(); gridbag.setConstraints (oscillators, constraints); add(oscillators); offscreenImg = createImage(this.size().width, this.size().height); offscreenG = offscreenImg.getGraphics(); } public void start() { if (runner == null); { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { double deltat, junk, scale, mass; int i; deltat=0.1; scale = 175.0; mass = 1.0; xOrigin = 100; yOrigin = 300; springMid = yOrigin - 10; springHi = springMid-7; springLo = springMid+7; wallX = xOrigin+140; EnLo = 50; startFlag = false; pauseFlag = false; while (true) { t = 0.0; k = springK; xI = xInit/100.0; w = Math.sqrt(k/mass); f = w /(2*3.14159265358); KE = 0.0; PE = 0.5*k*xI*xI; totalEnergy=KE+PE; EnPE = (int)(100.0*PE/totalEnergy); EnKE = (int)(100.0*KE/totalEnergy); x = xI; xpos = (int)(xOrigin+scale*x); v = 0.0; a = -xI*w*w; springX[0]=wallX; junk = (wallX-xpos-10)/11.0; for (i=1; i<12; i++) { springX[i]=springX[0]-(int)(i*junk); } springY[0] = springMid; springY[1] = springMid; springY[10] = springMid; springY[11] = springMid; for (i=1; i<5; i++) { springY[2*i]=springHi; springY[2*i+1]=springLo; } while (pauseFlag) { while (startFlag) { t = t + deltat; x = xI*Math.cos(w*t); xpos = (int)(xOrigin+scale*x); v = -xI*w*Math.sin(w*t); a = -xI*w*w*Math.cos(w*t); KE = 0.5*mass*v*v; PE = 0.5*k*x*x; EnPE = (int)(100.0*PE/totalEnergy); EnKE = (int)(100.0*KE/totalEnergy); junk = (wallX-xpos-10)/11.0; for (i=1; i<12; i++) { springX[i]=springX[0]-(int)(i*junk); } repaint(); try { Thread.sleep(100); } catch (InterruptedException e) { } } } repaint(); try { Thread.sleep(1); } catch (InterruptedException e) { } } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { int i; // Draw background offscreenG.setColor(Color.lightGray); offscreenG.fillRect(0,0,500,200); offscreenG.setColor(Color.white); offscreenG.fillRect(0,200,500,400); // Draw mass NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(4); offscreenG.setColor(Color.black); offscreenG.drawLine(2, yOrigin, wallX, yOrigin); offscreenG.drawLine(wallX, yOrigin, wallX, yOrigin-40); offscreenG.drawString("The bar graph shows how the energy" , EnLo, yOrigin+48); offscreenG.drawString("is split between potential (in red)" , EnLo, yOrigin+63); offscreenG.drawString("and kinetic (in blue)" , EnLo, yOrigin+78); offscreenG.setColor(Color.red); for (i=0; i<11; i++) { offscreenG.drawLine(springX[i],springY[i],springX[i+1],springY[i+1]); } offscreenG.drawString("PE = " + nf.format(PE) + " J", 300, 340); offscreenG.fillRect(EnLo, yOrigin+25, EnPE, 8); offscreenG.setColor(Color.blue); offscreenG.fillRect(xpos-10, yOrigin-20, 20, 20); offscreenG.fillRect(xOrigin-10, yOrigin+5, 20, 4); offscreenG.fillRect(EnLo+EnPE, yOrigin+25, EnKE, 8); offscreenG.drawString("frequency = " + nf.format(f) + " Hz", 300, 220); offscreenG.drawString("angular freq. = " + nf.format(w) + " rad/s", 300, 240); offscreenG.drawString("x = " + nf.format(x) + " m", 300, 260); offscreenG.drawString("v = " + nf.format(v) + " m/s", 300, 280); offscreenG.drawString("a = " + nf.format(a) + " m/s^2", 300, 300); offscreenG.drawString("t = " + nf.format(t) + " s", 300, 320); offscreenG.drawString("KE = " + nf.format(KE) + " J", 300, 360); offscreenG.drawString("Total energy = " + nf.format(totalEnergy) + " J", 300, 380); g.drawImage(offscreenImg,0,0,this); } public void destroy() { offscreenG.dispose(); } public boolean action (Event evt, Object arg) { if (evt.target instanceof Button) { if ((Button)evt.target == Reset) { startFlag = false; pauseFlag = false; Start.setLabel(" Start "); } else if ((Button)evt.target == Start) { if (Start.getLabel().equals(" Start ")) { startFlag = true; pauseFlag = true; Start.setLabel("Pause"); } else { startFlag = false; pauseFlag = true; Start.setLabel(" Start "); } } } else return super.action(evt, arg); return true; } public boolean handleEvent(Event evt) { if (evt.target instanceof Scrollbar) { if ((Scrollbar)evt.target == xInitscroll) { xInit = ((Scrollbar)evt.target).getValue(); xInitS.setText(String.valueOf(xInit)); } else if ((Scrollbar)evt.target == springKscroll) { springK = ((Scrollbar)evt.target).getValue(); springKS.setText(String.valueOf(springK)); } repaint(); } else return super.handleEvent(evt); return true; } }