Java swing look and feel l.jpg
This presentation is the property of its rightful owner.
Sponsored Links
1 / 56

Java Swing Look and Feel PowerPoint PPT Presentation


  • 135 Views
  • Uploaded on
  • Presentation posted in: General

Java Swing Look and Feel. Creation of a Look and Feel package. Introduction. This presentation is designed to show you how to create a Java Look and Feel for the javax.swing package. Note Before Getting Started. You should have a basic understanding of the Java 2D API

Download Presentation

Java Swing Look and Feel

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Java swing look and feel l.jpg

Java Swing Look and Feel

Creation of a Look and Feel package


Introduction l.jpg

Introduction

  • This presentation is designed to show you how to create a Java Look and Feel for the javax.swing package.


Note before getting started l.jpg

Note Before Getting Started

  • You should have a basic understanding of the Java 2D API

    • java.awt.Graphics and java.awt.Graphics2D classes

    • Shape classes

      • java.awt.Rectangle, java.awt.image.Arc, etc.

    • Image classes

      • java.awt.Image, java.awt.images.BufferedImage, etc.

    • java.awt.Font and java.awt.Color

  • You should have a basic understanding of the Java Swing API

    • The various JComponents (JButton, JPanel, etc)

  • You are given great freedom in creating your Java look and feel package. Therefore, you should be familiar with other Java look and feel packages so when creating your own it behaves in a similar manner to other Java look and feel packages.

    • javax.swing.plaf.metal look and feel package


Resources to consider l.jpg

Resources to Consider

  • 5 really good Resources

    • A good book on Java Swing preferably one with a chapter or two on look and feel

      • Java Swing 2nd edition from O’Reilly is what I recommend

        • ISBN 0-596-00408-7

    • The Java API Documentation

      • Always a good resource

      • http://java.sun.com/apis.html#j2se

    • The Java base API source code

      • See what the guys at Sun did

      • http://java.sun.com/j2se/downloads.html

    • Someone else’s look and feel source code

      • See what someone else did, the guys at Sun tend to be more complicated then need be

    • Java Developer’s forums

      • Get help from other developers

      • http://forum.java.sun.com/


Why bother l.jpg

Why Bother

  • Games

    • Current Look and Feels were not designed with games in mind

  • Marketability

    • Company/Software Logo, Trademark, Distinct Look and Feel

  • Company Standards for in house applications

  • Quicker Development of Applications

    • By splitting the look and feel from functionality you can have two different teams developing simultaneously each working on different aspects (functionality and look) at the same time

    • Easier control of look and feel

      • Rather then setting colors, borders, icons, etc. for each instance of the swing components you plan on using.

  • Your swing applications might be running on device rather than a PC


How java look and feel works in a nutshell l.jpg

How Java Look and Feel Works in a Nutshell

  • Each Java Swing lightweight class or JComponent has a corresponding user interface class (UI class or ComponentUI) that is responsible for painting the component to the graphical device.

    • These are controlled 100% by the user

    • Java Swing components that do not have a corresponding UI class are the four heavyweight components: JFrame, JDialog, JWindow, and JApplet.

      • These are controlled by the Operating System and user.

        • Depending on the OS the user has different levels of control

  • The LookAndFeel class holds meta information about the look and feel

    • Within the LookAndFeel class the UIDefaults class associates the UI classes, which are created by the look and feel developer, with the Lightweight Java Swing classes they are suppose to paint

  • The UIManager’s setLookAndFeel methods are used to set which LookAndFeel class is used to associate UI classes with Lightweight Java Swing classes

  • Once the LookAndFeel class is set any call to paint a Lightweight Java Swing class to the graphical device will use the associated UI class

    • The Lightweight Java Swing class calls the UIManager’s getUI method to fetch the corresponding UI class

    • The UIManager, which holds a copy of the UIDefaults class from LookAndFeel class, calls UIDefaults class’s getUI method

    • UIDefaults obtains the UIClassID from the calling Lightweight Java Swing class then it gets the corresponding UI class through reflection

    • Once the UI class is obtained the UI class’s static createUI method is called which returns an instance of the UI class

    • The Lightweight Java Swing class then uses the UI class’s paint method when it is asked to paint or repaint itself

  • See next slide fore detail UML Sequence Diagram


Detailed sequence diagram of how it works l.jpg

Detailed Sequence Diagram of how it works

  • Marc Loy, Robert Eckstein, Dave Wood, James Elliott and Brain Cole, Java Swing, 2nd, (Sebastopol: O’Reilly, 2003), 1012.


Getting started l.jpg

Getting Started

  • Two basic approaches

    • Extending your look and feel from the javax.swing.plaf package

      • Not recommended if your GUI is to run on a PC

        • Every UI class is abstract and therefore needs to be extended

    • Extending your Look and Feel from the javax.swing.plaf.basic package or other look and feel packages

      • Recommended if your GUI is to run on a PC

        • Has an implementation of every UI class

        • Only need to extend the BasicLookAndFeel class

      • The approach of extending from the javax.swing.plaf.basic package is basically the same as extending from any other look and feel package


