⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 progressbar.java

📁 关于J4ME J2ME实例
💻 JAVA
字号:
package org.j4me.ui.components;

import java.util.*;
import javax.microedition.lcdui.*;
import org.j4me.ui.*;
import org.j4me.util.*;

/**
 * Displays a progress bar that indicates the state of a background
 * process.
 * <p>
 * Progress bars come in two flavors.  There is the standard progress
 * bar which appears as a rectangle that fills from left-to-right as
 * progress toward some known point occurs.  There is also a spinner
 * which is animated to show constant progress and is useful when it
 * is unknown how long the operation will last.  These are differentiated
 * by <code>setMaxSize</code>; when 0 it is a spinner and when positive it
 * is a progress bar.
 */
public class ProgressBar
	extends Component
{
	/**
	 * The millseconds between frames in the spinner animation.  The
	 * number of frames for one complete spin is 12, one for each hour
	 * on the clock.
	 */
	private static final int ANIMATION_INTERVAL = 2000 / 12;

	/**
	 * The percentage of the screen's width that a progress bar is.
	 */
	private static final double SCALE_WIDTH = 1.00;  // 100%
	
	/**
	 * The number of times the default font height that the progress bar
	 * should be. 
	 */
	private static final double SCALE_HEIGHT = 2.0;
	
	/**
	 * The label that appears right above the progress bar.  For example it might
	 * say "Downloaded 567 of 10235 bytes".  If this is <code>null</code> then no
	 * label will appear.
	 */
	private Label label;
	
	/**
	 * The amount of the operation represented by this progress bar that
	 * has been completed.  It should be between 0 and <code>max</code>.
	 */
	private int value;
	
	/**
	 * The total amount the operation represented by this progress bar is
	 * working toward.  When <code>current</code> equals <code>max</code> the progress
	 * bar will be full.
	 * <p>
	 * If this is 0, the component will draw itself as a spinner component
	 * because it doesn't know how long the operation will last.
	 */
	private int max;
	
	/**
	 * One less than the current hour pointed to by the spinner component.
	 * As the spinner rotates, this is the leading edge (i.e. fully colored).
	 * It goes between 0-11 so the actual hour is 1 greater.
	 */
	private int spinnerHour;
	
	/**
	 * A timer that triggers animation events every
	 * <code>ANIMATION_INTERVAL</code> milliseconds when this component is
	 * visible.
	 */
	private Timer timer;
	
	/**
	 * Creates a progress bar component.
	 */
	public ProgressBar ()
	{
	}
	
	/**
	 * @return The text that appears above the progess bar.  If
	 *  <code>null</code> there is no text.
	 */
	public String getLabel ()
	{
		if ( label == null )
		{
			return null;
		}
		else
		{
			return label.getLabel();
		}
	}
	
	/**
	 * @param label is the text that appears above the progress bar.
	 *  If <code>null</code> there will be no text.
	 */
	public void setLabel (String label)
	{
		if ( label == null )
		{
			this.label = null;
		}
		else
		{
			if ( this.label == null )
			{
				this.label = new Label();
			}
			
			this.label.setLabel( label );
		}
	}
	
	/**
	 * @return The amount of completed progess.
	 */
	public int getValue ()
	{
		return value;
	}
	
	/**
	 * Sets the maximum amount of progress.  If this is 0, the
	 * total progress is unknown and this component will be represented
	 * by a spinner animation.
	 * 
	 * @param value is the amount of completed progess.
	 */
	public void setValue (int value)
	{
		if ( value < 0 )
		{
			this.value = 0;
		}
		else if ( value > max )
		{
			this.value = max;
		}
		else
		{
			this.value = value;
		}
	}
	
	/**
	 * Returns the maximum amount of progress.  If this is 0, the
	 * total progress is unknown and this component will be represented
	 * by a spinner animation.
	 * 
	 * @return The maximum amount of progress.
	 */
	public int getMaxValue ()
	{
		return max;
	}
	
	/**
	 * @param max is the maximum amount of progress.
	 */
	public void setMaxValue (int max)
	{
		// Set the max.
		if ( max < 0 )
		{
			this.max = 0;
		}
		else
		{
			// Stop the animation timer in case it was running.
			stopTimer();
			
			this.max = max;
		}
		
		// Make sure the current value isn't more than the new max.
		if ( this.max < value )
		{
			value = this.max;
		}
	}

	/**
	 * Paints the progress bar. 
	 * 
	 * @param g is the <code>Graphics</code> object to be used for rendering the item.
	 * @param theme is the application's theme.  Use it to get fonts and colors.
	 * @param width is the width, in pixels, to paint the component.
	 * @param height is the height, in pixels, to paint the component.
	 * @param selected is <code>true</code> when this components is currently selected
	 *  and <code>false</code> when it is not.
	 * 
	 * @see org.j4me.ui.components.Component#paintComponent(Graphics, Theme, int, int, boolean)
	 */
	protected void paintComponent (Graphics g, Theme theme, int width, int height, boolean selected)
	{
		int y = 0;
		
		// Paint the label above this component.
		if ( label != null )
		{
			// Make the justification the same as for this component.
			label.setHorizontalAlignment( this.getHorizontalAlignment() );
			
			// Paint the label.
			label.paint( g, theme, getScreen(), 0, 0, width, height, selected );
			
			// The top of the progress bar is below the label.
			int labelHeight = label.getHeight();
			y = labelHeight;
			height -= labelHeight;
		}
		
		if ( max == 0 )
		{
			startTimer();
			paintSpinner( g, theme, 0, y, width, height, selected );
		}
		else
		{
			paintBar( g, theme, 0, y, width, height, selected );
		}
	}

	/**
	 * Paints a progress bar that shows an operation with a known duration.
	 * The bar fills in left-to-right as progress occurs.  The portion on the 
	 * left indicating completed progress will take up <code>getCurrent / getMax</code>
	 * percent of the progress bar. 
	 * 
	 * @param g is the <code>Graphics</code> object to be used for rendering the item.
	 * @param theme is the application's theme.  Use it to get fonts and colors.
	 * @param x is the left side of the component.
	 * @param y is the top side of the component.
	 * @param width is the width, in pixels, to paint the component.
	 * @param height is the height, in pixels, to paint the component.
	 * @param selected is <code>true</code> when this components is currently selected
	 *  and <code>false</code> when it is not.
	 */
	protected void paintBar (Graphics g, Theme theme, int x, int y, int width, int height, boolean selected)
	{
		// Calculate the completed progress.
		double percentageCompleted = (double)value / (double)max;
		int completedWidth = (int)MathFunc.round( width * percentageCompleted );

		// Paint the completed portion of the progress bar.
		int complete = theme.getBorderColor();
		int highlight = theme.getHighlightColor();

		Theme.gradientFill( g, x, y, completedWidth, height, true, complete, highlight, 0.50 );
	
		// Paint the uncompleted portion of the progress bar.
		int incomplete = theme.getBackgroundColor();
		g.setColor( incomplete );

		g.fillRect( x + completedWidth, y, x + width - completedWidth, height );

		// Paint a border around the progress bar.
		int border = theme.getBorderColor();
		g.setColor( border );
		
		g.drawRect( x, y, width - 1, height - 1 );
	}
	
	/**
	 * Paints a spinner component used to show progress during an operation
	 * of an unknown duration.
	 * 
	 * @param g is the <code>Graphics</code> object to be used for rendering the item.
	 * @param theme is the application's theme.  Use it to get fonts and colors.
	 * @param x is the left side of the component.
	 * @param y is the top side of the component.
	 * @param width is the width, in pixels, to paint the component.
	 * @param height is the height, in pixels, to paint the component.
	 * @param selected is <code>true</code> when this components is currently selected
	 *  and <code>false</code> when it is not.
	 */
	protected void paintSpinner (Graphics g, Theme theme, int x, int y, int width, int height, boolean selected)
	{
		// The component is square so get the size of a side.
		int side = Math.min( width, height );
		
		// Get the diameter of a circle that makes up the spinner.
		int diameter = side / 6;
		int radius = diameter / 2;
		
		// The centers of all the circles are on the hour hands of a clock. 
		double toCenter = side / 3;
		int temp = (side / 2) - radius;
		int left = x + temp;
		int top = y + temp;
		
		// Adjust for the horizontal alignment.
		int horizontalAlignment = getHorizontalAlignment();
		
		if ( horizontalAlignment == Graphics.HCENTER )
		{
			left += (width - side) / 2; 
		}
		else if ( horizontalAlignment == Graphics.RIGHT )
		{
			left += (width - side); 
		}
		
		// The color of this circle is between the background and primary
		// component color.  (spinnerHour + 1) is at full color while one
		// more is at the background color.  This gives the illusion of
		// it moving clockwise.
		int background = theme.getBackgroundColor();
		int foreground = theme.getBorderColor();
		
		int redStart   = (background & 0x00FF0000) >> 16;
		int greenStart = (background & 0x0000FF00) >> 8;
		int blueStart  = (background & 0x000000FF);
		
		int redDelta   = (foreground & 0x00FF0000) >> 16;
		int greenDelta = (foreground & 0x0000FF00) >> 8;
		int blueDelta  = (foreground & 0x000000FF);

		redDelta = (redDelta - redStart) / 12;
		greenDelta = (greenDelta - greenStart) / 12;
		blueDelta = (blueDelta - blueStart) / 12;
		
		// Draw each circle.
		for ( int hour = 1; hour <= 12; hour++ )
		{
			// Each hour hand on a clock is spaced 30 degrees apart (360 degrees / 12 hours).
			// They fall onto a 30-60-90 degree triangle.
			
			// Calculate the center of this circle.
			int angle = ((hour - 3) * -30 + 360) % 360;  // 3 o'clock = 0 degrees, 12 = 90 degrees
			double radians = Math.toRadians( angle );
			int cx = (int)MathFunc.round( Math.cos(radians) * toCenter );
			int cy = (int)MathFunc.round( Math.sin(radians) * toCenter ) * -1;  // Y-coordinates flipped on screen

			// Draw a circle for this spoke on the spinner.
			int offset = ((hour - spinnerHour) + 12) % 12;
			int red = redStart + (offset * redDelta);
			int green = greenStart + (offset * greenDelta);
			int blue = blueStart + (offset * blueDelta);
			g.setColor( red, green, blue );
			
			g.fillRoundRect( left + cx, top + cy,
					diameter, diameter, diameter, diameter );
		}
	}
	
	/**
	 * Returns the dimensions of the progress bar.
	 * 
	 * @see org.j4me.ui.components.Component#getPreferredComponentSize(org.j4me.ui.Theme, int, int)
	 */
	protected int[] getPreferredComponentSize (Theme theme, int viewportWidth, int viewportHeight)
	{
		int width = (int)( viewportWidth * SCALE_WIDTH );
		
		int fontHeight = theme.getFont().getHeight();
		int height = (int)( fontHeight * SCALE_HEIGHT );
		
		if ( max == 0 )
		{
			// Make sure height of spinners is divisible by 6.
			height += (height % 6);
		}

		// Add the height of the label above the component.
		if ( label != null )
		{
			int[] labelDimensions = label.getPreferredComponentSize( theme, viewportWidth, viewportHeight );
			height += labelDimensions[1];
		}
		
		return new int[] { width, height };
	}
	
	/**
	 * Starts the animation timer for this spinner.
	 */
	private void startTimer ()
	{
		if ( timer == null )
		{
			timer = new Timer();
			timer.schedule( new SpinnerTask(), 0, ANIMATION_INTERVAL );
		}
	}
	
	/**
	 * Stops the animation timer for this spinner.
	 */
	private void stopTimer ()
	{
		if ( timer != null )
		{
			timer.cancel();
			timer = null;
		}
	}
	
	/**
	 * An event raised whenever the component is made visible on the screen.
	 * This is called before the <code>paintComponent</code> method.
	 * 
	 * @see Component#showNotify()
	 */
	protected void showNotify ()
	{
		// Pass the event to contained components.
		if ( label != null )
		{
			label.show( true );
		}

		// Continue processing the event.
		super.showNotify();
	}

	/**
	 * An event raised whenever the component is removed from the screen.
	 * 
	 * @see Component#hideNotify()
	 */
	protected void hideNotify ()
	{
		// Pass the event to contained components.
		if ( label != null )
		{
			label.show( false );
		}
		
		// If this is a spinner, stop it.
		stopTimer();
		
		// Continue processing the event.
		super.hideNotify();
	}
	
	/**
	 * A task executed at regularly scheduled intervals that forces
	 * the spinner animation to advance to the next frame.
	 */
	private final class SpinnerTask
		extends TimerTask
	{
		public void run ()
		{
			// Increment the position of the lead spoke.
			spinnerHour = (spinnerHour + 1) % 12;
			
			// Repaint the spinner.
			ProgressBar.this.repaint();
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -