Autocompletion stops after entering one word using JSuggestField - SSCCE attached - java

I added to my project the element of autocompletion; but after the user has entered one
word, the autocompletion algorithm stops. I can add more characters, however without
the autocompltion's suggestions.
I'm using JSuggestField (added the jar to my project) , here is SSCCE that illustrates the problem :
import javax.swing.*;
import ch.rakudave.suggest.JSuggestField;
import java.awt.*;
import java.util.Vector;
public class Classic extends JFrame {
public static final String CHILD = "/child::";
public static final String DESCENDANT = "/descendant::";
public static final String FOLLOWING_SIBLING = "/following-sibling::";
public static final String DESCENDANT_OR_SELF = "/descendant-or-self::";
public static final String SELF = "/self::";
public static final String PRECEDING_SIBLING = "/preceding-sibling::";
public static final String ANCESTOR_OR_SELF = "/ancestor-or-self::";
public static final String ANCESTOR = "/ancestor::";
public static final String FOLLOWING = "/following::";
public static final String PRECEDING = "/preceding::";
public Classic() {
initComponents();
}
private void initComponents() {
Vector<String> vector = new Vector<String>();
vector.add(DESCENDANT);
vector.add(FOLLOWING_SIBLING);
vector.add(DESCENDANT_OR_SELF);
vector.add(SELF);
vector.add(PRECEDING_SIBLING);
vector.add(ANCESTOR_OR_SELF);
vector.add(ANCESTOR);
vector.add(FOLLOWING);
vector.add(PRECEDING);
JSuggestField jsuggest= new JSuggestField(this,vector );
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(200, 200);
Container container = getContentPane();
container.setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField textField = new JTextField(15);
jsuggest.setPreferredSize(new Dimension(100, 20));
//
// Right justify the JTextField contents
//
jsuggest.setHorizontalAlignment(JTextField.RIGHT);
container.add(jsuggest);
textField = jsuggest;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Classic().setVisible(true);
}
});
}
}
Here is a snapshot : .
This is nice , but I want that the autocompletion would work after each time the user has entered the character /, hence one autocompletion is not enough.
Any idea how can I solve this using JSuggestField or something else?
Thanks.

Related

Java: Add Place Holder on JTextField

Is there a way or method in which we can add placeholder in j text field. I want to add placeholder "Enter Your Number" in field but how can I do this. I check all methods but didn't working.
Code:
public class Loop extends JFrame{
private JTextField t1;
public L(){
getContentPane().setLayout(null);
t1=new JTextField();
t1.setBounds(27,50,47,28);
getContentPane().add(t1);
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
}
Main:
public class Main {
public static void main(String[] args) {
L object = new L();
}
}
Check out Text Prompt for a flexible solution.
You can control when prompt is displayed (always, focus gained or focus lost). You can also customize the style of the text.
Here is an example of which you can you inspire
package TinyOS;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.Document;
#SuppressWarnings("serial")
public class PlaceholderTextField extends JTextField {
public static void main(final String[] args) {
final PlaceholderTextField tf = new PlaceholderTextField ("");
tf.setColumns(20);
tf.setPlaceholder("Here is a placeHolder!");
final Font f = tf.getFont();
tf.setFont(new Font(f.getName(), f.getStyle(), 30));
JOptionPane.showMessageDialog(null, tf);
}
private String placeholder;
public PlaceholderTextField () {
}
public PlaceholderTextField (
final Document pDoc,
final String pText,
final int pColumns)
{
super(pDoc, pText, pColumns);
}
public PlaceholderTextField (final int pColumns) {
super(pColumns);
}
}
I hope that can help you
This code should work, it listen on first click and removes the text
public class Loop extends JFrame{
private JTextField t1;
private boolean clicked = false;
public L(){
getContentPane().setLayout(null);
t1=new JTextField();
t1.setText("Enter Your Number");
t1.addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent e){
if(!clicked){
clicked=true;
t1.setText("");
}
}
}
t1.setBounds(27,50,47,28);
getContentPane().add(t1);
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
}
Maybe better solution exists
Note - not tested
EDIT (how the boolean clicked works)
when you call method mousePressed(MouseEvent) at the first time, the clicked variable is false, by declaration:
private boolean clicked = false;
So the if body is executed (because !clicked = !false = true)
in the if body, the clicked variable is set to true, so if condition will be then false: (because !clicked = !true = false)
This solves the problem of running code just once.