Uimanager class l.jpg

UIManager Class

  • This class is responsible for setting the look and feel

  • JComponents call this to obtain their corresponding ComponentUI class for the information on how to paint themselves to the graphical device


Lookandfeel class l.jpg

LookAndFeel Class

  • To start, extend the BasicLookAndFeel class

    • This is the class that is passed into UIManager.setLookAndFeel method

    • This class is the center of your look and feel

      • Contains the UIDefaults class

        • Links JComponent classes to ComponentUI classes

        • Lists all the colors, icons, borders, etc. that your look and feel as available to it

      • Contains all the meta information about your look and feel


Lookandfeel class cont l.jpg

LookAndFeel Class Cont.

  • Abstract Methods to Implement

    • getDescription()

      • Returns a String describing this look and feel

    • getID()

      • Returns a String with the ID of this look and feel

    • getName()

      • Returns a String with the name of this look and feel

    • isNativeLookAndFeel()

      • Returns a boolean for whether or not this look and feel is native to the operating system it is instantiated on

      • The Windows look and feel for Java will return true on Window systems and false on all others

      • Custom look and feels will all always return false

    • isSupportedLookAndFeel()

      • Returns a boolean for whether or not this look and feel is supported on the operating system it is instantiated on

      • Cross platform look and feels will usually always return true

    • These methods are used by the UIManager class is a variety of ways


Lookandfeel class cont12 l.jpg

LookAndFeel Class Cont.

  • Static methods

    • The static methods are provided for convenience

  • Other methods to consider overriding

    • initialize()

      • Used for initializing your look and feel

      • Invoked by UIManager before getting the UIDefaults class from the LookAndFeel class

    • uninitialize()

      • Used to uninitialize your look and feel

      • Invoked by UIManager before look and feel is replaced by another look and feel

    • provideErrorFeedback(Component c)

      • Invoked when the user performs an illegal action “such as pasting into an uneditable JTextField that has focus” – Java API


Basiclookandfeel class l.jpg

BasicLookAndFeel Class

  • This is the class to extend when creating your own look and feel

    • By extending the BasicLookAndFeel Class you get an implementation of every UIClass in the javax.swing.plaf.basic package

    • Aside from overriding the abstract methods from the LookAndFeel class there are only three methods you need to override to get started


Basiclookandfeel class cont l.jpg

BasicLookAndFeel Class cont.

  • Three methods that give you complete control of your look and feel

    • initSystemColorDefaults(UIDefaults table)

      • Sets the colors of your look and feel

    • initComponentDefaults(UIDefaults table)

      • Sets the icons, borders, etc. of your look and feel

    • initClassDefaults(UIDefaults table)

      • Sets the UI Classes corresponding to the JComponents they are responsible for painting

  • By overriding these three methods you can customize your look and feel completely

  • They are called before returning the UIDefaults class to the UIManager class in the getDefaults() method of the BasicLookAndFeel class


Uidefaults class l.jpg

UIDefaults class

  • UIDefaults

    • This class holds all the information for your look and feel

    • The information is stored in key/value pairs

    • The UIManager class retrieves Object values from the UIDefaults class based on the key pass to one of the many static getXXX(key) methods

    • Most importantly it holds the Colors, Icons, Borders, Insets, and ComponentUI classes for your look and feel


Note about uidefaults class l.jpg

Note about UIDefaults class

  • A majority of the key/value pairs set by the BasicLookAndFeel in the UIDefaults are only used internally in the look and feel package by the ComponentUI classes

    • This is a good practice to continue because it gives you global control of your look and feel through one class

      • i.e. If one wants to change the color of the buttons in the look and feel. Then one can change the value in the UIDefaults class without having to look for it in the button ComponentUI class

  • The key/value pairs that are used out of the look and feel package are the ones that match JComponent classes to ComponentUI classes

  • With this in mind two conclusions are drawn

    • One is obligated to set all the key/value pairs for the ComponentUI classes

      • This is one reason why extending BasicLookAndFeel is a good idea because these are all set by BasicLookAndFeel

      • Another is that all the Icons, Borders, Colors, etc. are controlled global through the UIDefaults class by default in BasicLookAndFeel

    • One can add any type of key/value pair to the UIDefaults class to use


Uiresource interface l.jpg

UIResource interface

  • This interface is responsible for separating user set colors, borders, insets, etc. from the look and feel’s colors, borders, insets, etc

  • It has NO methods, it is used to mark objects used by the look and feel from those objects set by the user

  • This allows the look and feel developer to separate those values set by the user on the JComponent object from those set by the look and feel.

    • This way the look and feel developer won’t override those values when setting the look and feel or switching to a different look and feel or theme (see javax.swing.plaf.metal look and feel)

  • Every Icon, Inset, Border, ComponentUI class, etc. for the look and feel will have to or already has implemented this interface

  • There are also several convenience classes that implement this interface that are useful

    • ColorUIResource, BorderUIResource, InsetUIResource, etc.


Adding key value pairs to the uidefaults class l.jpg

