50% OFF!!!

Tuesday, June 16, 2009

J2ME | Analog Clock control - custom item



Here is an example for anlogic clock control (extends CustomItem) which may be added to Form class and also in Canvas class.
for Form class just add it as and item,
and for Canvas class and its paint method, provide graphics to AnalogClock's paint method.

Here is Code for the analog clock:


package CustomItems;

import javax.microedition.lcdui.*;
import java.util.Calendar;

public class AnalogClock extends CustomItem implements Runnable
{

private double diam = 0.38;
private double LineLengthSeconds = 0.90;
private double LineLengthMinutes = 0.75;
private double LineLengthHour = 0.50;
private double LineLengthTicks = 0.08;
private double TextPositionRelativeR = 1.22;
//
/***
* Represents control's width
*/
private int Width = 100;
/***
* Represents control's height
*/
private int Height = 100;
/***
* Represents clock's radius
*/
private int _raduis;
/***
* Represents clock's center point - X
*/
private int _circleCenterX;
/***
* Represents clock's center point - Y
*/
private int _circleCenterY;
/***
* Represents clock's current date&time
*/
private Calendar _now;
/***
* Represents the thread which implement the clock's ticks
*/
private Thread _thread = null;
/***
* Represents a flag which describe if the thread is running or not
*/
private boolean _threadIsRunning = false;
//
/***
* Represents the background color of the clock
*/
public int BackColor = 0xffffff;
/***
* Represents the color of the clock (text & lines)
*/
public int ClockColor = 0x000000;
/***
* A flag which represent whether or not display the date inside the clock
*/
public boolean ShowDate = false;
/***
* Represents the font of the text drawn
*/
public Font Font;

/** Creates a new instance of AnalogClock */
public AnalogClock(String p_label, int p_size)
{
super(p_label);
if (p_size <= 0)
{
sizeChanged(Width, Height);
}
else
{
sizeChanged(p_size, p_size);
}
Font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL);
}

protected int getMinContentWidth()
{
return 10;
}

protected int getMinContentHeight()
{
return 10;
}

protected int getPrefContentWidth(int p_height)
{
return Width;
}

protected int getPrefContentHeight(int p_width)
{
return Height;
}

protected void sizeChanged(int p_w, int p_h)
{
Height = p_h;
Width = p_w;
int size = Math.min(Width, Height);
_raduis = (int) (diam * (double) size);
_circleCenterX = size / 2;
_circleCenterY = size / 2;
_now = Calendar.getInstance();
}

private int pointX(double minute, double radius, int _circleCenterX)
{
double angle = minute * Math.PI / 30.0;
return (int) ((double) _circleCenterX + radius * Math.sin(angle));
}

private int pointY(double minute, double radius, int oy)
{
double angle = minute * Math.PI / 30.0;
return (int) ((double) oy - radius * Math.cos(angle));
}

public void updateTime()
{
_now = Calendar.getInstance();
repaint();
}

public void updateTime(Calendar p_currtime)
{
_now = p_currtime;
repaint();
}

