Skip to main content

Autocomplete Textfield.

13 replies [Last post]
rosstheboss
Offline
Joined: 2009-02-03

Hello.

I'm working on creating a auto completing text field, a bit like the example I once saw on the blog. I'd like to have a suggestions list (scrollable) appear underneath the text field appearing to be part of the text field, and overlaying any other components on the field. An example of how this best works is the search within firefox.

Any suggestions on an approach to this would be great, I'm going to handle data using a model and filterproxy.

Thanks

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rosstheboss
Offline
Joined: 2009-02-03

Sorted!

Obviously I was setting preferred size, when in actual fact I needed to be setting actual size, as I'm not using a layout manager.

Thanks!

More likely questions to follow!

rosstheboss
Offline
Joined: 2009-02-03

Sorry to drag this up again, but I've still not had any luck painting a list onto a glasspane. I just can't seem to get anything to show when I'm calling any componenets PaintComponent method.

Thanks

Shai Almog

Did you call it within the paint method of the glass pane painter
and give it the graphics of the painter?
Is the code invoked?

> Sorry to drag this up again, but I've still not had any luck
> painting a list onto a glasspane. I just can't seem to get anything
> to show when I'm calling any componenets PaintComponent method.
>
> Thanks
> [Message sent by forum member 'rosstheboss' (rosstheboss)]
>
> http://forums.java.net/jive/thread.jspa?messageID=334613
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>

Shai Almog
http://lwuit.blogspot.com/
https://lwuit.dev.java.net/faq.html

[att1.html]

rosstheboss
Offline
Joined: 2009-02-03

Hi Shai,

Yes I'm calling a components PaintComponent method within the Painter's paint call. i.e.

public void paint(Graphics g, Rectangle rect) {
Label l = new Label("Test");
l.getStyle();
l.paintComponent(g);
}

Thanks Ross

Shai Almog

You need to set the size and position of the component manually for
this to work since there is no layout manager applicable to the
component. You can size the component based on its "preferred size"
and place it in the proper X/Y

> Hi Shai,
>
> Yes I'm calling a components PaintComponent method within the
> Painter's paint call. i.e.
>
> public void paint(Graphics g, Rectangle rect) {
> Label l = new Label("Test");
> l.getStyle();
> l.paintComponent(g);
> }
>
> Thanks Ross
> [Message sent by forum member 'rosstheboss' (rosstheboss)]
>
> http://forums.java.net/jive/thread.jspa?messageID=335745
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>

Shai Almog
http://lwuit.blogspot.com/
https://lwuit.dev.java.net/faq.html

[att1.html]

rosstheboss
Offline
Joined: 2009-02-03

Sorry I feel I must be missing something fundamental here, as I'm still not getting any closer.

I've set x and y to postive integers, and set pref size to a positive number too. I'm calling paintcomponent and nothing is visible.

Thanks for patience

Ross

rosstheboss
Offline
Joined: 2009-02-03

I've been attempting to do this for a while now, and I've come up with a problem that I can't solve. I'm trying to display a list of all autocomplete options, with 3 being displayed, and anymore being scrolled. However the scrolling doesn't work at all, instead the focus component just goes off the bottom of the list.

Any ideas why? Code for autocomplete posted below, it relies on being passed the form instance so it can set / remove glass pane.

import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Dialog;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Graphics;
import com.sun.lwuit.List;
import com.sun.lwuit.Painter;
import com.sun.lwuit.TextField;
import com.sun.lwuit.events.DataChangedListener;
import com.sun.lwuit.events.SelectionListener;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.geom.Rectangle;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.list.DefaultListCellRenderer;
import com.sun.lwuit.list.DefaultListModel;
import com.sun.lwuit.list.ListModel;
import java.util.Vector;

public class ACTextField extends TextField {

Form _parent;
autoCompletePane autoComplete;
boolean autoCompleteShown = false;
List l;
ListModel underlyingDataModel = new DefaultListModel(new String[]{"Accountants", "Advertising Agencies", "Air Conditioning", "Airlines", "Airport", "Architects", "Builder", "Baker", "Basketmaker", "Plumber", "Pizza Maker", "Piano Repair"});

public ACTextField(Form parent) {
_parent = parent;
}

public void keyPressed(int keyCode) {

super.keyPressed(keyCode);

if (!autoCompleteShown) {
if (isEditingTrigger(keyCode)) {
if (autoComplete == null) {
autoComplete = new autoCompletePane();
}
_parent.setGlassPane(autoComplete);
_parent.repaint();
l.setSelectedIndex(500);
autoCompleteShown = !autoCompleteShown;
}
} else if (autoCompleteShown) {
if (isEditingEndTrigger(keyCode)) {
_parent.setGlassPane(null);
autoCompleteShown = !autoCompleteShown;
}
}

int k = Display.getInstance().getGameAction(keyCode);

if (k == Display.GAME_DOWN) {
if (autoCompleteShown && l.getSelectedIndex() < l.size() - 1) {
l.setSelectedIndex(l.getSelectedIndex() + 1);
_parent.repaint();

}
}

if (k == Display.GAME_UP) {
if (autoCompleteShown && l.getSelectedIndex() > 0) {
l.setSelectedIndex(l.getSelectedIndex() - 1);
_parent.repaint();
}
} else {
}

}

protected boolean isEditingEndTrigger(int keyCode) {
int k = Display.getInstance().getGameAction(keyCode);

if (k == Display.GAME_DOWN) {
if (autoCompleteShown) {// && l.getSelectedIndex() < l.size() - 1) {
return false;
}
}

if (k == Display.GAME_UP) {
if (autoCompleteShown && l.getSelectedIndex() > 0) {
return false;
}
}

if (k == Display.GAME_FIRE) {
if (autoCompleteShown) {
String selected = (String) l.getSelectedItem();
if (selected != null) {
this.setText(selected);
setCursorPosition(getText().length());
}
}
}

if (isQwertyInput()) {
return keyCode < 0 && (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN);
}
return (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN);
}

public boolean handlesInput() {

if (autoCompleteShown) {
return true;
}

return super.handlesInput();
}

public class autoCompletePane implements Painter {

Container d;

public autoCompletePane() {
d = new Dialog();
d.setY(getY() + getHeight() + 2);
d.setX(10); //Why not getX()?
d.setScrollable(true);
d.setLayout(new BorderLayout());
d.setHeight(100);

//List
final FilterProxyListModel proxyModel = new FilterProxyListModel(underlyingDataModel);
l = new List(proxyModel){

public void paint(Graphics g) {
super.paint(g);
}
};
l.setOrientation(List.VERTICAL);
//Focus off the bottom of the list.
// l.setSelectedIndex(proxyModel.getSize() + 1, false);

addDataChangeListener(new DataChangedListener() {

public void dataChanged(int type, int index) {
proxyModel.filter(getText());
}
});

DefaultListCellRenderer dlcr = new DefaultListCellRenderer(false){
};
l.setListCellRenderer(dlcr);

if (l.getParent() == null) {
d.addComponent( BorderLayout.CENTER, l);
}
}

public void paint(Graphics g, Rectangle rect) {
if (l.size() > 0 && l.getSelectedItem() != null && !l.getSelectedItem().toString().equals(getText())) {
d.paint(g);
}
}
}

Shai Almog

Since you are painting on your own you need to respect the getScrollY()
value from the containers and properly "translate" the graphics context.
This is somewhat hard to explain so you should probably look in the
paintComponent code which does this properly.
I don't see why you need a Dialog class since you can just paint the
list directly on the graphics which might simplify this process.
> I've been attempting to do this for a while now, and I've come up with a problem that I can't solve. I'm trying to display a list of all autocomplete options, with 3 being displayed, and anymore being scrolled. However the scrolling doesn't work at all, instead the focus component just goes off the bottom of the list.
>
> Any ideas why? Code for autocomplete posted below, it relies on being passed the form instance so it can set / remove glass pane.
>
> import com.sun.lwuit.Component;
> import com.sun.lwuit.Container;
> import com.sun.lwuit.Dialog;
> import com.sun.lwuit.Display;
> import com.sun.lwuit.Form;
> import com.sun.lwuit.Graphics;
> import com.sun.lwuit.List;
> import com.sun.lwuit.Painter;
> import com.sun.lwuit.TextField;
> import com.sun.lwuit.events.DataChangedListener;
> import com.sun.lwuit.events.SelectionListener;
> import com.sun.lwuit.geom.Dimension;
> import com.sun.lwuit.geom.Rectangle;
> import com.sun.lwuit.layouts.BorderLayout;
> import com.sun.lwuit.list.DefaultListCellRenderer;
> import com.sun.lwuit.list.DefaultListModel;
> import com.sun.lwuit.list.ListModel;
> import java.util.Vector;
>
> public class ACTextField extends TextField {
>
> Form _parent;
> autoCompletePane autoComplete;
> boolean autoCompleteShown = false;
> List l;
> ListModel underlyingDataModel = new DefaultListModel(new String[]{"Accountants", "Advertising Agencies", "Air Conditioning", "Airlines", "Airport", "Architects", "Builder", "Baker", "Basketmaker", "Plumber", "Pizza Maker", "Piano Repair"});
>
>
> public ACTextField(Form parent) {
> _parent = parent;
> }
>
> public void keyPressed(int keyCode) {
>
> super.keyPressed(keyCode);
>
> if (!autoCompleteShown) {
> if (isEditingTrigger(keyCode)) {
> if (autoComplete == null) {
> autoComplete = new autoCompletePane();
> }
> _parent.setGlassPane(autoComplete);
> _parent.repaint();
> l.setSelectedIndex(500);
> autoCompleteShown = !autoCompleteShown;
> }
> } else if (autoCompleteShown) {
> if (isEditingEndTrigger(keyCode)) {
> _parent.setGlassPane(null);
> autoCompleteShown = !autoCompleteShown;
> }
> }
>
> int k = Display.getInstance().getGameAction(keyCode);
>
> if (k == Display.GAME_DOWN) {
> if (autoCompleteShown && l.getSelectedIndex() < l.size() - 1) {
> l.setSelectedIndex(l.getSelectedIndex() + 1);
> _parent.repaint();
>
> }
> }
>
> if (k == Display.GAME_UP) {
> if (autoCompleteShown && l.getSelectedIndex() > 0) {
> l.setSelectedIndex(l.getSelectedIndex() - 1);
> _parent.repaint();
> }
> } else {
> }
>
> }
>
> protected boolean isEditingEndTrigger(int keyCode) {
> int k = Display.getInstance().getGameAction(keyCode);
>
> if (k == Display.GAME_DOWN) {
> if (autoCompleteShown) {// && l.getSelectedIndex() < l.size() - 1) {
> return false;
> }
> }
>
> if (k == Display.GAME_UP) {
> if (autoCompleteShown && l.getSelectedIndex() > 0) {
> return false;
> }
> }
>
> if (k == Display.GAME_FIRE) {
> if (autoCompleteShown) {
> String selected = (String) l.getSelectedItem();
> if (selected != null) {
> this.setText(selected);
> setCursorPosition(getText().length());
> }
> }
> }
>
> if (isQwertyInput()) {
> return keyCode < 0 && (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN);
> }
> return (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN);
> }
>
> public boolean handlesInput() {
>
> if (autoCompleteShown) {
> return true;
> }
>
> return super.handlesInput();
> }
>
> public class autoCompletePane implements Painter {
>
> Container d;
>
> public autoCompletePane() {
> d = new Dialog();
> d.setY(getY() + getHeight() + 2);
> d.setX(10); //Why not getX()?
> d.setScrollable(true);
> d.setLayout(new BorderLayout());
> d.setHeight(100);
>
> //List
> final FilterProxyListModel proxyModel = new FilterProxyListModel(underlyingDataModel);
> l = new List(proxyModel){
>
> public void paint(Graphics g) {
> super.paint(g);
> }
> };
> l.setOrientation(List.VERTICAL);
> //Focus off the bottom of the list.
> // l.setSelectedIndex(proxyModel.getSize() + 1, false);
>
> addDataChangeListener(new DataChangedListener() {
>
> public void dataChanged(int type, int index) {
> proxyModel.filter(getText());
> }
> });
>
> DefaultListCellRenderer dlcr = new DefaultListCellRenderer(false){
> };
> l.setListCellRenderer(dlcr);
>
> if (l.getParent() == null) {
> d.addComponent( BorderLayout.CENTER, l);
> }
> }
>
> public void paint(Graphics g, Rectangle rect) {
> if (l.size() > 0 && l.getSelectedItem() != null && !l.getSelectedItem().toString().equals(getText())) {
> d.paint(g);
> }
> }
> }
> [Message sent by forum member 'rosstheboss' (rosstheboss)]
>
> http://forums.java.net/jive/thread.jspa?messageID=359743
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>
>

--
Shai Almog

LWUIT Blog http://lwuit.blogspot.com/
LWUIT FAQ https://lwuit.dev.java.net/faq.html
YouTube Channel http://www.youtube.com/user/vprise
Applications in LWUIT https://lwuit.dev.java.net/nonav/featuredapp.html

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net

Shai Almog

Hi,
generally I would suggest using a list that doesn't allow user input.
You can paint the list onto a GlassPane using a painter (the painter
would call the lists paintComponent method).
When the user presses up and down you would just send the events to
the List component. When focus for the field is lost you just remove
the glass pane from the painter chain...

> Hello.
>
> I'm working on creating a auto completing text field, a bit like
> the example I once saw on the blog. I'd like to have a suggestions
> list (scrollable) appear underneath the text field appearing to be
> part of the text field, and overlaying any other components on the
> field. An example of how this best works is the search within firefox.
>
> Any suggestions on an approach to this would be great, I'm going to
> handle data using a model and filterproxy.
>
> Thanks
> [Message sent by forum member 'rosstheboss' (rosstheboss)]
>
> http://forums.java.net/jive/thread.jspa?messageID=333315
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>

Shai Almog
http://lwuit.blogspot.com/
https://lwuit.dev.java.net/faq.html

[att1.html]

rosstheboss
Offline
Joined: 2009-02-03

Thanks for the response.

I've attempted to do it using a painter, but I can't get even the most basic of components to draw onto the glass pane.

Label label = new Label("Test");
label.paintComponent(g);

Draws nothing. I've tried setting preferred size, absolute positioning, everything but can't make any progress!

Thanks

rosstheboss
Offline
Joined: 2009-02-03

Sorry to drag this up again, but I've still not had any luck painting a list onto a glasspane. I just can't seem to get anything to show when I'm calling any componenets PaintComponent method.

Thanks

Message was edited by: rosstheboss

thorar
Offline
Joined: 2004-11-15

Hi.

I know very little of LWUIT, but if you can find some similiarities with the Swing World, the JIDE OSS component library has an intellihints component that does exactly what you are asking for: https://jide-oss.dev.java.net/.

I hope it may help you.
Marco

rosstheboss
Offline
Joined: 2009-02-03

Thanks for the link.

The real probelm I've got with LWUIT is understanding the notion of overlaying containers on other containers, without having to use the Coordinate Layout. I.e I can detect focus / text input on a textfield and overlay an auto suggest box that can then be navigated.