Adding key/value pairs to the UIDefaults class

  • To add key/values the UIDefaults to first create an Object[] that is the twice the length of the amount of key/value pairs you want to add

    • If you are adding 12 key/value pairs the length of the Object[] is 24

  • Add your key/value pairs to the Object[] by setting the first key to the Object[] at index 0 followed by it’s value at index 1 continue with the next key/value pair at index 2 and 3, continue until the Object[] is full

  • Then call the UIDefaults method putDefaults(Object[] obj) and pass the Object[] to it.


Code example of adding key value pairs to uidefaults l.jpg

Code Example of adding Key/Value pairs to UIDefaults

/* Adding two key values to table */

UIDefaults table …

Object[] key_values = new Object[4];

key_values[0] = “desktop”; // 1st key

key_values[1] = “#FFFFFF”; // 1st key’s value

key_values[2] = “Button.margin”;// 2nd key

key_values[3] = new InsetsUIResource(1,1,1,1);// 2nd key’s value

table.putDefaults(key_values);

Or

UIDefaults table …

Object[] key_values = {

/*KeyValue */

“desktop”,“#FFFFFF”,

“Button.margin”,new InsetsUIResource(1,1,1,1)

};

table.putDefaults(key_values);


Setting system colors l.jpg

Setting System Colors

  • Override the initSystemColorDefaults(UIDefaults table)

    • System Colors

      • Every color used by the BasicLookAndFeel’s UI classes is set by default to one of the System Colors

      • This givens one global control of all the colors in the look and feel

    • Overriding the method

      • Two primary ways

        • One

          • Setting every System Colors’ key/value pair with ColorUIResource Objects

          • Passing the Object[] holding them in the UIDefaults table

        • Two

          • Setting some or all the System Colors’ key/value pairs using String representations for the color values

          • Passing the UIDefaults class, the Object[] with the key/value pairs to the loadSystemColors method


System colors l.jpg

System colors

  • These are the System colors that the BasicLookAndFeel uses

    • desktopColor of the desktop background

    • activeCaptionColor for captions (title bars) when they are active

    • activeCaptionTextText color for text in captions (title bars)

    • activeCaptionBorderBorder color for caption (title bar) window borders

    • inactiveCaptionColor for captions (title bars) when not active

    • inactiveCaptionTextText color for text in inactive captions (title bars)

    • inactiveCaptionBorderBorder color for inactive caption (title bar) window borders

    • windowDefault color for the interior of windows

    • windowBorderColor of the window border

    • windowTextColor of the window text

    • menuBackground color for menus

    • menuTextText color for menus

    • textText background color

    • textTextText foreground color

    • textHighlightText background color when selected

    • textHighlightTextText color when selected

    • textInactiveTextText color when disabled

    • controlDefault color for controls (buttons, sliders, etc)

    • controlTextDefault color for text in controls (buttons, sliders, etc)

    • controlHighlightHighlight color for controls

    • controlLtHighlightLighter highlight color for controls

    • controlShadowShadow color for controls

    • controlDkShadowDark shadow color for controls

    • scrollbarScrollbar background (usually the "track")

    • infoBackground color for informational text

    • infoTextColor for informational text

  • Marc Loy, Robert Eckstein, Dave Wood, James Elliott and Brain Cole, Java Swing, 2nd, (Sebastopol: O’Reilly, 2003), 1059. and Java Source Code for javax.swing.plaf.basic.BasicLookAndFeel Sun Mircosystems Inc.


Example code for overriding initsystemcolordefaults uidefaults table l.jpg

Example Code for Overriding initSystemColorDefaults(UIDefaults table)

//By setting every System color key

protected void initSystemColorDefaults(UIDefaults table) {

ColorUIResource pr1 = new ColorUIResource(new Color(127,127,255));

ColorUIResource pr2 = new ColorUIResource(new Color(0,0,127));

ColorUIResource pr3 = new ColorUIResource(new Color(63,63,191));

ColorUIResource pr4 = new ColorUIResource(new Color(0,0,255));

ColorUIResource blk = new ColorUIResource(Color.BLACK);

ColorUIResource wht = new ColorUIResource(Color.WHITE);

ColorUIResource gry = new ColorUIResource(Color.GRAY);

Object[] colors = {

"desktop" , pr1, /* Color of the desktop background */

"activeCaption" , pr3, /* Color for captions (title bars) when they are active. */

"activeCaptionText" , wht, /* Text color for text in captions (title bars). */

"activeCaptionBorder" , blk, /* Border color for caption (title bar) window borders. */

"inactiveCaption" , pr1, /* Color for captions (title bars) when not active. */

"inactiveCaptionText" , gry, /* Text color for text in inactive captions (title bars). */

"inactiveCaptionBorder" , gry, /* Border color for inactive caption (title bar) window borders. */

"window" , wht, /* Default color for the interior of windows */

"windowBorder" , blk, /* Color of the window border */

"windowText" , blk, /* Color of the window text */

"menu" , pr1, /* Background color for menus */

"menuText" , blk, /* Text color for menus */

"text" , pr1, /* Text background color */

"textText" , blk, /* Text foreground color */

"textHighlight" , pr4, /* Text background color when selected */

"textHighlightText" , wht, /* Text color when selected */

"textInactiveText" , gry, /* Text color when disabled */

"control" , pr1, /* Default color for controls (buttons, sliders, etc) */

"controlText" , blk, /* Default color for text in controls (buttons, sliders, etc) */

"controlHighlight" , pr4, /* Highlight color for controls */

"controlLtHighlight" , wht, /* Lighter highlight color for controls */

"controlShadow" , pr2, /* Shadow color for controls */

"controlDkShadow" , blk, /* Dark shadow color for controls */

"scrollbar" , pr3, /* Scrollbar background (usually the "track") */

"info" , wht, /* Background color for informational text */

"infoText" , blk /* Color for informational text */

};

table.putDefaults(colors);

}


