//: BangBean2.java ////////////////////////////////////////////////// // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" // All rights reserved EXCEPT as allowed by the // following statements: You can freely use this file // for your own work (personal or commercial), // including modifications and distribution in // executable form only. Permission is granted to use // this file in classroom situations, including its // use in presentation materials, as long as the book // "Thinking in Java" is cited as the source. // Except in classroom situations, you cannot copy // and distribute this code; instead, the sole // distribution point is http://www.BruceEckel.com // (and official mirror sites) where it is // freely available. You cannot remove this // copyright and notice. You cannot distribute // modified versions of the source code in this // package. You cannot use this file in printed // media without the express permission of the // author. Bruce Eckel makes no representation about // the suitability of this software for any purpose. // It is provided "as is" without express or implied // warranty of any kind, including any implied // warranty of merchantability, fitness for a // particular purpose or non-infringement. The entire // risk as to the quality and performance of the // software is with you. Bruce Eckel and the // publisher shall not be liable for any damages // suffered by you or any third party as a result of // using or distributing software. In no event will // Bruce Eckel or the publisher be liable for any // lost revenue, profit, or data, or for direct, // indirect, special, consequential, incidental, or // punitive damages, however caused and regardless of // the theory of liability, arising out of the use of // or inability to use software, even if Bruce Eckel // and the publisher have been advised of the // possibility of such damages. Should the software // prove defective, you assume the cost of all // necessary servicing, repair, or correction. If you // think you've found an error, please email all // modified files with clearly commented changes to: // Bruce@EckelObjects.com. (Please use the same // address for non-code errors found in the book.) ///////////////////////////////////////////////// // You should write your Beans this way so they // can run in a multithreaded environment. import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; public class BangBean2 extends Canvas implements Serializable { private int xm, ym; private int cSize = 20; // Circle size private String text = "Bang!"; private int fontSize = 48; private Color tColor = Color.red; private Vector actionListeners = new Vector(); public BangBean2() { addMouseListener(new ML()); addMouseMotionListener(new MM()); } public synchronized int getCircleSize() { return cSize; } public synchronized void setCircleSize(int newSize) { cSize = newSize; } public synchronized String getBangText() { return text; } public synchronized void setBangText(String newText) { text = newText; } public synchronized int getFontSize() { return fontSize; } public synchronized void setFontSize(int newSize) { fontSize = newSize; } public synchronized Color getTextColor() { return tColor; } public synchronized void setTextColor(Color newColor) { tColor = newColor; } public void paint(Graphics g) { g.setColor(Color.black); g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize); } // This is a multicast listener, which is // more typically used than the unicast // approach taken in BangBean.java: public synchronized void addActionListener ( ActionListener l) { actionListeners.addElement(l); } public synchronized void removeActionListener( ActionListener l) { actionListeners.removeElement(l); } // Notice this isn't synchronized: public void notifyListeners() { ActionEvent a = new ActionEvent(BangBean2.this, ActionEvent.ACTION_PERFORMED, null); Vector lv = null; // Make a copy of the vector in case someone // adds a listener while we're // calling listeners: synchronized(this) { lv = (Vector)actionListeners.clone(); } // Call all the listener methods: for(int i = 0; i < lv.size(); i++) { ActionListener al = (ActionListener)lv.elementAt(i); al.actionPerformed(a); } } class ML extends MouseAdapter { public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.setColor(tColor); g.setFont( new Font( "TimesRoman", Font.BOLD, fontSize)); int width = g.getFontMetrics().stringWidth(text); g.drawString(text, (getSize().width - width) /2, getSize().height/2); g.dispose(); notifyListeners(); } } class MM extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { xm = e.getX(); ym = e.getY(); repaint(); } } // Testing the BangBean2: public static void main(String[] args) { BangBean2 bb = new BangBean2(); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("ActionEvent" + e); } }); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("BangBean2 action"); } }); bb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("More action"); } }); Frame aFrame = new Frame("BangBean2 Test"); aFrame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); aFrame.add(bb, BorderLayout.CENTER); aFrame.setSize(300,300); aFrame.setVisible(true); } } ///:~