Swing Component communication

i am building an algorithm simulation tool and I am struggling to get my mainframe class which instantiates and adds all the subcomponents to the JFrame to get the file system location of where the pseudocode is located (for the psuedocode panel.)
I have made every single algorithm have a string which details where the relevant text file information for each algorithm is.
I have a method which then takes the string when the algorithm is passed in and stores it into a string variable.
This string variable is then passed to the panel.
Unfortunately this is throwing a null pointer and I have been trying to debug this and can't get far.
public class SortAnimator extends JFrame
{
private static final int VALUES_LENGTH = 30;
private static final int FRAME_WIDTH = 1200;
private static final int FRAME_HEIGHT = 700;
private PsuedocodePanel pseudoPanel;
private Menu menu;
private InformationPanel infoPanel;
private String algoName;
public String algoLocation;
public SortAnimator(Sorter s) throws IOException
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu=new Menu();
pseudoPanel=new PsuedocodePanel();
ArrayComponent panel = new ArrayComponent();
infoPanel= new InformationPanel();
add(menu,BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
add(pseudoPanel,BorderLayout.WEST);
add(infoPanel,BorderLayout.SOUTH);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
int[] values = new int[VALUES_LENGTH];
for (int i = 0; i < values.length; i++)
values[i] = (int) (Math.random() * panel.getHeight());
s.setValues(values);
s.setPanel(panel);
Thread t = new Thread(s);
t.start();
algoName=s.getAlgorithmName();
algoLocation =s.getAlgorithmLocation();
System.out.println(algoLocation);
pseudoPanel.passFileLocation(algoLocation);
}
}
public class PsuedocodePanel extends JPanel{
private JTextArea txtArea;
private String textFile;
private String fileLocation;
public PsuedocodePanel() throws FileNotFoundException, IOException{
setLayout(new BorderLayout());
txtArea=new JTextArea();
txtArea.setEditable(false);
add(txtArea,BorderLayout.CENTER);
FileReader fr = new FileReader(this.fileLocation);
BufferedReader reader=new BufferedReader(fr);
txtArea.read(reader,null);
Dimension dim=getPreferredSize();//returns object
System.out.println(getPreferredSize());
dim.width=300;
dim.height=75;
setPreferredSize(dim);
Border innerBorder=BorderFactory.createTitledBorder("Algorithm Psuedocode");
Border outerBorder=BorderFactory.createEmptyBorder(5,5,5,5);
setBorder(BorderFactory.createCompoundBorder(outerBorder,innerBorder));
}
public void passFileLocation(String algoLocation) {
this.fileLocation= algoLocation;
}
Your PsuedocodePanel class creates a FileReader in its constructor, using this.fileLocation, but fileLocation will be null at that point in the code - see simplified code fragment below:
public class PsuedocodePanel extends JPanel{
private String fileLocation; // not initialised
// constructor does not accept a fileLocation...
public PsuedocodePanel() throws FileNotFoundException, IOException{
// ... so this.fileLocation is null here:
FileReader fr = new FileReader(this.fileLocation);

Java JTextField information access from another class

I am using a gui with JTextFields to collect some information and then a JButton that takes that infomration and writes it to a file, sets the gui visibility to false, and then uses Runnable to create an instance of another JFrame from a different class to display a slideshow.
I would like to access some of the information for the JTextFields from the new JFrame slideshow. I have tried creating an object of the previous class with accessor methods, but the values keep coming back null (I know that I have done this correctly).
I'm worried that when the accessor methods go to check what the variables equal the JTextFields appear null to the new JFrame.
Below is the sscce that shows this problem.
package accessmain;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class AccessMain extends JFrame implements ActionListener
{
private static final int FRAMEWIDTH = 800;
private static final int FRAMEHEIGHT = 300;
private JPanel mainPanel;
private PrintWriter outputStream = null;
private JTextField subjectNumberText;
private String subjectNumberString;
public static void main(String[] args)
{
AccessMain gui = new AccessMain();
gui.setVisible(true);
}
public AccessMain()
{
super("Self Paced Slideshow");
setSize(FRAMEWIDTH, FRAMEHEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
//Begin Main Content Panel
mainPanel = new JPanel();
mainPanel.setBorder(new EmptyBorder(0,10,0,10));
mainPanel.setLayout(new GridLayout(7, 2));
mainPanel.setBackground(Color.WHITE);
add(mainPanel, BorderLayout.CENTER);
mainPanel.add(new JLabel("Subject Number: "));
subjectNumberText = new JTextField(30);
mainPanel.add(subjectNumberText);
mainPanel.add(new JLabel(""));
JButton launch = new JButton("Begin Slideshow");
launch.addActionListener(this);
mainPanel.add(launch);
//End Main Content Panel
}
#Override
public void actionPerformed(ActionEvent e)
{
String actionCommand = e.getActionCommand();
if(actionCommand.equals("Begin Slideshow"))
{
subjectNumberString = subjectNumberText.getText();
if(!(subjectNumberString.equals("")))
{
System.out.println(getSubjectNumber());
this.setVisible(false);
writeFile();
outputStream.println("Subject Number:\t" + subjectNumberString);
outputStream.close();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass();
testClass.setVisible(true);
}
});
}
else
{
//Add warning dialogue here later
}
}
}
private void writeFile()
{
try
{
outputStream = new PrintWriter(new FileOutputStream(subjectNumberString + ".txt", false));
}
catch(FileNotFoundException e)
{
System.out.println("Cannot find file " + subjectNumberString + ".txt or it could not be opened.");
System.exit(0);
}
}
public String getSubjectNumber()
{
return subjectNumberString;
}
}
And then creating a barebones class to show the loss of data:
package accessmain;
import javax.swing.*;
import java.awt.*;
public class AccessClass extends JFrame
{
AccessMain experiment = new AccessMain();
String subjectNumber = experiment.getSubjectNumber();
public AccessClass()
{
System.out.println(subjectNumber);
}
}
Hardcoding the accessor method with "test" like this:
public String getSubjectNumber()
{
return "test";
}
Running this method as below in the new JFrame:
SelfPaceMain experiment = new SelfPaceMain();
private String subjectNumber = experiment.getSubjectNumber();
System.out.println(subjectNumber);
Does cause the system to print "test". So the accessor methods seem to be working. However, trying to access the values from the JTextFields doesn't seem to work.
I would read the information from the file I create, but without being able to pass the subjectNumber (which is used as the name of the file), I can't tell the new class what file to open.
Is there a good way to pass data from JTextFields to other classes?
pass the argument 'AccessMain' or 'JTextField' to the second class:
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass(AccessMain.this); //fixed this
testClass.setVisible(true);
}
});
Then reading the value of 'subjectNumber'(JTextField value) from the 'AccessMain' or 'JTextField' in the second class:
public class AccessClass extends JFrame
{
final AccessMain experiment;
public AccessClass(AccessMain experiment)
{
this.experiment = experiment;
}
public String getSubjectNumber(){
return experiment.getSubjectNumber();
}
}
Also, you should try Observer pattern.
A simple demo of Observalbe and Observer
Observable and Observer Objects