Example code for overriding initsystemcolordefaults uidefaults table23 l.jpg

Example Code for Overriding initSystemColorDefaults(UIDefaults table)

/*By setting only sum and using String representations of the colors */

protected void initSystemColorDefaults(UIDefaults table) {

Object[] colors = {

"desktop“,“#CC5500”,

"activeCaption“,“#FFFFFF”,

"activeCaptionText“,“#000000”

};

loadSystemColors(table, colors, false);

/* the last value false is saying not to override

your changes with the native system colors */

}


Setting components l.jpg

Setting Components

  • Override the initComponentDefaults(UIDefaults table)

    • Components are various objects used by the UI classes

      • Borders, Insets, Fonts, Colors, etc

        • By default all the color components are mapped to one of the System Colors

    • By convention the keys are named by the ComponetUI class that is going to use it

      • i.e. key “button.border” would be the border component used by the ComponentUI button class

    • See Java Swing 2nd Edition by O’Reilly Appendix A for a complete list of all the components set by the BasicLookAndFeel

    • Overriding the method

      • Call the super.initComponentDefaults(UIDefaults table) method (unless you map all the components)

        • This will map all the component key/value pairs from the BasicLookAndFeel

        • Note this is not done in initSystemColorDefaults(UIDefaults table);

      • Set the key/value pairs that are to be changed

      • Pass the Object[] holding the key/value pairs to the UIDefaults.putDefaults(Object[] obj) method


Example code for overriding initcomponentdefaults uidefaults table l.jpg

Example Code for Overriding initComponentDefaults(UIDefaults table)

protected void initComponentDefaults(UIDefaults table) {

super.initComponentDefaults(table);

Object[] components = {

"CheckBox.icon",new CheckBoxIcon(),

"Button.background",pr4,

"Button.foreground",wht,

"Button.font", new Font("Times",Font.BOLD|Font.ITALIC,10)

};

table.putDefaults(components);

}


Setting componentui classes l.jpg

Setting ComponentUI Classes

  • Override the initClassDefaults(UIDefaults table)

    • ComponentUI Classes are the classes responsible for painting the varies JComponents

    • The keys to the ComponentUI class must match what is returned by the JComponent’s getUIClassID() method for the class they are to paint

      • The convention is: the name of the JComponent minus the processing J and adding UI at the end

        • i.e. JButton.getUIClassID() returns the String “ButtonUI” and therefore the key for the UI class must be the String“ButtonUI”

    • The values must be a String object holding the complete name of the ComponentUI class (this is the package+class name)

      • i.e. “william.swing.plaf.blue.BlueButtonUI”

        • The package is william.swing.plaf.blue

        • The class is BlueButtonUI

    • Overriding the method

      • Call the super.initClassDefaults(UIDefaults table) method (unless you map all the ComponentUI classes)

        • This will map all the UI classes key/value pairs from the BasicLookAndFeel

        • Note this is not done in initSystemColorDefaults(UIDefaults table);

      • Set the key/value pairs that are to be changed

      • Pass the Object[] holding the key/value pairs to the UIDefaults.putDefaults(Object[] obj) method


Example code for overriding initclassdefaults uidefaults table l.jpg

Example Code for Overriding initClassDefaults(UIDefaults table)

protected void initClassDefaults(UIDefaults table) {

super.initClassDefaults(table);

//package that the ComponentUI classes belong too

String pkg = "william.swing.plaf.blue.";

Object[] classes = {

"RootPaneUI", pkg + "BlueRootPaneUI",

"PanelUI" , pkg + "BluePanelUI",

"MenuBarUI" , pkg + "BlueMenuBarUI",

"MenuUI" , pkg + "BlueMenuUI",

"ButtonUI" , pkg + "BlueButtonUI"

};

table.putDefaults(classes);

}


Componentui classes l.jpg

ComponentUI Classes

  • These are the classes responsible for painting the JComponents to the graphical device

    • Each ComponentUI class is responsible for painting one of the JComponents

  • They all extend ComponentUI class

  • The convention for naming the ComponentUI Classes is the short name of the look and feel + UIClassID of the JComponent the ComponentUI is to paint

    • i.e. BlueButtonUI (Blue + ButtonUI) is responsible for for painting JButton which returns ButtonUI as its UIClassID