protected void paint(Graphics g, int w, int h)
{
// clear background
g.setColor(BackColor);
g.fillRect(0, 0, Width - 1, Height - 1);
g.setColor(ClockColor);

// draw circle
g.drawArc(_circleCenterX - _raduis, _circleCenterY - _raduis, _raduis * 2, _raduis * 2, 0, 360);

// set text's font
g.setFont(Font);
int textH = Font.getHeight();

// draw date (if allowed)
if (ShowDate == true)
{
String strDate = getDateString(_now, "-");
int strDateWidth = Font.stringWidth(strDate);
g.drawRect(_circleCenterX - strDateWidth / 2, _circleCenterY, strDateWidth, textH);
g.drawString(strDate, _circleCenterX, _circleCenterY, Graphics.TOP | Graphics.HCENTER);
}

// draw ticks & digits
int textW;
for (int hour = 1; hour <= 12; hour++)
{
double angle = hour * 60.0 / 12.0;
g.drawLine(
pointX(angle, _raduis * (1 - LineLengthTicks), _circleCenterX),
pointY(angle, _raduis * (1 - LineLengthTicks), _circleCenterY),
pointX(angle, _raduis, _circleCenterX),
pointY(angle, _raduis, _circleCenterY));

// texts
textW = Font.stringWidth("" + hour);
g.drawString("" + hour,
(int) pointX(angle, _raduis * TextPositionRelativeR, _circleCenterX) - textW / 2,
(int) pointY(angle, _raduis * TextPositionRelativeR, _circleCenterY) - textH / 2,
0);
}

double hour = _now.get(Calendar.HOUR) * 60.0 / 12.0;
double minute = _now.get(Calendar.MINUTE);
double second = _now.get(Calendar.SECOND);

// draw hour line
g.drawLine(_circleCenterX, _circleCenterY,
pointX(hour + (double) minute / 12.0, _raduis * LineLengthHour, _circleCenterX),
pointY(hour + (double) minute / 12.0, _raduis * LineLengthHour, _circleCenterY));

// draw minutes line
g.drawLine(_circleCenterX, _circleCenterY,
pointX(minute + second / 60.0, _raduis * LineLengthMinutes, _circleCenterX),
pointY(minute + second / 60.0, _raduis * LineLengthMinutes, _circleCenterY));

// draw seconds line
g.drawLine(_circleCenterX, _circleCenterY,
pointX((double) second, _raduis * LineLengthSeconds, _circleCenterX),
pointY((double) second, _raduis * LineLengthSeconds, _circleCenterY));
}

public synchronized void startTicking()
{
if (_thread == null)
{
_thread = new Thread(this);

_threadIsRunning = true;
_thread.start();
}
}

public synchronized void stopTicking()
{
if (_thread != null)
{
_threadIsRunning = false;
try
{
_thread.join();
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}

public void run()
{
while (_threadIsRunning == true)
{
this.updateTime();

try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}

private String getDateString(Calendar p_calendar, String p_delimiter)
{
int day = p_calendar.get(Calendar.DAY_OF_MONTH);
int month = p_calendar.get(Calendar.MONTH) + 1;
int year = p_calendar.get(Calendar.YEAR);

String strDay = (day < 10) ? "0" + day : String.valueOf(day);
String strMonth = (month < 10) ? "0" + month : String.valueOf(month);
String strYear = String.valueOf(year);

StringBuffer sb = new StringBuffer();
sb.append(strDay);
sb.append(p_delimiter);
sb.append(strMonth);
sb.append(p_delimiter);
sb.append(strYear);

return sb.toString();
}
}


Usage sample:

package Test;

import CustomItems.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class StartMidlet extends MIDlet implements CommandListener
{
public void startApp()
{
Form f = new Form("My Clock Test");
int w = f.getWidth();
int h = f.getHeight();

AnalogClock cl = new AnalogClock(null, (int) (w * 0.8));
cl.setLayout(Item.LAYOUT_2 | Item.LAYOUT_CENTER);
cl.startTicking();
f.append(cl);

Command cmd = new Command("Back", Command.BACK, 0);
f.addCommand(cmd);

cmd = new Command("Next", Command.OK, 1);
f.addCommand(cmd);

f.setCommandListener(this);

Display.getDisplay(this).setCurrent(f);
}

public void pauseApp()
{ }

public void destroyApp(boolean unconditional)
{ }

public void commandAction(Command arg0, Displayable arg1)
{ }
}




The contorl have 2 methods for managing clock timer.
startTicking - for start ticking the timer (this calls repaint...)
stopTicking- for stop the timer



Use it smartly...

6 comments:

  1. This doesn't work!!!!!

    ReplyDelete
  2. well I get 1 error that says that CustomItems does not exist, and to remove it, yet I run it and it comes up with the one error saying it doesn't exist and to import CustomItems.*;

    I'm confused :s

    ReplyDelete
  3. also can I check that I am putting the code in the right classes

    the StartMidlet is a Midlet
    and the AnalogClass is a java class

    sorry if this seems like a really stupid question just I'm pretty new to all this and I don't really know what I'm doing

    ReplyDelete
  4. Sry, i wanna ask.
    is the first code(analogClock) and the second code (StartMidelt) on a different projects? or in the same project?

    ReplyDelete
  5. how do you change the height of the customitem. i cant seem to change it

    ReplyDelete