Java console keyboard - accept input automatically

I am creating a simple console application in which I can use keyboard arrow keys as an input like a typical remote of a toy. When I press arrow up the console will print the output text "UP" or if I press arrow down it will print "down".
I want to press the arrow key only once, i.e. I am not needed to press enter afterwards to accept my input. I want the input to be accepted automatically on pressing the arrow key.
I already tried some code but this is still not happening and I still need to press enter to accept my input. If you have any idea how I can achieve this as simple as possible, I would really appreciate it.
This sample code will helps you to get the Left Arrow Key Event. You can refer this,
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Test2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 50;
private Timer leftKeyTimer = new Timer(TIMER_DELAY , new TimerListener());
public Test2() {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition );
ActionMap actionMap = getActionMap();
String leftDownKey = "Left Down";
String leftUpKey = "Left Up";
KeyStroke leftDown = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT , 0, false);
KeyStroke leftUp = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT , 0, true);
inputMap.put(leftDown, leftDownKey);
inputMap.put(leftUp, leftUpKey);
actionMap.put(leftDownKey, new LeftKeyAction(false));
actionMap.put(leftUpKey, new LeftKeyAction(true));
leftKeyTimer.setActionCommand("Left Key");
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class LeftKeyAction extends AbstractAction {
private boolean onKeyRelease;
public LeftKeyAction(boolean onKeyRelease) {
this.onKeyRelease = onKeyRelease;
}
#Override
public void actionPerformed(ActionEvent e) {
if (onKeyRelease) {
if (leftKeyTimer != null && leftKeyTimer.isRunning()) {
leftKeyTimer.stop();
}
} else {
if (leftKeyTimer != null && !leftKeyTimer.isRunning()) {
leftKeyTimer.start();
}
}
}
}
private class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent actEvt) {
System.out.println(actEvt.getActionCommand());
}
}
private static void createAndShowGui() {
Test2 mainPanel = new Test2();
JFrame frame = new JFrame("Test2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
This is actually a surprisingly complicated problem.
If you want a true console app (no GUI elements) you have to sacrifice portability.
Most consoles are line buffered by default, so Java won't get any input until enter is pressed. Most can be switched to a character mode, but there is no OS independent way to do this. For more information see http://www.darkcoding.net/software/non-blocking-console-io-is-not-possible/

Java notSerializableExceptionError

When trying to save an arraylist of my class Click, I get this error: java.io.NotSerializableException:javax.swing.text.DefaultHighlighter$LayeredHighlightInfo
on this line of code: os.writeObject(saveList);. Even though I made my Click class implement serializable. Does anyone know the cause of this?
Here is my save Method:
public static void saveArray(ArrayList<Click> saveList) {
JFileChooser c = new JFileChooser();
c.showSaveDialog(new JFrame());
File f = c.getSelectedFile();
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(
f.getAbsolutePath()));
os.writeObject(saveList);
} catch (IOException e1) {
e1.printStackTrace();
}
}
And here is my Click class:
public static class Click implements Serializable {
JTextField xClickField;
JTextField yClickField;
JTextField clickIntervalField;
JTextField repeatTimesField;
boolean isLeft;
Integer clickX;
Integer clickY;
Integer clickInterval;
Integer clickTimes;
public Click(boolean left){
xClickField = new JTextField();
yClickField = new JTextField();
clickIntervalField = new JTextField();
repeatTimesField = new JTextField();
clickX = 0;
clickY = 0;
clickInterval = 0;
clickTimes = 0;
isLeft = left;
addToJPanel();
}
public void addToJPanel() {
xClickField.setText(clickX.toString());
yClickField.setText(clickY.toString());
clickIntervalField.setText(clickInterval.toString());
repeatTimesField.setText(clickTimes.toString());
panel.add(xClickField);
panel.add(yClickField);
panel.add(clickIntervalField);
panel.add(repeatTimesField);
frame.setVisible(false);
frame.setVisible(true);
}
public void removeFromJPanel() {
panel.remove(xClickField);
panel.remove(yClickField);
panel.remove(clickIntervalField);
panel.remove(repeatTimesField);
frame.setVisible(false);
frame.setVisible(true);
}
}
By the way I took out a chunk of code from the Click class. So if you think that the error could be in that portion of the code, I will gladly add it in.
Thanks in advance!
Implementing Serializable is not sufficient to make an object serializable. For example, a Socket is not serializable: it doesn't make sense to serialize a socket. So, if you have a Foo class that has a field of type Socket and that implements Serializable, how do you intend to serialize a Foo instance. It won't work. All the fields of a serializable object msut also be serializable, recursively.
And, as Hovercraft says in his comment, you should serialize data, not swing components.
You're serializing JTextFields and other Swing components which is a waste of time and resources and is completely unnecessary. You should be serializing the state of your GUI, the data held by the class's fields. If you understand MVC, you should be serializing the model, not the view. If you don't understand MVC, Google it or read this article and learn the key concepts as they are key to creating GUI programs in any language.
Also, for my money, I'd use JAXB or some other XML-based tool to serialize your data as it is saved in text format and thus understandable when read.
Example of separating GUI from model and using a property change listener to listen and respond to property changes:
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class SimpleClickEg {
private static void createAndShowGui() {
SimpleClickPanel clickPanel = new SimpleClickPanel();
JFrame frame = new JFrame("SimpleClickEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(clickPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class SimpleClickPanel extends JPanel {
private static final int PREF_WIDTH = 800;
private static final int PREF_HIEGHT = 600;
private JTextField clickCountField = new JTextField(5);
private JTextField clickXField = new JTextField(5);
private JTextField clickYField = new JTextField(5);
private SimpleClick click = new SimpleClick();
public SimpleClickPanel() {
add(new JLabel("Click X:"));
add(clickXField);
add(new JLabel("Click Y:"));
add(clickYField);
add(new JLabel("Click Count:"));
add(clickCountField);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
click.setClickPoint(e.getPoint());
}
});
click.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (SimpleClick.CLICK_COUNT.equals(evt.getPropertyName())) {
clickCountField.setText(String.valueOf(click.getClickCount()));
} else if (SimpleClick.CLICK_X.equals(evt.getPropertyName())) {
clickXField.setText(String.valueOf(click.getClickX()));
} else if (SimpleClick.CLICK_Y.equals(evt.getPropertyName())) {
clickYField.setText(String.valueOf(click.getClickY()));
}
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_WIDTH, PREF_HIEGHT);
}
public SimpleClick getClick() {
return click;
}
}
class SimpleClick implements Serializable {
private static final long serialVersionUID = 1L;
public static final String CLICK_COUNT = "click count";
public static final String CLICK_X = "click x";
public static final String CLICK_Y = "click y";
private int clickCount;
private int clickX;
private int clickY;
private transient SwingPropertyChangeSupport spcSupport = new SwingPropertyChangeSupport(
this);
public int getClickCount() {
return clickCount;
}
public void setClickCount(int clickCount) {
Integer oldValue = this.clickCount;
Integer newValue = clickCount;
this.clickCount = newValue;
spcSupport.firePropertyChange(CLICK_COUNT, oldValue, newValue);
}
public void incrementClickCount() {
setClickCount(getClickCount() + 1);
}
public void setClickPoint(Point p) {
setClickX(p.x);
setClickY(p.y);
incrementClickCount();
}
public int getClickX() {
return clickX;
}
public void setClickX(int clickX) {
Integer oldValue = this.clickX;
Integer newValue = clickX;
this.clickX = newValue;
spcSupport.firePropertyChange(CLICK_X, oldValue, newValue);
}
public int getClickY() {
return clickY;
}
public void setClickY(int clickY) {
Integer oldValue = this.clickY;
Integer newValue = clickY;
this.clickY = newValue;
spcSupport.firePropertyChange(CLICK_Y, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
spcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
spcSupport.removePropertyChangeListener(listener);
}
}
As you can see the error clearly states that javax.swing.text.DefaultHighlighter is not serializable.
Now this class is used by composition inside the JTextField, which is a GUI component and it is not meant to be serialized. From your code it seems that you don't need to serialize the fields themselves, so just mark them as transient and you are done.
As a side note: it is always good to split what is your data from what is your GUI so that you can easily serialize just data and foget about anything concerning the GUI. This helps in general, not just in serialization, to preserve encapsulation and use OOP as it is meant to be used.
The problem is that your Click class has references to JTextField instances, and these (presumably) have references to some Swing class called DefaultHighlighter.LayeredHighlightInfo ... and that is not serializable.
You probably need to declare the 4 JTextField variables as transient. As a general rule, Java GUI classes such as Swing components are not effectively serializable.

Categories