Componentui methods l.jpg

ComponentUI methods

  • public static ComponentUI createUI(JComponent c)

    • The factory method that creates the UI class

    • Two options

      • One: create a singleton

        • How

          • By returning a static class variable of the ComponentUI class

        • Pros

          • Uses less memory because there is only one instance of the ComponentUI class that is responsible for painting

        • Cons

          • No stateful information can be held for a particle JComponent but rather all the JComponets that ComponentUI class is painting for will share the same state

      • Two: create a new instance

        • How

          • By returning a new instance

        • Pros

          • Stateful information may be held by the ComponentUI class of a particle JComponent and can share state through static class variables

        • Cons

          • Uses more memory because each JComponent that needs this ComponentUI class will have an instance of it

      • How to decide

        • More often then not you will use a singleton because any stateful information can be stored in the JComponent itself

        • When the stateful information can not be stored in the JComponent and is critical to the look and feel for that JComponent

    • If extending the Basic Look And Feel this must be overridden and return an instance, singleton or new, of the ComponentUI this method is a member of

      • If not, then the Basic Look And Feel instance will be returned


Example of createui method l.jpg

Example of createUI method

//From william.swing.plaf.blue.BlueButtonUI

//which is responible for painting JButtons

//As a singleton.

//Note the static class variable

private static BlueButtonUI blueButtonUI = new BlueButtonUI();

public static ComponentUI createUI(JComponent c) {

return blueButtonUI;

}

Or

//As a new instance

public static ComponentUI createUI(JComponent c) {

return new BlueButtonUI();

}


Componentui methods cont l.jpg

ComponentUI methods cont.

  • public void installUI(JComponent c)

    • Install default components (Color, Borders, etc.)

      • Set the components on the JComponent if the user has not set them

        • To check if the user has set a component or not

          • Get it from the JComponent

          • Test if it is an instance of UIResourse

          • If it is not a UIResourse then the user set this value

        • If it is not a UIResourse

          • the convention is to leave what the user has set

        • If it is a UIResourse

          • Set the component to what the value is in the UIDefaults table

          • Use the UIManager to get values from the UIDefaults table

        • Examples of methods that set component state from JMenu

          • setForeground(Color fg)

          • setBackground(Color bg)

      • The JComponent holds the various states of the components for painting itself

    • Install listeners

      • Listeners are responsible for setting the state of the JComponent through the varies setters and getters in the JComponent

        • i.e. on a mouse Pressed event of a JButton the listener will set the JButton’s pressed class variable to true through setPressed(boolean p) method

    • Install Keyboard Actions

      • Registers keyboard actions to set state of the JComponent

        • i.e. registering the spacebar to be the same as the left mouse click

    • Install anything else you may need

    • More often then not this method won’t be overridden if you are extending the Basic Look And Feel UI class

    • Called by JComponent when the JComponent calls setUI(ComponentUI ui)

    • Typically the JComponent c is casted to an object of the actual class that is to be painted

      • i.e. if the ComponentUI class is to paint a JSeparator then cast c to a Jseparator object


Example of installui method l.jpg

Example of installUI method

//From william.swing.plaf.blue.BlueButtonUI which is responible for painting JButtons

public void installUI(JComponent c) {

/*Casting the JComponent c to AbstractButton b (several Lightweight Java Swing class extend AbstractButton)*/

AbstractButton b = (AbstractButton)c;

/*Setting the default components for the JButton

Getting the default font, background color and foreground color from the UIDefaults table for buttons*/

background = UIManager.getColor("Button.background");

foreground = UIManager.getColor("Button.foreground");

font = UIManager.getFont("Button.font");

/*Setting background and foreground colors on the JComponent c if the user did NOT set them

These values can be retrieved later by the paint method through c*/

if(c.getBackground()==null || (c.getBackground() instanceof UIResource))

c.setBackground(background);

if(c.getForeground()==null || (c.getForeground() instanceof UIResource))

c.setForeground(foreground);

//Using BasicButtonUI installListeners method to install listeners

super.installListeners(b);

/*Note that there are no keyboard registations, therefore hit any of the keys will not invoke an event*/

}


Componentui methods cont33 l.jpg

ComponentUI methods cont.

  • public void uninstallUI(JComponent c)

    • Used to remove and cleanup

      • Listeners

      • Keyboard Actions

      • Components

      • Anything else

    • More often then not this method won’t be overridden if you are extending the Basic Look And Feel UI class

    • Called by JComponent when the JComponent calls setUI(ComponentUI ui) if and only if the JComponent previously had a set it’s UI class


Example of uninstallui method l.jpg

Example of uninstallUI method

//From javax.swing.plaf.basic.BasicButtonUI

public void uninstallUI(JComponent c) {

//Uninstalling keyboard registations

uninstallKeyboardActions((AbstractButton) c);

//Uninstalling listeners

uninstallListeners((AbstractButton) c);

//Uninstalling default components

uninstallDefaults((AbstractButton) c);

}


