330 likes | 523 Views
Java applet. ใช้ยังไง. มันรันจากหน้า html ซึ่งหน้านั้นต้องมี tag ที่บอกข้อมูล เอา applet อะไร ( class file อยู่ไหน) จะอยู่ตรงไหนในหน้า browser (size, location) Browser ต้องมี java plug-in นะ ดูตัวอย่างหน้าต่อไปเลย. ต้อง extends ตัวนี้. import java.awt.*;
E N D
ใช้ยังไง • มันรันจากหน้า html ซึ่งหน้านั้นต้องมี tag ที่บอกข้อมูล • เอา applet อะไร (class file อยู่ไหน) • จะอยู่ตรงไหนในหน้า browser (size, location) • Browser ต้องมี java plug-in นะ • ดูตัวอย่างหน้าต่อไปเลย
ต้อง extends ตัวนี้ import java.awt.*; import javax.swing.*; /** * @version 1.22 2007-06-12 * @author Cay Horstmann */ public class NotHelloWorldApplet extends JApplet { public void init() { EventQueue.invokeLater(new Runnable() { public void run() { JLabel label = new JLabel("Not a Hello, World applet", SwingConstants.CENTER); add(label); } }); } } เรียกเมื่อโหลดครั้งแรก สั่งการอัพเดท user interface ไปที่ event dispatch thread เพื่อให้รันขนานกับ main ต่อไปนี้ถ้าจะเซ็ตอะไรใน GUI ก็ต้องทำในนี้จะดีกว่า invokeLaterรีเทิร์นทันที ต่อจากนี้ต้องสร้าง html ที่มีแท็กดังนี้
หน่วยเป็นพิกเซล <applet code="NotHelloWorldApplet.class" width="300" height="100"> </applet> แค่นี้ก็เอาหน้านี้เป็นตัวรันโปรแกรมจาว่าเราได้แล้ว ลองใช้ appletviewer xxx.html เปิดดูก็ได้ หรือเขียนแท็กนี้ในคลาสไฟล์แล้วใส่คอมเม้นก็ได้ ซึ่ง appletviewerก็จะรันจากคลาสได้เลย
แต่ตัวนี้มันเห็นแค่ applet ไม่เห็นส่วนอื่นในหน้า browser นั้น ถ้ามีการคอมไพล์ใหม่ ต้องปิดและเปิดบราวเซอร์ใหม่เลย ไม่งั้นโค้ดใหม่ไม่โหลด
วิธีเปลี่ยน application เป็น applet • สร้างหน้า html ที่โหลดคลาสได้ • สร้าง public class ที่ extends Japplet • เอา main method ทิ้งไป • ไม่ต้องสร้างเฟรมหลักให้ GUI แล้ว เพราะมันจะอยู่ในบราวเซอร์ • อะไรที่เคยเขียนในคอนสตรัคเตอร์ของเฟรมหลัก ให้มาเขียนใน init • ไม่ต้องสร้าง applet ออบเจ็กต์ เพราะบราวเซอร์ทำให้และบราวเซอร์จะเรียก init ให้เอง • ไม่ต้องเรียก setSizeอีกแล้ว เพราะทำจากหน้าเว็บไง • ไม่ต้องเรียก setDefaultCloseOperationเพราะว่าตอนนี้เราปิดบราวเซอร์แทน • ไม่ต้องเรียก setTitleและ setVisibleด้วยเช่นกัน
เมธอดต่างๆที่เราอาจต้อง override void start() รันทุกครั้งที่คนเข้ามาดูหน้าเว็บที่มีแอพเพล็ต จากหน้าอื่น void stop() รันทุกครั้งที่คนออกจากหน้าเว็บที่มีแอพเพลต ไปดูหน้าอื่น void destroy() รันทุกครั้งที่บราวเซอร์ถูกปิด void resize(int width, int height) ยังทำงานกับบราวเซอร์ทั่วไปไม่ได้ตอนนี้
Attribute ภายใน Tag • ถ้ามี text อยู่ใน applet tag มันจะถูกแสดงเมื่อบราวเซอร์นั้นแสดงตัวแอพเพล็ตไม่ได้ • width, height อย่าลืมว่า แอพเพล็ตนั้น resize ไม่ได้ • align บอก alignment ของตัวแอพเพล็ต ค่าต่างๆเหมือนค่าในแท็ก imgของเว็บ • vspace, hspaceบอกจะเว้นที่ในแนวตั้ง (ทั้งบนและล่าง)และแนวนอน (ทั้งซ้ายและขวา)หน่วยเป็นพิกเซล • code บอกถึง .class ว่าอยู่ไหน ถ้ามี package ต้องใส่ให้ถูกต้อง
codebase url เพื่อใช้หา .class ไฟล์ ใส่ชื่อเต็มๆได้ • archive บอกจาร์ไฟล์ หรือไฟล์ที่โปรแกรมนี้ใช้ ว่าอยู่ที่ไหน ซึ่งไฟล์พวกนี้จะถูกโหลดจากเว็บเซอร์เวอร์ก่อนที่แอ็พเพล็ตจะถูกโหลด ตัวอย่าง archive = “a.jar, corejava/corejavaclasses.jar’’ • object ใช้บอกชื่อไฟล์ที่มี serialize แอพเพลตออบเจ็กต์ คือเราเก็บค่าของทุกฟิลด์ในไฟล์ ถ้าใช้เมธอดนี้ init จะไม่ถูกเรียกแต่ start จะถูกเรียก ใช้กับการจำ state เอาไว้ • name ใช้ตั้งชื่อแอพเพลต สำหรับให้คนเขียนสคริปต์ใช้ได้ เช่นคนเขียน จาวาสคริปต์ หรือใช้ให้สองแอพเพล็ตติดต่อกันก็ได้
สำหรับ html 4.0 • ไม่ใช้ applet tag แล้ว ใช้ object tag แทน <object> codetype=“application/java” classid=“java:MyApplet.class” width=“100” height=“150” มี codebase ด้วย ทำงานเหมือนเดิมเลย
ถ้า applet ต้องใช้พารามิเตอร์ • เราต้องใส่ค่าพารามิเตอร์ลงใน html นั่นแหละ ตัวอย่างเช่น ให้ html เป็นตัวกำหนด font ที่ applet จะใช้ <applet code=“FontParamApplet.class” width=“100” height=“150”> <param name=“font” value=“Helvetica”/> </applet>
ส่วนการให้ applet อ่านพารามิเตอร์จากหน้า html นั้น ใช้เมธอด getParameter public class FontParamApplet extends JApplet{ public void init(){ … String fontname = getParameter(“font”); … } … } พารามิเตอร์นั้นเป็นสตริงเสมอ ดังนั้นเราต้องเปลี่ยนไทป์เองนะ เช่น intfontSize = Integet.parseInt(getParameter(“size”));
จริงๆ คนทำเว็บอาจจะให้พารามเตอร์มาไม่ครบ ดังนั้นในโค้ดเราจะต้องดักว่าเป็น null หรือไม่ด้วย • ดูตัวอย่าง applet ที่วาดบาร์ชาร์ต
Html ของ applet barchart <applet code="Chart.class" width=400 height=300> <param name="title" value="Diameters of the Planets"/> <param name="values" value="9"/> <param name="name.1" value="Mercury"/> <param name="name.2" value="Venus"/> <param name="name.3" value="Earth"/> <param name="name.4" value="Mars"/> <param name="name.5" value="Jupiter"/> <param name="name.6" value="Saturn"/> <param name="name.7" value="Uranus"/> <param name="name.8" value="Neptune"/> <param name="name.9" value="Pluto"/> <param name="value.1" value="3100"/> <param name="value.2" value="7500"/> <param name="value.3" value="8000"/> <param name="value.4" value="4200"/> <param name="value.5" value="88000"/> <param name="value.6" value="71000"/> <param name="value.7" value="32000"/> <param name="value.8" value="30600"/> <param name="value.9" value="1430"/> </applet> จริงๆจะสร้างอาร์เรย์ขึ้นมาแล้วให้ทำงานอยู่ในโค้ดก็ได้ แต่แบบนี้จะเปลี่ยนกราฟง่ายกว่า โดยไม่ต้องคอมไพล์โค้ดใหม่ และก็ยังทำ applet สองอันในหน้าเว็บเดียวได้ด้วย แค่ใส่พารามิเตอร์คนละชุดกัน
รูปร่าง ตอนรันออกมาแล้วจะเป็นแบบนี้
Code ของ applet barchart import javax.swing.*; public class Chart extends JApplet { public void init() { EventQueue.invokeLater(new Runnable() { public void run() { String v = getParameter("values"); if (v == null) return; int n = Integer.parseInt(v); double[] values = new double[n]; String[] names = new String[n]; for (int i = 0; i < n; i++) { values[i] = Double.parseDouble(getParameter("value." + (i + 1))); names[i] = getParameter("name." + (i + 1)); } add(new ChartComponent(values, names, getParameter("title"))); } }); } }
class ChartComponent extends JComponent { /** * Constructs a ChartComponent. * @param v the array of values for the chart * @param n the array of names for the values * @param t the title of the chart */ public ChartComponent(double[] v, String[] n, String t) { values = v; names = n; title = t; } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; // compute the minimum and maximum values if (values == null) return; double minValue = 0; double maxValue = 0;
for (double v : values) { if (minValue > v) minValue = v; if (maxValue < v) maxValue = v; } if (maxValue == minValue) return; intpanelWidth = getWidth(); intpanelHeight = getHeight(); Font titleFont = new Font("SansSerif", Font.BOLD, 20); Font labelFont = new Font("SansSerif", Font.PLAIN, 10); // compute the extent of the title FontRenderContext context = g2.getFontRenderContext(); Rectangle2D titleBounds = titleFont.getStringBounds(title, context); double titleWidth = titleBounds.getWidth(); double top = titleBounds.getHeight(); ข้อมูลต่างๆ ว่าฮาร์ดแวร์จะวาดฟอนต์อย่างไร เก็บไว้ใช้ในการวาดฟอนต์ทีหลัง Returns the logical bounds of the specified String in the specified FontRenderContext
Y coordinate of the upper-left corner The baseline of the first character is at position (x, y) // draw the title double y = -titleBounds.getY(); // ascent double x = (panelWidth - titleWidth) / 2; g2.setFont(titleFont); g2.drawString(title, (float) x, (float) y); // compute the extent of the bar labels LineMetricslabelMetrics = labelFont.getLineMetrics("", context); double bottom = labelMetrics.getHeight(); y = panelHeight - labelMetrics.getDescent(); g2.setFont(labelFont); // get the scale factor and width for the bars double scale = (panelHeight - top - bottom) / (maxValue - minValue); intbarWidth = panelWidth / values.length; encapsulates the measurement information associated with a run of text distance from the baseline to the descender line. ->the line beneath the lowercase ‘j’ and ‘y.’
// draw the bars for (inti = 0; i < values.length; i++) { // get the coordinates of the bar rectangle double x1 = i * barWidth + 1; double y1 = top; double height = values[i] * scale; if (values[i] >= 0) y1 += (maxValue - values[i]) * scale; else { y1 += maxValue * scale; height = -height; } // fill the bar and draw the bar outline Rectangle2D rect = new Rectangle2D.Double(x1, y1, barWidth - 2, height); g2.setPaint(Color.RED); g2.fill(rect); g2.setPaint(Color.BLACK); g2.draw(rect); // draw the centered label below the bar Rectangle2D labelBounds = labelFont.getStringBounds(names[i], context); double labelWidth = labelBounds.getWidth(); x = x1 + (barWidth - labelWidth) / 2; g2.drawString(names[i], (float) x, (float) y); } } // จบ paintConponent
private double[] values; private String[] names; private String title; } // จบคลาส
เมธอดอื่นๆที่น่าสนใจ เวลาใช้ต้อง override public String getAppletInfo() รีเทิร์นข้อมูล ผู้เขียน เวอร์ชั่น ลิขสิทธิ์ public String[][] getParameterInfo() รีเทิร์นว่า แอพเพล็ต รับพารามิเตอร์อะไรได้บ้าง แต่ละrow จะมีข้อมูล Name, type และคำอธิบายพารามิเตอร์
ไฟล์ภาพกับเสียง • ภาพเป็น png, gif, jpeg • เสียงเป็น au, aiff, wav, midi • ต้องใช้ location ของไฟล์พวกนี้เป็น relative url getDocumentBase รีเทิร์น url ของหน้าเว็บทีมีแอ็พเพล็ต getCodeBase รีเทิร์น url ของโฟลเดอร์ codebase ของแอ็พเพลต
ตัวอย่างการเอาไฟล์ภาพกับเสียงมาใช้ตัวอย่างการเอาไฟล์ภาพกับเสียงมาใช้ Image cat = getImage(getCodeBase(), “images/cat.gif”); AudioClip meaw = getAudioClip(getCodeBase(), “audio/meaw.au”); เล่นเสียง โดย play(getCodeBase() ,“audio/meaw.au”)
void play(URL url) เล่นไฟล์จาก urlเลย void play(URL url, String name) สตริงจะบอก relative path จากพารามิเตอร์แรก AudioClipgetAudioClip(URL, String name) ก็จะมีสองเวอร์ชั่นเหมือนกัน ถ้าหาไฟล์ไม่เจอมันจะรีเทิร์น null getImageก็เป็นเช่นเดียวกันนี้
Applet สั่งงาน browser ได้ • ต้อง getAppletContext ก่อน คือเป็นการเอาตัวเชื่อมระหว่าง บราวเซอร์กับโค้ดมาใช้
ส่งข้อมูลระหว่างสองแอพเพล็ตส่งข้อมูลระหว่างสองแอพเพล็ต • ถ้ามี <applet code =“Chart.class” width = “100” height=“100” name=“Chart1”> เราสามารถเรียกพอยต์เตอร์ของแอพเพล็ตขึ้นมาได้ Applet chart1 = getAppletContext().getApplet(“Chart1”); แล้วเราก็เรียกเมธอดต่างๆ ของchart1 จากอีก applet ได้แล้ว เช่น ((Chart) chart1).setData(…..); -
ตัวอย่าง เอาทุกแอ็พเพลตออกมาปริ๊น Enumeration<Applet> e = getAppletContext().getApplets()l While(e.hasMoreElements()) { Applet a = e.nextElement(); System.out.println(a.getClass().getName());
สั่งบราวเซอร์ให้พิมพ์สตริงลง status lint showStatus (”…”); • สั่งบราวเซอร์ให้เปลี่ยนไปดูเว็บอื่น URL u = new URL(“http:// ….”); getAppletContext().showDocument(u); จะให้เปิดหน้าใหม่ก็ได้ ดู showDocument เวอร์ชั่นต่างๆเอานะ
Two in one เป็นทั้ง application และ applet • สร้าง Jframeที่ในเฟรมมี applet อยู่ใน content pane public class AppletFrame extends JFrame implements AppletStub, AppletContext { public AppletFrame(Applet anApplet) { applet = anApplet; add(applet); ……
ใน main ให้เรา show AppletFrame public class AppletApplication extends NotHelloWorldApplet { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { AppletFrame frame = new AppletFrame(new NotHelloWorldApplet()); frame.setTitle("NotHelloWorldApplet"); frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); }
เปลี่ยน setVisibleของ AppletFrameให้เรียก init กับ start public void setVisible(boolean b) { if (b) { applet.init(); super.setVisible(true); applet.start(); } else { applet.stop(); super.setVisible(false); applet.destroy(); } }
ต้องระวัง ว่าเกิดไปเรียก getAppletContext().getApplet(“Chart1”) โดยที่เป็นแอพพลิเคชั่น จะได้ null ซึ่งทำโปรแกรมเจ๊งได้ • ดังนั้นเราแก้ได้โดยให้โค้ดเราอิมพลีเม้นอินเตอร์เฟสอีกสองตัว แล้วมา setStub • ดูโค้ดเอา มีไฟล์ให้