I am displaying a customized list field with text on the right side and image on the left side.The image comes from a URL dynamically. Initially i am placing a blank image on the left of the list field,then call URLBitmapField class's setURL method,which actually does the processing and places the processed image on top of the blank image.The image gets displayed on the list field,but to see that processed image i need to click on the list field image.I want the processed image to be displayed automatically in the list field after the processing.Can anyone tell me where i am getting wrong?I have been asking for help,but no one seems to figure out the problem.Any productive suggestions would be appreciated
import java.util.Vector;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.NullField;
import net.rim.device.api.ui.container.FullScreen;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.ui.component.ListField;
public class TaskListField extends UiApplication {
// statics
// ------------------------------------------------------------------
public static void main(String[] args) {
TaskListField theApp = new TaskListField();
theApp.enterEventDispatcher();
}
public TaskListField() {
pushScreen(new TaskList());
}
}
class TaskList extends MainScreen implements ListFieldCallback {
private Vector rows;
private Bitmap p1;
private Bitmap p2;
private Bitmap p3;
String Task;
ListField listnew = new ListField();
private VerticalFieldManager metadataVFM;
TableRowManager row;
public TaskList() {
super();
URLBitmapField artistImgField;
listnew.setRowHeight(80);
listnew.setCallback(this);
rows = new Vector();
for (int x = 0; x <3; x++) {
row = new TableRowManager();
artistImgField = new URLBitmapField(Bitmap
.getBitmapResource("res/images/bg.jpg"));
row.add(artistImgField);
String photoURL = "someimagefrmurl.jpg";
Log.info(photoURL);
// strip white spaces in the url, which is causing the
// images to not display properly
for (int i = 0; i < photoURL.length(); i++) {
if (photoURL.charAt(i) == ' ') {
photoURL = photoURL.substring(0, i) + "%20"
+ photoURL.substring(i + 1, photoURL.length());
}
}
Log.info("Processed URL: " + photoURL);
artistImgField.setURL(photoURL);
LabelField task = new LabelField("Display");
row.add(task);
LabelField task1 = new LabelField(
"Now Playing" + String.valueOf(x));
Font myFont = Font.getDefault().derive(Font.PLAIN, 12);
task1.setFont(myFont);
row.add(task1);
rows.addElement(row);
}
listnew.setSize(rows.size());
this.add(listnew);
//listnew.invalidate();
}
// ListFieldCallback Implementation
public void drawListRow(ListField listField, Graphics g, int index, int y,
int width) {
TableRowManager rowManager = (TableRowManager) rows.elementAt(index);
rowManager.drawRow(g, 0, y, width, listnew.getRowHeight());
}
protected void drawFocus(Graphics graphics, boolean on) {
}
private class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
// Causes the fields within this row manager to be layed out then
// painted.
public void drawRow(Graphics g, int x, int y, int width, int height) {
// Arrange the cell fields within this row manager.
layout(width, height);
// Place this row manager within its enclosing list.
setPosition(x, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
}
// Arrages this manager's controlled fields from left to right within
// the enclosing table's columns.
protected void sublayout(int width, int height) {
// set the size and position of each field.
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
// start with the Bitmap Field of the priority icon
Field field = getField(0);
layoutChild(field, 146,80);
setPositionChild(field, 0, 0);
// set the task name label field
field = getField(1);
layoutChild(field, preferredWidth - 16, fontHeight + 1);
setPositionChild(field, 149, 3);
// set the list name label field
field = getField(2);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field, 149, fontHeight + 6);
setExtent(360, 480);
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth() {
return listnew.getWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight() {
return listnew.getRowHeight();
}
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
}
Finally i solved it of my own. This worked:
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
listnew.invalidate();
}
},500,true);
Related
I am using Handler post delay to call onDraw each time I want to draw new rectangle, but for every new rectangle erase the previous one ..
How can I make the canvas keep the content of all rectangles:
My code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.CountDownTimer;
import android.os.Handler;
import android.util.Log;
import com.adhamenaya.microchart.model.ChartData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
/**
* Created by Admin on 18/12/2016.
*/
public class ColumnChart extends Chart implements Runnable {
private int mSpace = 0;
private int mColumnSize = 0;
private int mColumnsCount = 0;
private int mCurrentStart = 0;
private float mHeightUnit = 0;
private int mHeightDiff;
int columnIndex = 0;
private Handler mHandler;
private Canvas mCanvas;
private Iterator mDataIterator;
static final long FRAME_TIME = 100;
private ArrayList<Rect> rectangles = new ArrayList<Rect>();
public ColumnChart(Context context) {
super(context);
mHandler = new Handler();
}
#Override
protected void prepare() {
if (mChartData != null && mChartData.getSingleData().size() > 0) {
mColumnsCount = mChartData.getSingleData().size();
// Column size, 1 is added to reserve a space at the end of the chart
mColumnSize = (int) ((mWidth / (mColumnsCount)) * 0.9);
// Calculate the space between the bars
mSpace = (mWidth / mColumnsCount) - mColumnSize;
// Calculate height unit
// Calculate 80% of the total height
float height08 = mHeight * 0.8f;
mHeightUnit = height08 / mChartData.getMax();
// Draw bars
mDataIterator = mChartData.getSingleData().entrySet().iterator();
mMainPaint = getRectPaint();
// Create rect objects
while (mDataIterator.hasNext()) {
Map.Entry entry = (Map.Entry) mDataIterator.next();
int columnHeight = (int) ((int) entry.getValue() * mHeightUnit);
String key = (String) entry.getKey();
// Shift the
mCurrentStart += mSpace;
// Calculate the difference between the total height and the height of the column
mHeightDiff = mHeight - columnHeight;
mCurrentStart += mColumnSize;
mDataIterator.remove();
Rect rect = new Rect(mCurrentStart, mHeightDiff,
mCurrentStart + mColumnSize, mHeight);
rectangles.add(rect);
}
}
}
#Override
protected void paintChart(Canvas canvas) {
}
#Override
public void setData(ChartData data) {
this.mChartData = data;
prepare();
mHandler.post(this);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Get measured height and width of the view
setMeasuredDimension(getMeasurement(widthMeasureSpec, mWidth),
getMeasurement(heightMeasureSpec, mHeight));
// mWidth = MeasureSpec.getSize(widthMeasureSpec);
// mHeight = MeasureSpec.getSize(heightMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(columnIndex > 0 && columnIndex<rectangles.size())
canvas.drawRect(rectangles.get(columnIndex), getRectPaint());
}
#Override
public void run() {
if(columnIndex<rectangles.size()){
invalidate();
columnIndex++;
mHandler.postDelayed(this,FRAME_TIME);
}else{
mHandler.removeCallbacks(this);
}
}
}
Create a FrameLayout on which you want to draw rectangles. Create a view every time you are drawing a new circle. Draw circle on newly created view and the add that view to FrameLayout. Background of the view will be transparent by default. If not then set the background as transparent. This way your previous rectangles will be visible and new rectangle will be drawn on existing rectangles.
Your are near to make it done! Just call you prepare after calling invalidate method.
#Override
public void run() {
if(columnIndex<rectangles.size()){
invalidate();
columnIndex++;
mHandler.postDelayed(this,FRAME_TIME);
}else{
mHandler.removeCallbacks(this);
eraseAll();
}
}
...
public void eraseAll() {
this.canvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
prepare();
}
For me this logic is working fine
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(columnIndex < rectangles.size()) {
for (int i = 0; i <= columnIndex; ++i) {
canvas.drawRect(rectangles.get(i), paint);
}
}
}
Simplest heck is to keep the canvas object as class level variable and always draw on this canvas object and in super.onDraw() pass on this canvas, it will always keep your previous rectangles drawn
Okay, so my friend and I are making are a game that requires some pixel analysis for the rectangles, and I wrote the code to analyze the rectangles, and It works swimmingly, However, when I try to draw the bufferedImage it doesn't show up. The main issue is that my java class has never taught us how to use Jframes, and I don't want to change my code to accommodate:
// Threaded Applet Template that works with Macs
// Import section
// Use this section to add additional libaries for use in your program.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.image.BufferedImage;
import java.awt.Toolkit;
import javax.imageio.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.*;
// This begins the class definition.
// Notice that this is a "world". You can tell since it extends Applet.
// It also implement Runnable which allows it to be and use threads.
public class PixelAnalyzetest extends Applet implements Runnable
{
//variable declaration section
// public datatype variablename
public int xTitle;
public int yTitle;
public Analyzer analyzer;
public BufferedImage test;
public Image itest;
public boolean analyzeonce=true;
//declare your Hero object here
//Sets up a Thread called thread
Thread thread;
// Method definition section
// init() is the first method an Applet runs when started
public void init()
{
//Initialize variables
xTitle=10;
yTitle=10;
BufferedImage test = new BufferedImage(1200,1200, BufferedImage.TYPE_INT_ARGB);
//test = getImage(getDocumentBase(),"test.png");
System.out.println("the width of the image is: "+test.getWidth(this));
try{
test = ImageIO.read(new File("test.png"));
} catch(IOException e) {};
//itest=test.getAsBufferedImage();
analyzer = new Analyzer(test, 5);
//construct objects
//construct your hero here!
//Set up the thread
//These should be the LAST lines in your init( ) method.
thread = new Thread(this); //constructs a new thread
thread.start(); //starts the thread
}//init()
// paint() is used to display things on the screen
public void paint(Graphics g)
{
setSize(1200,1200);
//Put the title on the screen.
/*for(int x=0;x<test.getWidth();x++)
{
for(int y=0;y<test.getHeight();y++)
{
BufferedImage.setRGB(x,y,analyzer.pictureRGB[x][y]);
}
}*/
g.drawImage(test,0,0,1200,1200,this);
//draw your hero's name here using g.drawString( )
}// paint()
// every thread needs a run method
// this is what the thread will do
public void run() {
// this thread loop forever and runs the paint method and then sleeps.
while(true)
{
//put what you want your program to do here.
//move your hero here by calling its move() method.
if(analyzeonce==true)
{
analyzer.analyzelines();
analyzeonce=false;
}
repaint(); // run the paint method.
//sleep
try {
thread.sleep(100);
}
catch (Exception e){ }
}//while
}// run()
}
Now my analyzer class:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.image.BufferedImage;
import java.awt.Toolkit;
public class Analyzer
{
public int[][] pictureRGB;
//VARIABLE DECLARATION SECTION
//Here's where you state which variables you are going to use.
public String name; //use this format public datatype variablename;
public boolean isAlive;
public int health;
public int strength;
public String theGlove;
public int dx, dy;
public BufferedImage analyzing, bgrab;
public int imagewidth, imageheight;
public int linecounter = 0;
public int boxcounter = 0;
public boolean endline = false;
public Line lines[];
public Box boxes[];
public int totalboxes;
public boolean donean = false;
// METHOD DEFINITION SECTION
// Constructor Definition
// A constructor "builds" the object when called and give the variable initial values.
// This constructor build Heroes with all the same initial values.
public Analyzer(BufferedImage grab, int xtotalboxes)
{
//BufferedImage bgrab = (BufferedImage) grab;
//bgrab = new BufferedImage(1200,1200, BufferedImage.TYPE_INT_ARGB);
//bgrab.getGraphics().drawImage(grab,0,0,bgrab.getWidth(),bgrab.getHeight(),null);
analyzing = grab;
totalboxes = xtotalboxes;
imagewidth=analyzing.getWidth();
System.out.println(imagewidth+" Is the image's Width");
imageheight=analyzing.getHeight();
System.out.println(imagewidth+" Is the image's Height");
pictureRGB= new int[imagewidth] [imageheight];
lines = new Line[10];
boxes = new Box[20];
isAlive = true;
health = 200;
strength = 20;
for(int xpos = 1; xpos<imagewidth-1;xpos++)
{
for(int ypos = 1; ypos<imageheight-1; ypos++)
{
pictureRGB[xpos][ypos]=analyzing.getRGB(xpos,ypos);
//System.out.println(pictureRGB[xpos][ypos]);
}
}
}
public void analyzelines()
{
for(boxcounter=0; boxcounter<boxes.length; boxcounter++)
{
int tempx = 0;
int tempy = 0;
int tempw = 0;
int temph = 0;
//int pxpos = 0;
//int pypos = 0;
boolean startline=false;
boolean foundw = false;
boolean foundh = false;
if(donean==false)
{
for(int ypos = 1; ypos<imageheight-1; ypos++)
{
for(int xpos = 1; xpos<imagewidth-1;xpos++)
{
if(boxcounter>0)
{
if(pictureRGB[xpos][ypos]==-3584 && startline==false && boxes[boxcounter-1].rect.contains(new Point(xpos,ypos))==false && boxes[boxcounter-1].rect.intersects(new Rectangle(xpos-2,ypos-2,4,4))==false && isEqual(new Rectangle(xpos-2,ypos-2,4,4))==false)
{
System.out.println("--------------------------------START BOX --------------");
System.out.println("The top left corner of the box is: ("+xpos+","+ypos+")");
startline=true;
tempx=xpos;
tempy=ypos;
//System.out.println(tempx+"<<TEMPX TEMPY>>"+tempy);
}
if(startline==true && pictureRGB[xpos+1][ypos]!=pictureRGB[xpos][ypos] && foundw==false && foundh==false && boxes[boxcounter-1].rect.contains(new Point(xpos,ypos))==false && isEqual(new Rectangle(xpos-2,ypos-2,4,4))==false)
{
tempw=xpos-tempx;
System.out.println("XPOS EQ = "+xpos+" - "+tempx+" = "+ tempw);
foundw = true;
//System.out.println(tempw+"<<TEMPw TEMPx>>"+tempx+"<<<<XPOS>>>>>>>>>>>>>"+xpos);
}
if(startline==true && pictureRGB[xpos][ypos+1]!=pictureRGB[xpos][ypos] && foundh==false && foundw==true && boxes[boxcounter-1].rect.contains(new Point(xpos,ypos))==false && pictureRGB[xpos-1][ypos]==pictureRGB[xpos][ypos] && pictureRGB[xpos+1][ypos]!=pictureRGB[xpos][ypos] && isEqual(new Rectangle(xpos-2,ypos-2,4,4))==false)
{
temph=ypos-tempy;
System.out.println("YPOS EQ = "+ypos+" - "+tempy+" = "+ temph);
foundh=true;
System.out.println("The Width is: "+tempw+" The height is: "+temph+" boxcounter="+boxcounter);
boxes[boxcounter]= new Box(tempx, tempy, tempw, temph);
System.out.println("--------------------------------NEXT BOX ---------------");
//System.out.println("BOX WIDTH"+boxes[boxcounter].width + "BOX COUNTER=="+boxcounter);
}
}
if(boxcounter==0)
{
if(pictureRGB[xpos][ypos]==-3584 && startline==false)
{
System.out.println("The top left corner of the box is: ("+xpos+","+ypos+")");
startline=true;
tempx=xpos;
tempy=ypos;
}
if(startline==true && pictureRGB[xpos+1][ypos]!=pictureRGB[xpos][ypos] && foundw==false && foundh==false)
{
tempw=xpos-tempx;
foundw = true;
}
if(startline==true && pictureRGB[xpos][ypos+1]!=pictureRGB[xpos][ypos] && foundh==false && foundw==true)
{
temph=ypos-tempy;
foundh=true;
System.out.println("The Width is: "+tempw+" The height is: "+temph+" boxcounter="+boxcounter);
boxes[boxcounter]= new Box(tempx, tempy, tempw, temph);
//System.out.println("BOX WIDTH"+boxes[boxcounter].width);
}
}
}
}
if(boxcounter>=(totalboxes))
{
donean=true;
}
}
//System.out.println("The black lines width is: "+(lines[linecounter].endx-lines[linecounter].startx));
}
}
public boolean isEqual(Rectangle c1)
{
boolean returned = false;
for(int i = 0; i<boxcounter; i++)
{
if(c1.intersects(boxes[i].rect) || boxes[i].rect.contains(new Point(c1.x, c1.y)))
{
returned=true;
}
}
return(returned);
}
/*
public static BufferedImage toBufferedImage(Image img)
{
if (img instanceof BufferedImage)
{
return (BufferedImage) img;
}
// Create a buffered image with transparency
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
}
*/
public void move()
{
}
//Other methods
//You can define what this type of object can do here.
}
my line and box classes are very straight forward just some classes i made with xposes and yposes, width's and heights
I'm trying for more than 2 days to implement a specific requirement for a text editor window... unfortunately without success so far :(
The goal is to get a text editor window which will highlight the current row, like other text editors do. With current row I mean the row where currently the cursor/caret is positioned.
I already found two different approaches but unfortunately I'm not able to adopt them so they work as expected.
The first approach is to overwrite the DefaultHighlighter (http://snippets.dzone.com/posts/show/6688).
In the second approach the HighlighterPainter will be overwritten instead (http://www.jroller.com/santhosh/date/20050622).
Right now I'm trying to adopt the first approach in my project but as I said it is not working as desired.
At the end of this post I'm posting a small sample application which demonstrates the problem.
If I start the program, the caret is placed at the beginning of the first line. However, the line is not highlighted.
Now I type in some characters. Those chars will be highlighted but only those chars not the complete line
I hit enter to move to the next line. The first line is not highlighted anymore what is correct. The second line isn't highlighted as well, what is not correct. Again, when I type in some chars, those will be higlighted but not the complete row.
When I now move back the caret to the first line, either by cursor up key or mouse clicking, the complete first line will be highlighted, not only the existing chars. This is the behavior I want right from the start.
I hope anybody can tell me what I'm doing wrong here... or explain why it is not possible to resolve that issue at all. Any alternative solutions how I could realize the line highlighting are also highly appreciated!
Thanks a lot in advance
Cheers
Preachie
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
public class HighlightProblem extends JFrame {
private static final long serialVersionUID = 1L;
private final JTextPane textPane;
private final Highlighter.HighlightPainter cyanPainter;
public HighlightProblem() {
cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);
textPane = new JTextPane();
textPane.setPreferredSize(new Dimension(500, 300));
textPane.setHighlighter(new LineHighlighter());
textPane.addCaretListener(new CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
setHighlight(e);
}
});
getContentPane().add(textPane);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
new HighlightProblem();
}
public void setHighlight(CaretEvent e) {
textPane.getHighlighter().removeAllHighlights();
int currentLine = getLineFromOffset(textPane, e.getDot());
int startPos = getLineStartOffsetForLine(textPane, currentLine);
int endOffset = getLineEndOffsetForLine(textPane, currentLine);
try {
textPane.getHighlighter().addHighlight(startPos, endOffset, cyanPainter);
} catch (Exception ex) {
ex.printStackTrace();
}
textPane.repaint();
}
public int getLineFromOffset(JTextComponent component, int offset) {
return component.getDocument().getDefaultRootElement().getElementIndex(offset);
}
public int getLineStartOffsetForLine(JTextComponent component, int line) {
return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset();
}
public int getLineEndOffsetForLine(JTextComponent component, int line) {
return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset();
}
public class LineHighlighter extends DefaultHighlighter {
private JTextComponent component;
#Override
public final void install(final JTextComponent c) {
super.install(c);
this.component = c;
}
#Override
public final void deinstall(final JTextComponent c) {
super.deinstall(c);
this.component = null;
}
#Override
public final void paint(final Graphics g) {
final Highlighter.Highlight[] highlights = getHighlights();
final int len = highlights.length;
for (int i = 0; i < len; i++) {
Highlighter.Highlight info = highlights[i];
if (info.getClass().getName().indexOf("LayeredHighlightInfo") > -1) {
// Avoid allocing unless we need it.
final Rectangle a = this.component.getBounds();
final Insets insets = this.component.getInsets();
a.x = insets.left;
a.y = insets.top;
// a.width -= insets.left + insets.right + 100;
a.height -= insets.top + insets.bottom;
final Highlighter.HighlightPainter p = info.getPainter();
p.paint(g, info.getStartOffset(), info.getEndOffset(), a, this.component);
}
}
}
#Override
public void removeAllHighlights() {
textPane.repaint(0, 0, textPane.getWidth(), textPane.getHeight());
super.removeAllHighlights();
}
}
}
http://tips4java.wordpress.com/2008/10/29/line-painter/
I think this is what you are looking for. I took that LinePainter class and copied your constructor over into a main method, took out your highlighter parts and added a new LinePainter(textPane); Works like a charm
Below is the code to extract text from current line.
You can use same logic to get required indexes and highlight text
private String getCurrentEditLine() {
int readBackChars = 100;
int caretPosition = scriptEditor.getCaretPosition();
if (caretPosition == 0) {
return null;
}
StyledDocument doc = scriptEditor.getStyledDocument();
int offset = caretPosition <= readBackChars ? 0 : caretPosition
- readBackChars;
String text = null;
try {
text = doc.getText(offset, caretPosition);
} catch (BadLocationException e) {
}
if (text != null) {
int idx = text.lastIndexOf("\n");
if(idx != -1) {
return text.substring(idx);
}else {
return text;
}
}
return null;
}
I think this might be difficult to achieve using highlighters - I don't think it is what they were designed for. You may need to do it with custom painting code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
public class HighlightLineTest {
private static class HighlightLineTextPane extends JTextPane {
public HighlightLineTextPane() {
// Has to be marked as transparent so the background is not replaced by
// super.paintComponent(g);
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
try {
Rectangle rect = modelToView(getCaretPosition());
if (rect != null) {
g.setColor(Color.CYAN);
g.fillRect(0, rect.y, getWidth(), rect.height);
}
} catch (BadLocationException e) {
}
super.paintComponent(g);
}
#Override
public void repaint(long tm, int x, int y, int width, int height) {
// This forces repaints to repaint the entire TextPane.
super.repaint(tm, 0, 0, getWidth(), getHeight());
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Highlight test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new HighlightLineTextPane());
frame.setBounds(100, 100, 300, 400);
frame.setVisible(true);
}
}
I want three list field items to be displayed, from bottom to top. I am able to display three list field items, but they display from top to bottom. I have tried setting the position, but it isn't working.
import java.util.Vector;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.NullField;
import net.rim.device.api.ui.container.FullScreen;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.ui.component.ListField;
/**
* #author Jason Emerick
*/
public class TaskListField extends UiApplication
{
//statics ------------------------------------------------------------------
public static void main(String[] args)
{
TaskListField theApp = new TaskListField();
theApp.enterEventDispatcher();
}
public TaskListField()
{
pushScreen(new TaskList());
}
}
/*class List extends FullScreen {
TaskList tl;
List(){
super();
TaskList tl=new TaskList();
}
}*/
class TaskList extends MainScreen implements ListFieldCallback {
private Vector rows;
private Bitmap p1;
private Bitmap p2;
private Bitmap p3;
String Task;
ListField listnew=new ListField();
public TaskList() {
super();
listnew.setRowHeight(50);
//setEmptyString("Hooray, no tasks here!", DrawStyle.HCENTER);
listnew.setCallback(this);
p1 = Bitmap.getBitmapResource("1.png");
p2 = Bitmap.getBitmapResource("2.png");
p3 = Bitmap.getBitmapResource("3.png");
rows = new Vector();
for (int x = 0; x < 3; x++) {
TableRowManager row = new TableRowManager();
if (x== 0) {
Task="On Air Now";
}
if (x== 1) {
Task="Music Channel";
}
if (x==2) {
Task="News Channel";
}
// SET THE PRIORITY BITMAP FIELD
// if high priority, display p1 bitmap
if (x % 2 == 0) {
row.add(new BitmapField(p1));
}
// if priority is 2, set p2 bitmap
else if (x % 3 == 0) {
row.add(new BitmapField(p2));
}
// if priority is 3, set p3 bitmap
else {
row.add(new BitmapField(p3));
}
// SET THE TASK NAME LABELFIELD
// if overdue, bold/underline
LabelField task = new LabelField(Task,
DrawStyle.ELLIPSIS);
// if due today, bold
if (x % 2 == 0) {
task.setFont(Font.getDefault().derive(
Font.BOLD));
} else {
task.setFont(Font.getDefault().derive(Font.BOLD));
}
row.add(task);
LabelField task1 = new LabelField("Now Playing" + String.valueOf(x),
DrawStyle.ELLIPSIS);
// if due today, bold
/* if (x % 2 == 0) {
task.setFont(Font.getDefault().derive(
Font.BOLD));
} else {
task.setFont(Font.getDefault().derive(Font.BOLD));
}*/
Font myFont = Font.getDefault().derive(Font.PLAIN, 12);
task1.setFont(myFont);
row.add(task1);
// SET THE DUE DATE/TIME
row.add(new LabelField("",
DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
| DrawStyle.RIGHT) {
protected void paint(Graphics graphics) {
graphics.setColor(0x00878787);
super.paint(graphics);
}
});
rows.addElement(row);
}
listnew.setSize(rows.size());
this.add(listnew);
}
// ListFieldCallback Implementation
public void drawListRow(ListField listField, Graphics g, int index, int y,
int width) {
//TaskList list =(TaskListField) listnew;
TableRowManager rowManager = (TableRowManager)rows
.elementAt(index);
rowManager.drawRow(g, 0, y, width, listnew.getRowHeight());
}
private class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
// Causes the fields within this row manager to be layed out then
// painted.
public void drawRow(Graphics g, int x, int y, int width, int height) {
// Arrange the cell fields within this row manager.
layout(0, 1);
// Place this row manager within its enclosing list.
setPosition(x,y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
}
// Arrages this manager's controlled fields from left to right within
// the enclosing table's columns.
protected void sublayout(int width, int height) {
// set the size and position of each field.
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
// start with the Bitmap Field of the priority icon
/* Field field = getField(0);
layoutChild(field, 0, 0);
setPositionChild(field, 150, 300);*/
// set the task name label field
/* field = getField(1);
layoutChild(field, preferredWidth - 16, fontHeight + 1);
setPositionChild(field, 34, 3);
// set the list name label field
field = getField(2);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field, 34, fontHeight + 6);*/
// set the due time name label field
/* field = getField(3);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field,4,340);*/
/* layoutChild(listnew, preferredWidth, fontHeight);
setPositionChild(listnew, 3, 396);*/
setExtent(360, 480);
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth() {
return getWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight() {
return listnew.getRowHeight();
}
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
// TODO Auto-generated method stub
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
}
What do I need to fix to make it work as I want?
My guess is you want to know how to change the focus to item 3 in your listfield
So the answer is:
listnew.setSelectedIndex(2);
I have a JComboBox and would like to have a separator in the list of elements. How do I do this in Java?
A sample scenario where this would come in handy is when making a combobox for font-family-selection; similar to the font-family-selection-control in Word and Excel. In this case I would like to show the most-used-fonts at the top, then a separator and finally all font-families below the separator in alphabetical order.
Can anyone help me with how to do this or is this not possible in Java?
There is a pretty short tutorial with an example that shows how to use a custom ListCellRenderer on java2s
http://www.java2s.com/Code/Java/Swing-Components/BlockComboBoxExample.htm
Basically it involves inserting a known placeholder in your list model and when you detect the placeholder in the ListCellRenderer you return an instance of 'new JSeparator(JSeparator.HORIZONTAL)'
By the time I wrote and tested the code below, you probably got lot of better answers...
I don't mind as I enjoyed the experiment/learning (still a bit green on the Swing front).
[EDIT] Three years later, I am a bit less green, and I took in account the valid remarks of bobndrew. I have no problem with the key navigation that just works (perhaps it was a JVM version issue?). I improved the renderer to show highlight, though. And I use a better demo code. The accepted answer is probably better (more standard), mine is probably more flexible if you want a custom separator...
The base idea is to use a renderer for the items of the combo box. For most items, it is a simple JLabel with the text of the item. For the last recent/most used item, I decorate the JLabel with a custom border drawing a line on its bottom.
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class TwoPartsComboBox extends JComboBox
{
private int m_lastFirstPartIndex;
public TwoPartsComboBox(String[] itemsFirstPart, String[] itemsSecondPart)
{
super(itemsFirstPart);
m_lastFirstPartIndex = itemsFirstPart.length - 1;
for (int i = 0; i < itemsSecondPart.length; i++)
{
insertItemAt(itemsSecondPart[i], i);
}
setRenderer(new JLRenderer());
}
protected class JLRenderer extends JLabel implements ListCellRenderer
{
private JLabel m_lastFirstPart;
public JLRenderer()
{
m_lastFirstPart = new JLabel();
m_lastFirstPart.setBorder(new BottomLineBorder());
// m_lastFirstPart.setBorder(new BottomLineBorder(10, Color.BLUE));
}
#Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
if (value == null)
{
value = "Select an option";
}
JLabel label = this;
if (index == m_lastFirstPartIndex)
{
label = m_lastFirstPart;
}
label.setText(value.toString());
label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
label.setOpaque(true);
return label;
}
}
}
Separator class, can be thick, with custom color, etc.
import java.awt.*;
import javax.swing.border.AbstractBorder;
/**
* Draws a line at the bottom only.
* Useful for making a separator in combo box, for example.
*/
#SuppressWarnings("serial")
class BottomLineBorder extends AbstractBorder
{
private int m_thickness;
private Color m_color;
BottomLineBorder()
{
this(1, Color.BLACK);
}
BottomLineBorder(Color color)
{
this(1, color);
}
BottomLineBorder(int thickness, Color color)
{
m_thickness = thickness;
m_color = color;
}
#Override
public void paintBorder(Component c, Graphics g,
int x, int y, int width, int height)
{
Graphics copy = g.create();
if (copy != null)
{
try
{
copy.translate(x, y);
copy.setColor(m_color);
copy.fillRect(0, height - m_thickness, width - 1, height - 1);
}
finally
{
copy.dispose();
}
}
}
#Override
public boolean isBorderOpaque()
{
return true;
}
#Override
public Insets getBorderInsets(Component c)
{
return new Insets(0, 0, m_thickness, 0);
}
#Override
public Insets getBorderInsets(Component c, Insets i)
{
i.left = i.top = i.right = 0;
i.bottom = m_thickness;
return i;
}
}
Test class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class TwoPartsComboBoxDemo extends JFrame
{
private TwoPartsComboBox m_combo;
public TwoPartsComboBoxDemo()
{
Container cont = getContentPane();
cont.setLayout(new FlowLayout());
cont.add(new JLabel("Data: ")) ;
String[] itemsRecent = new String[] { "ichi", "ni", "san" };
String[] itemsOther = new String[] { "one", "two", "three" };
m_combo = new TwoPartsComboBox(itemsRecent, itemsOther);
m_combo.setSelectedIndex(-1);
cont.add(m_combo);
m_combo.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
String si = (String) m_combo.getSelectedItem();
System.out.println(si == null ? "No item selected" : si.toString());
}
});
// Reference, to check we have similar behavior to standard combo
JComboBox combo = new JComboBox(itemsRecent);
cont.add(combo);
}
/**
* Start the demo.
*
* #param args the command line arguments
*/
public static void main(String[] args)
{
// turn bold fonts off in metal
UIManager.put("swing.boldMetal", Boolean.FALSE);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame demoFrame = new TwoPartsComboBoxDemo();
demoFrame.setTitle("Test GUI");
demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demoFrame.setSize(400, 100);
demoFrame.setVisible(true);
}
});
}
}
You can use a custom ListCellRenderer which would draw the separator items differently. See docs and a small tutorial.
Try adding this renderer. Just supply a list of index values that you want the separator to be above.
private class SeperatorComboRenderer extends DefaultListCellRenderer
{
private final float SEPARATOR_THICKNESS = 1.0f;
private final float SPACE_TOP = 2.0f;
private final float SPACE_BOTTOM = 2.0f;
private final Color SEPARATOR_COLOR = Color.DARK_GRAY;
private final List<Integer> marks;
private boolean mark;
private boolean top;
public SeperatorComboRenderer(List<Integer> marks)
{
this.marks = marks;
}
#Override
public Component getListCellRendererComponent(JList list, Object object, int index, boolean isSelected, boolean hasFocus)
{
super.getListCellRendererComponent(list, object, index, isSelected, hasFocus);
top = false;
mark = false;
marks.forEach((idx) ->
{
if(index - 1 == idx)
top = true;
if(index == idx)
mark = true;
});
return this;
}
#Override
protected void paintComponent(Graphics g)
{
if(mark)
g.translate(0, (int)(SEPARATOR_THICKNESS + SPACE_BOTTOM));
Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g);
if(mark)
{
g2.setColor(SEPARATOR_COLOR);
g2.setStroke(new BasicStroke(SEPARATOR_THICKNESS));
g2.drawLine(0, 0, getWidth(), 0);
}
}
#Override
public Dimension getPreferredSize()
{
Dimension pf = super.getPreferredSize();
double height = pf.getHeight();
if(top) height += SPACE_TOP;
else if(mark) height += SEPARATOR_THICKNESS + SPACE_BOTTOM;
return new Dimension((int)pf.getWidth(), (int)height);
}
}