Componentui methods cont35 l.jpg

ComponentUI methods cont.

  • Sizing methods

    • Three sizing methods

      • getMinimumSize()

      • getMaximumSize()

      • getPreferredSize()

    • Used by various Layout Managers to get the size of the Graphics object for the JComponent

      • Some will ignore these values

        • i.e. GridLayout and BorderLayout


Componentui methods cont36 l.jpg

ComponentUI methods cont.

  • public voidpaint(Graphics g, JComponent c)

    • Thismethod is responsible for painting the JComponent to the graphical device

    • Most of the work will be done here

    • Graphical state and function state information is obtained from the JComponent

      • Examples of Graphical states

        • Foreground color

        • Background color

        • Borders

      • Examples of Function states

        • Is the button pressed

    • The Graphics object is really a Graphics2D object


Example of paint method l.jpg

Example of paint method

//Example of painting semi-translucent lines on a MenuBar

public void paint(Graphics g, JComponent c) {

super.paint(g, c);

//Get the state of the background color from the JComponent

Color bg = c.getBackground().darker().darker();

g.setColor(new Color(bg.getRed(),bg.getGreen(),bg.getBlue(),127));

/*Added lines at every 5 pixels of 1 pixel height and the width of the JMenuBar

Note the getting of the width and height from the JMenuBar and that the Graphic starts at 0,0*/

for(int j=0;j<c.getHeight();) {

g.fillRect(0,j,c.getWidth(),1);

j=j+5;

}

}


Non componentui methods l.jpg

Non-ComponentUI methods

  • If you are extending the Basic look and feel you will have various methods available to use depending on the UI Class.


3 ways to control look and feel l.jpg

3 Ways to Control Look and Feel

  • With the preceding covered, 3 ways of controlling look and feel should become evident by extending the javax.swing.plaf.basic look and feel package

    • Through color

    • Through components

    • Through CompnentUI classes


Through color l.jpg

Through Color

  • This is the simplest of the three methods

    • Override the initSystemColorDefaults(UIDefaults table) method

      • Set the System colors as desired

    • With a little trial and error one can see quickly what System colors control what components


Through components l.jpg

Through Components

  • This is a bit harder than through colors but gives greater control

  • Override the initComponentDefaults(UIDefaults table) method

    • Set icons, borders, insets, etc. as desired

      • Creating your own components

        • Become familiar with the component you are going to create

        • It is easiest to create a factory class that will return instances of your components, which will be inner classes of your factory class (This approach is best if you have multiple types of a particular component)

          • All types of a component are centrally located in one class so the management is easier

          • i.e. all your borders will be inner classes of and created by your border factory class


Example of a checkbox icon component cont l.jpg

Example of a Checkbox Icon Component cont.

package william.swing.plaf.blue;

import java.awt.*;

import java.io.Serializable;

import java.net.URL;

import javax.swing.*;

//I could have implemented javax.swing.plaf.IconUIResource

