// BasicGUI.java // This is like SampleGUI.java, but with the sample code removed, // making this a better starting point for your own code. // David Kosbie, 15-111/AB, Spring 2007 // Last modified: 8-Feb-07 /* Standard disclaimer: As usual with sample code designed (often in class!) to demonstrate specific issues, the style may not be perfect (it is especially lacking comments and some top-down design), and there may even be a bug or two lurking in the code! Note: you are not responsible for the code in the bottom half of this file (there is a comment clearly indicating where this occurs). This code lets you create Java GUI applications! It does so by providing you with two helper classes: IntroCsApplication and IntroCsComponent Typically, you would create one subclass of each -- your main would typically just create a single instance of your application subclass, and that would create one or more instances of your component subclass. The sample code below demonstrates how to do this. Here are the API's. The dot-dot-dot's indicate methods that you should OVERRIDE, the semicolons are methods you can call but typically would not override. ////////////////////////////////////////////// // IntroCsApplication API ////////////////////////////////////////////// public class IntroCsApplication { public void init() { ... } public Component add(Component c); public void addButtons(String... buttonLabels) { ... } public void onButtonPressed(String label) { ... } public void startTimer(int timerDelay); public void onTimer() { ... } public void beep(); } ////////////////////////////////////////////// // IntroCsComponent API ////////////////////////////////////////////// class IntroCsComponent { public void paintComponent(Graphics page) { ... } public void onMousePressed(int x, int y) { ... } public void onMouseDragged(int x, int y) { ... } public void onMouseReleased(int x, int y) { ... } public void startTimer(int timerDelay); public void onTimer() { ... } public void onResized() { ... } public void beep(); } Note that the helper classes definitely abstract away some of the complexities of writing Swing applications (that's why they are there, after all!). If you want to see what's going on, well, by all means: the code is at the bottom of this file, so go take a look! */ import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; public class BasicGUI extends IntroCsApplication { public static void main(String[] args) { new BasicGUI(); } public void init() { add(new CustomComponent()); } public void onButtonPressed(String label) { } public void onTimer() { } } class CustomComponent extends IntroCsComponent { public void paintComponent(Graphics page) { int width = this.getWidth(), height = this.getHeight(); page.setColor(Color.green); page.fillRect(0,0,width,height); page.setColor(Color.orange); page.fillOval(50,50,width-100,height-100); page.setColor(Color.blue); page.setFont(new Font("Arial",Font.BOLD,36)); page.drawString("Basic GUI",100,100); } //////////////////////////////////////////// // Event Handlers //////////////////////////////////////////// public void onMousePressed(int x, int y) { } public void onMouseDragged(int x, int y) { } public void onMouseReleased(int x, int y) { } public void onKeyPressed(KeyEvent e, int keyCode, char keyChar) { } public void onTimer() { } public void onResized() { } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // You are not (yet) responsible for the code below here! //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// class IntroCsComponent extends JComponent { public IntroCsComponent() { this.addEventListeners(); this.setPreferredSize(new Dimension(400,400)); } // override these methods to respond to events public void onTimer() { } public void onMousePressed(int x, int y) { } public void onMouseDragged(int x, int y) { } public void onMouseReleased(int x, int y) { } public void onKeyPressed(KeyEvent e, int keyCode, char keyChar) { } public void onResized() { } public void beep() { Toolkit.getDefaultToolkit().beep(); } public void startTimer(final int timerDelay) { // use invokeLater to allow window to become visible before starting // to be initialized in subclasses before calling init() method javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new javax.swing.Timer(timerDelay, new ActionListener() { public void actionPerformed(ActionEvent evt) { onTimer(); repaint(); } }).start(); } }); } protected void addEventListeners() { // add actions in response to mouse events addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { onMousePressed(e.getX(),e.getY()); repaint(); } public void mouseReleased(MouseEvent e) { onMouseReleased(e.getX(),e.getY()); repaint(); } }); // and for mouse motion events addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { onMouseDragged(e.getX(),e.getY()); repaint(); } }); // and for keyboard events addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { onKeyPressed(e,e.getKeyCode(),e.getKeyChar()); repaint(); } }); // and for component events addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { onResized(); repaint(); } }); } } class IntroCsApplication extends JFrame { public void init() { // override this method to add your buttons, objects, etc } public void onTimer() { } // This method lives outside the anonymous inner class Runnable // so that getClass() returns this class (in fact, the overridden subclass) protected String makeTitle() { return this.getClass().getName(); } public IntroCsApplication() { super(); Container cp = this.getContentPane(); cp.setBackground(Color.white); cp.setLayout(new BoxLayout(cp,BoxLayout.Y_AXIS)); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // use invokeLater to allow instance variables (like buttonLabels[]) // to be initialized in subclasses before calling init() method javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { init(); // override this method! pack(); if (focusComponent != null) // send key events to this component! focusComponent.requestFocusInWindow(); setTitle(makeTitle()); setVisible(true); } }); } private IntroCsComponent focusComponent = null; public Component add(Component c) { Component result = super.add(c); if (c instanceof IntroCsComponent) { // the first one added gets the keyboard by default if (focusComponent == null) { focusComponent = (IntroCsComponent) c; // send key events to this component! focusComponent.requestFocusInWindow(); } } return result; } public void onButtonPressed(String label) { System.out.printf("onButtonPressed(%s)\n",label); } public void addButtons(String... buttonLabels) { JPanel buttons = new JPanel(); buttons.setLayout(new BoxLayout(buttons,BoxLayout.X_AXIS)); for (int i=0; i