public class CheckBoxIcon implements UIResource, Icon, Serializable {

//two images to represent the checkbox being unchecked and checked

Image unchecked = null, checked = null;

//the size of this icon

int width = 20, height = 20;

//the constructor is loading the images

public CheckBoxIcon() {

unchecked = new ImageIcon(this.getClass().getResource("/william/swing/plaf/blue/unchecked.gif")).getImage();

checked = new ImageIcon(this.getClass().getResource("/william/swing/plaf/blue/checked.gif")).getImage();

}

public int getIconWidth() {

return width;

}

public int getIconHeight() {

return height;

}


Example of a checkbox icon component cont43 l.jpg

Example of a Checkbox Icon Component cont.

/*c is the checkbox, g is the Graphics object from the paint method of the CheckboxUI class

x and y are where the icon is to be painted on the Graphics object g */

public void paintIcon(Component c, Graphics g, int x, int y) {

/*This icon will be used with a JCheckBox

so the assumption can be made to cast it as an AbstractButton

will provide state information of the checkbox */

ButtonModel model = ((AbstractButton)c).getModel();

//This ant aliasing provides a nice blended into the background

((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

//Drawing the unchecked image by default at x and y

g.drawImage(unchecked,x,y,width,height,null);

//If the checkbox is checked then paint over the unchecked image with the checked image

if(model.isSelected()||model.isPressed()||model.isArmed())

g.drawImage(checked,x,y,width,height,null);

//Drawing a 2px circle around the checkbox

g.drawOval(x+1,y+1,width-1,height-1);

g.drawOval(x,y,width,height);

}

}


Example of a checkbox icon component cont44 l.jpg

Example of a Checkbox Icon Component cont.

//Then you just add it to the UIDefaults table

protected void initComponentDefaults(UIDefaults table) {

super.initComponentDefaults(table);

Object[] components = {

"CheckBox.icon",new CheckBoxIcon()

};

table.putDefaults(components);

}

The checkbox goes from this:

To this:

It should be noted that this would be better as a radio button then a check box due to its round nature


Example of a checkbox icon component cont45 l.jpg

Example of a Checkbox Icon Component cont.

  • Two notes about using images

    • One

      • One can obtain an URL object representing the locate of a resource relative to your class path by invoking this.getClass().getResource(String relative_path) method

        • This way one can store all images within the look and feel package for that look and feel

    • Two

      • By using the javax.swing.ImageIcon class for retrieving Images one is guaranteed the image will be loaded in the Image object when getImage() method is called

        • This is easier and safer than use the DefaultToolkit from the java.awt.Toolkit class for loading images


Through componentui classes l.jpg

Through ComponentUI Classes

  • This is the hardest but gives the greatest control

  • Override the initClassDefaults (UIDefaults table) method

  • The example is of ComponentUI responsible for painting JButton

    • It is good to understand this because of the 40 or so JComponents 8 are buttons and behave very similarly to JButton

    • This example shows how one has to do the following

      • Painting the button

      • Painting the text if there is text

      • Painting the icon if there is an icon

      • Setting up the listeners

      • Determining user values look and feel set values

      • A singleton


Example of a button componentui l.jpg

Example of a Button ComponentUI

package william.swing.plaf.blue;

import java.awt.*;

import java.awt.image.*;

import javax.swing.*;

import java.awt.geom.*;

import javax.swing.plaf.*;

import javax.swing.plaf.basic.*;

import javax.swing.text.View;

public class BlueButtonUI extends BasicButtonUI {

//The singleton istance of BlueButtonUI

static BlueButtonUI b = new BlueButtonUI();

//Default background and foreground

Color background;

Color foreground;

//There will be only one font for this these buttons

Font font;

public BlueButtonUI() {

super();

}

//The factory method returns the singleton

public static ComponentUI createUI(JComponent c) {

return b;

}


Example of a button componentui cont l.jpg

Example of a Button ComponentUI cont.

public void installUI(JComponent c) {

//Since we know this is a JButton it is safe to cast as an AbstractButton

AbstractButton b = (AbstractButton)c;

//Setting the default values from the UIDefaults table

background = UIManager.getColor("Button.background");

foreground = UIManager.getColor("Button.foreground");

font = UIManager.getFont("Button.font");

//Checking for user set values for foreground and background before setting them

//Note that the font compnonent is not checked therefore the value from the UIDefaults table will

//override the user’s values (This is not recommended) further not all the defaults are set

if(c.getBackground()==null || (c.getBackground() instanceof UIResource))

c.setBackground(background);

if(c.getForeground()==null || (c.getForeground() instanceof UIResource))

c.setForeground(foreground);

//Using BasicButtonUI installListeners method to install listeners

super.installListeners(b);

/*Note that there are no keyboard registations, therefore hit any of the keys will not invoke an event*/

}


Example of a button componentui cont49 l.jpg

Example of a Button ComponentUI cont.

//Paints a rounded button that is semi-transparent with lines

public void paint(Graphics g, JComponent c) {

//Once again it is safe to cast as an AbstractButton because we know it is a JButton

AbstractButton b = (AbstractButton)c;

//The ButtonModel holds a lot of the functional state of the button

ButtonModel model = b.getModel();

//Casting to a Graphics2D for convenience, this is safew because we know that the g object is really a Graphics2D object

Graphics2D g2 = (Graphics2D)g;

//Sets the arcs widths and heights

int arc_w = (int)c.getHeight()/2;

int arc_h = arc_w;

Insets i = c.getInsets();

//Gets the area for the text and icon to be painted in with respects to the insets

Rectangle viewRect = new Rectangle(i.left,i.top,b.getWidth()-(i.right+i.left),b.getHeight() - (i.bottom + i.top));

//the area that the text will be drawn in that will be defined

//by SwingUtilities.layoutCompoundLabel

Rectangle textRect = new Rectangle(0,0,0,0);

//the area that the icon will be drawn in that will be defined

//by SwingUtilities.layoutCompoundLabel

Rectangle iconRect = new Rectangle(0,0,0,0);

//I have opted to set the base font size on the size of the button this will cause the font size to skrink or grow with respect to the button size

int fontSize = (int)c.getHeight()/3;

if(fontSize<8)

fontSize = 8;

g2.setFont(new Font(font.getName(),font.getStyle(),fontSize));

//modify text for display, will add ... if clipped and

//determine the text area and icon area

String text = SwingUtilities.layoutCompoundLabel(

c, g2.getFontMetrics(), b.getText(), b.getIcon(),

b.getVerticalAlignment(), b.getHorizontalAlignment(),

b.getVerticalTextPosition(), b.getHorizontalTextPosition(),

viewRect, iconRect, textRect,

b.getText() == null ? 0 : b.getIconTextGap());


Example of a button componentui cont50 l.jpg

Example of a Button ComponentUI cont.

//Starting with a BufferedImage because the graphics object from a BufferedImage respects composite overlay directives

//NOTE the Graphics object passed in to this method does not respect these directives

BufferedImage buffImg = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);

Graphics2D gbi = buffImg.createGraphics();

//Retrieving the state of the colors from the component which were set in the installUI method

Color back = c.getBackground();

Color fore = c.getForeground();

//creating a semi-transparent background for the button

Color bg = new Color(back.getRed(),back.getGreen(),back.getBlue(),127);

//Defining the color of my borders

Color wh = Color.WHITE;

Color gr = Color.GRAY;

//if button is pressed change the background to dark and switch the border colors (this makes it appear that the button is pressed in)

if (model.isArmed() && model.isPressed()) {

Color d = back.darker().darker().darker();

bg = new Color(d.getRed(),d.getGreen(),d.getBlue(),127);

wh = Color.GRAY;

gr = Color.WHITE;

}

//set background color

gbi.setColor(bg);

gbi.fillRoundRect(0,0,c.getWidth(),c.getHeight(),arc_w,arc_h);

//lay in the strips

gbi.setColor(Color.BLACK);

gbi.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN,1.0f));

gbi.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

for(int j=0;j<c.getHeight();) {

gbi.fillRect(0,j,c.getWidth(),2);

j=j+4;

}


Example of a button componentui cont51 l.jpg

Example of a Button ComponentUI cont.

//paint button image

g2.drawImage(buffImg,0,0,c);

//Draw borders (NOTE a better implementation would have created a borders object)

g2.setColor(wh);

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g2.setStroke(new BasicStroke(2.0f));

Arc2D.Double ar1;

ar1 = new Arc2D.Double(0,0,arc_w,arc_h,90,90,Arc2D.OPEN);

g2.draw(ar1);

ar1 = new Arc2D.Double(c.getWidth()-arc_w,1,arc_w,arc_h,0,90,Arc2D.OPEN);

g2.draw(ar1);

g2.fillRect(arc_w/2-2,0,c.getWidth()-arc_w+2,2);

g2.fillRect(0,arc_h/2-2,2,c.getHeight()-arc_h+2);

g2.setColor(gr);

ar1 = new Arc2D.Double(c.getWidth()-arc_w,c.getHeight()-arc_h,arc_w,arc_h,270,90,Arc2D.OPEN);

g2.draw(ar1);

ar1 = new Arc2D.Double(0,c.getHeight()-arc_h,arc_w,arc_h,180,90,Arc2D.OPEN);

g2.draw(ar1);

g2.fillRect(c.getWidth()-1,arc_h/2-2,1,c.getHeight()-arc_h+8);

g2.fillRect(arc_w/2-8,c.getHeight()-2,c.getWidth()-arc_w+16,2);

//painting text

g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

g2.setColor(fore);

//draw the text at the x of the textRect and the y textRect plus the font ascent.

//"The font ascent is the distance from the font's baseline to the top of most

//alphanumeric characters."(From Java API Doc on java.awt.FontMetrics.getAscent())

g2.drawString(text,(int)textRect.getX(),(int)textRect.getY()+g2.getFontMetrics().getAscent());

//If there is an icon paint it at the x and y of the iconRect

if(b.getIcon()!=null)

b.getIcon().paintIcon(c,g,(int)iconRect.getX(),(int)iconRect.getY());

}


Example of a button componentui cont52 l.jpg

Example of a Button ComponentUI cont.

//Then you just add it to the UIDefaults table

protected void initClassDefaults(UIDefaults table) {

super.initClassDefaults(table);

//package that the ComponentUI classes belong too

String pkg = "william.swing.plaf.blue.";

Object[] classes = {

"ButtonUI" , pkg + "BlueButtonUI"

};

table.putDefaults(classes);

}

}


Last note on componentui l.jpg

Last Note on ComponentUI

  • Each ComponentUI is slightly different, though there are strong similarities between many of them (i.e. buttons, panels, etc.), and only through trial and error and reviewing the source code of the Java API or someone else’s look and feel will you be able to fully master each ComponentUI


Future research l.jpg

Future Research

  • Active and Lazy Values

  • GTK+ for Java 1.4

  • How motion is achieved


Glossary for this presentation l.jpg

Glossary for this Presentation

  • Component

    • Any object or class that is use to help create the look and feel

  • ComponentUI

    • Parent class of all UI classes; any UI class (see UI Class)

  • Factory Class

    • A class whose sole purpose it to return instances of classes through factory methods

  • Factory method

    • A static method that is responsible for returning and instance of a class, whether it be a singleton or new instance

  • Heavyweight Java Swing Class

    • Top level swing classes; painting is partly or completely controlled by the OS

  • JComponent

    • Parent class of Lightweight Java Swing classes; any Lightweight Java Swing class (see Lightweight Java Swing Class)

  • Lightweight Java Swing Class

    • A Swing class that allows for pluggable look and feel through UIManager.setLookAndFeel

  • Singleton

    • An instance of a class in which there will be only one instance within of it within the JVM

  • UI Class

    • A class that is responsible for paint a JComponent class


Author l.jpg

Author

  • By William Pohlhaus

    • Email:

      • [email protected]

    • Homepage:

      • http://www.homepage.villanova.edu/william.pohlhaus


  • Login