Find anywhere in jList items? - java

I can find item in jlist with this code. But I want to find anywhere in item. How can I do this. Thanks a lot. (Sorry my English)
For example: I can find "New or San" but I want to find "York or Diago".
New York
San Diago
jTextField1.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String text = "" + e.getKeyChar();
StringBuffer buffer = new StringBuffer(jTextField1.getText().substring(0, jTextField1.getText().length() - 1));
buffer.append(text);
int index = jList1.getNextMatch(buffer.toString(), 0, Position.Bias.Forward);
jList1.setSelectedIndex(index);
}
});

getNextMatch checks if the given string exists at the start position passed as the second param. You can just traverse the jlist to find the index.
jTextField1.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String text = "" + e.getKeyChar();
StringBuffer buffer = new StringBuffer(jTextField1.getText().substring(0, jTextField1.getText().length() - 1));
buffer.append(text);
ListModel<String> model = jList1.getModel();
int index;
for(int i = 0; i < model.getSize(); i++) {
if(model.getElementAt(i).contains(buffer.toString())){
index = i;
break;
}
}
jList1.setSelectedIndex(index);
}
});

I believe the method available in JList only searches if the items start with a specific prefix.
public List<Integer> getMatches(ListModel listModel, String text){
List<Integer> indices = new List<Integer>();
for(int i = 0; i < listModel.getSize(); i++){
if(listModel.getElementAt(i).contains(text)){
indices.add(i);
}
}
return indices;
}
The method above iterates the listmodel and checks if each element contains the text provided and returns the indices of matched items.

Related

Trying to add item listener to a JCheckBox object

I am trying add an item listener to a checkbox to see if its been checked, and if it is, to be added to a list of SQL table names to be selected. Inversely, if it is not selected then remove it from the list. I cannot add a listener though to any checkbox because "they are not effitively final". What can I do/is there a better way to attack it?
My method:
public JPanel drawChecks(){
ArrayList<String> list = MainFrame.grabSQLTableNames();
int index = list.size();
int rows = 1;
while(index > 1){
rows++;
index = index - 3;
}
GridLayout c = new GridLayout(rows, 3);
JPanel panel = new JPanel(c);
JCheckBox check[] = new JCheckBox[list.size()];
for(int x = 0; x < list.size(); x++){
check[x] = new JCheckBox(list.get(x));
check[x].setVisible(true);
check[x].addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (check[x].getState == true){
//do something
}
}
});
panel.add(check[x]);
}
Get the source of the event using the getSource method of the ItemEvent
public void itemStateChanged(ItemEvent e) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if ( checkBox.isSelected() ){
//do something
}
}
For future reference, please read the following for tips on posting code examples for asking questions on stack overflow: https://stackoverflow.com/help/mcve

Could someone tell me why my actionListener for-loop is not working?

I have a program that takes an input file, pulls a color word + hexadecimal value from it (for exaple Red 0xFF0000). I had my code working perfectly except I tried to replace my 2 arrayLists with a HashMap... That is where things took a wrong turn. I have my code back to what I believe it was before except now it is NOT changing colors when the radio buttons are pushed. Anyone want to take a peek?
public HashMapTests() {
JPanel p1 = new JPanel();
this.getContentPane().setLayout(new GridLayout(5,4));
ButtonGroup group = new ButtonGroup();
for (int i = 0; i < colorCollection.size(); i++) {
jrbColor[i] = new JRadioButton(colorCollection.get(i));
jrbColor[i].setText(colorCollection.get(i));
group.add(jrbColor[i]);
p1.add(jrbColor[i]);
}
for(int i = 0; i < colorCollection.size(); i++){
jrbColor[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
for (int j = 0; j < colorCollection.size(); j++){
String hexColor = hexCollection.get(j);
if(hexCollection.get(j).equals(((JRadioButton)e.getSource()).getText())){
getContentPane().setBackground(Color.decode(hexColor));
repaint();
}
}
}
});
}
add(p1);
}
First investigation:
while (colorCollection.size() < 10)
shall be replaced with
if (colorCollection.size() < 10)
Second observation:
jrbColor[i] = new JRadioButton(colorCollection.get(i));
jrbColor[i].setText(colorCollection.get(i));
The second line is useless, see constructor's javadoc.
Third:
The second loop where you attach the listener is useless, you can put this code to the first loop where you create a button.
Finally:
if (hexCollection.get(j).equals(((JRadioButton) e.getSource()).getText())) {
You compare here content of hexCollection with radio button text, but the button has label from colorCollection. I cannot look to your file but I think that this will be the problem.
Map Solution:
Initialization
String name = fileInput.next();
String hexValue = fileInput.next();
colors.put(name, hexValue);
Buttons
int i = 0;
for (String s : colors.keySet()) {
jrbColor[i] = new JRadioButton(s);
group.add(jrbColor[i]);
p1.add(jrbColor[i]);
jrbColor[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String hexColor = colors.get(((JRadioButton) e.getSource()).getText());
getContentPane().setBackground(Color.decode(hexColor));
}
});
}

Bin Packing Algorithm In Need of Speeding-Up

I'm looking for an intelligent way to approach a version of the common bin-packing problem. Given a number of bags (as I'm calling them) with a certain capacity, and list of items that take up a certain amount of space, the task is to determine if all of the items can fit in the bags; and if so, how. I've got an exhaustive DFS working right now, but it takes... forever. My DFS is iterative and requires copying entire states at every step, which is very expensive. Here's my code for a specific problem with 4 bags with 10 capacity (the truly relevant portions of this code are just the pack() method and the State class if you don't want to look at it all):
import java.util.ArrayList;
import java.util.Stack;
public class BagProblem {
int numBags;
int bagCapacity;
ArrayList<Item> items = new ArrayList<Item>();
public static void main(String[] args) {
BagProblem bp = new BagProblem(4, 10);
bp.pack();
}
public BagProblem(int numBags, int bagCapacity) {
this.numBags = numBags;
this.bagCapacity = bagCapacity;
items = new ArrayList<Item>();
items.add(new Item("item0", 6));
items.add(new Item("item1", 6));
items.add(new Item("item2", 6));
items.add(new Item("item5", 3));
items.add(new Item("item6", 3));
items.add(new Item("item7", 3));
items.add(new Item("item8", 2));
items.add(new Item("item9", 2));
items.add(new Item("item10", 2));
items.add(new Item("item11", 2));
items.add(new Item("item12", 2));
items.add(new Item("item13", 2));
items.add(new Item("item14", 1));
}
// find a valid way to pack and print the items in each Bag, or
// print failure
public void pack() {
Stack <State> s = new Stack<State>();
Bag[] currBags = new Bag[numBags];
for (int i = 0; i < numBags; i++) {
currBags[i] = new Bag(bagCapacity);
}
s.push(new State(currBags));
while(!s.isEmpty()) {
State currState = s.pop();
for (Item i : items) {
if (!currState.containsItem(i)) {
State newState = new State(currState.bags);
newState.numItems = currState.numItems;
if (newState.addItem(i)) {
s.push(newState);
if (newState.numItems == items.size()) {
System.out.println("success");
System.out.println(newState);
return;
}
}
}
}
}
System.out.println("failure");
}
private class State {
Bag[] bags;
int numItems;
public State(Bag[] currBags) {
bags = new Bag[numBags];
for (int i = 0; i < numBags; i++) {
bags[i] = new Bag(bagCapacity);
}
// figure out how to actually copy this
for (int j = 0; j < numBags; j++) {
Bag bagToCopy = currBags[j];
for (Item item : bagToCopy.contents) {
Item newItem = new Item(item.name, item.size);
bags[j].size = bagToCopy.size;
bags[j].contents.add(newItem);
}
}
}
public boolean addItem(Item i) {
for (Bag b : bags) {
if (b.addItem(i)) {
numItems++;
return true;
}
}
return false;
}
public boolean containsItem(Item i) {
for (Bag b : bags) {
for (Item item : b.contents) {
if (item.name.equals(i.name))
return true;
}
}
return false;
}
public String toString() {
String output = "";
for (Bag b : bags) {
for (Item j : b.contents) {
output += j.name + " ";
}
output += "\n";
}
return output;
}
}
private class Bag {
int capacity;
int size;
ArrayList<Item> contents;
public Bag(int capacity) {
this.capacity = capacity;
this.size = 0;
contents = new ArrayList<Item>();
}
public boolean addItem(Item i) {
if(size + i.size > capacity)
return false;
contents.add(i);
size += i.size;
return true;
}
public String toString() {
String output = "";
for (Item i : contents) {
output += i.name + " ";
}
return output + "\n";
}
}
private class Item {
String name;
int size;
public Item(String name, int size) {
this.name = name;
this.size = size;
}
public String toString() {
return name;
}
}
}
After approximately one million years, this does spit out a correct answer (you probably won't want to actually wait that long if you try to run this):
success
item14 item7 item6 item5
item13 item12 item2
item11 item10 item1
item9 item8 item0
Each line indicates a separate bag. How can I speed this up? I know there are heuristics about trying to place the largest item first, etc., but what I'm really interested in is getting the basic DFS (or maybe I should try backtracking?) to have less overhead; I'll try to get fancier later.
Any help would be greatly appreciated.
I don't use Java but your implementation seems quite inefficient (as you've mentioned yourself) due to overcomplicating it. The algorithm itself is also very strange, I did not attempt to replicate it and just used the obvious O(bags^items) brute force algorithm that tries to put the first item into each bag, for each of those cases tries to put the second item into each bag, etc...
Instead of replicating the entire state repeatedly on the stack, you can put an item in a bag, explore the branch of the tree with this change, then take the item out of the bag.
Here is an example that completes instantly for your test case in C#.
static int[] itemSize;
static int[] bagFreeSpace;
static bool[,] doesBagContainItem; // in case this looks weird, [,] is a matrix, in java it would be [][]
static bool pack(int item)
{
// output the solution if we're done
if (item == itemSize.Length)
{
for (int i = 0; i < bagFreeSpace.Length; i++)
{
Console.WriteLine("bag" + i);
for (int j = 0; j < itemSize.Length; j++)
if (doesBagContainItem[i, j])
Console.Write("item" + j + "(" + itemSize[j] + ") ");
Console.WriteLine();
}
return true;
}
// otherwise, keep traversing the state tree
for (int i = 0; i < bagFreeSpace.Length; i++)
{
if (bagFreeSpace[i] >= itemSize[item])
{
doesBagContainItem[i,item] = true; // put item into bag
bagFreeSpace[i] -= itemSize[item];
if (pack(item + 1)) // explore subtree
return true;
bagFreeSpace[i] += itemSize[item]; // take item out of the bag
doesBagContainItem[i,item] = false;
}
}
return false;
}
static void Main(string[] args)
{
itemSize = new int[] { 6, 6, 6, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1 };
bagFreeSpace = new int[] { 10, 10, 10, 10 };
doesBagContainItem = new bool[bagFreeSpace.Length, itemSize.Length];
if (!pack(0))
Console.WriteLine("No solution");
}
Note: if you want to parallelize execution, you need to give each worker its own copy of the state (or 1 copy per job), but only at the point of branching, they can still then proceed as above, without replicating the state.

JComboBox setSelectedItem does not work

I am trying to set the setSelectedItem of the JComboBox in the constructor of my JPanel class just after populating the combobox.
I am set the value for textbox, but I can't figure out why setSelectedItem does not seem to work. Any ideas?
public StudentProfilePanel(StudentInfo si) {
yesButton.setBounds(50, 346, 69, 40);
noButton.setBounds(121, 346, 56, 40);
this.add(yesButton);
this.add(noButton);
setLayout(null);
comboBoxYear.setModel(new DefaultComboBoxModel(years()));
comboBoxYear.setBounds(202, 365, 62, 23);
if(si.birthdate!=null){
//System.out.println("year value : ["+dateofbirth(si.birthdate)[2]+"]");
comboBoxYear.setSelectedItem(dateofbirth(si.birthdate)[2]);
}
add(comboBoxYear);
comboBoxMonth.setModel(new DefaultComboBoxModel(new String[]{"01","02","03","04","05","06","07","08","09","10","11","12"}));
comboBoxMonth.setBounds(285, 365, 56, 23);
//set month value
if(si.birthdate!=null){
//comboBoxMonth.setSelectedItem(dateofbirth(si.birthdate)[1]);
comboBoxMonth.setSelectedItem("04");
System.out.println("month value : ["+dateofbirth(si.birthdate)[1]+"]");
}
add(comboBoxMonth);
comboBoxDay.setModel(new DefaultComboBoxModel(days()));
comboBoxDay.setBounds(351, 365, 54, 23);
if(si.birthdate!=null){
//comboBoxDay.setSelectedItem(dateofbirth(si.birthdate)[0]);
comboBoxDay.setSelectedItem(dateofbirth(si.birthdate)[0]);
}
add(comboBoxDay);
textFieldFirstName = new JTextField();
textFieldFirstName.setBounds(21, 321, 171, 21);
add(textFieldFirstName);
textFieldFirstName.setColumns(10);
// set the value of first name
textFieldFirstName.setText(si.firstName);
textFieldLastName = new JTextField();
textFieldLastName.setBounds(242, 321, 163, 21);
add(textFieldLastName);
textFieldLastName.setColumns(10);
//set the value of the last name
textFieldLastName.setText(si.lastName);
JPanel panelPersonPhoto = new ImagePanel(
"C:\\Users\\MDJef\\Pictures\\Wallpaper\\General\\11.jpg");
panelPersonPhoto.setBorder(new TitledBorder(null, "",
TitledBorder.LEADING, TitledBorder.TOP, null, null));
panelPersonPhoto.setBounds(21, 20, 384, 291);
add(panelPersonPhoto);
}
Thanks very much.
helper methods that I used
// jf : helper method
public String[] years() {
String[] results = new String[90];
for (int i = 0; i < 90; i++) {
results[i] = Integer.toString(1900 + i);
}
return results;
}
// jf : helper method
public String[] months() {
String[] results = new String[12];
for (int i = 0; i < 12; i++) {
results[i] = Integer.toString(i + 1);
}
return results;
}
// jf : helper method
public String[] days() {
String[] results = new String[31];
for (int i = 0; i < 31; i++) {
results[i] = Integer.toString(i + 1);
}
return results;
}
// jf : helper method
public String[] dateofbirth(String dob) {
String[] tokens = dob.split("-");
return tokens;
}
The values assigned to the combo box are not the same values you are trying set.
For example, the years are Strings from 1900 - 1990, but if I supply a value 72, there is no matching value in the combo box to match to.
Equally, your days and months methods are only returning values that are not padded (ie 01), where as, in your code, you're trying to set the value using a padded value (ie 04), meaning there is no matching value...
You have a number of options...
You could...
Convert all the values to an int, meaning that the values in the combo box are simply ints. You would then need to convert the date values to ints as well.
This would make your helper code look more like...
public int[] years() {
int[] results = new String[90];
for (int i = 0; i < 90; i++) {
results[i] = 1900 + i;
}
return results;
}
public int[] months() {
int[] results = new String[12];
for (int i = 0; i < 12; i++) {
results[i] = i + 1;
}
return results;
}
public int[] days() {
int[] results = new String[31];
for (int i = 0; i < 31; i++) {
results[i] = i + 1;
}
return results;
}
public int[] dateofbirth(String dob) {
int[] tokens = dob.split("-");
int[] values = new int[tokens.length];
for (int index = 0; index < tokens.length; index++) {
values[index] = Integer.parse(tokens[index]);
}
return index;
}
A better solution
Would be to use a JSpinner, which would take care of date rolling issues and validation automatically.
Check out Using Standard Spinner Models and Editors
Not related to your problem, but:
yesButton.setBounds(50, 346, 69, 40);
noButton.setBounds(121, 346, 56, 40);
setLayout(null);
Don't use a null layout and setBounds(...). Swing was designed to be used with Layout Manager. In the long run you will save time.
if(si.birthdate!=null){
Don't access variables in your class directly. Create a getter method to access the properties of your class.
//System.out.println("year value : ["+dateofbirth(si.birthdate)[2]+"]");
comboBoxYear.setSelectedItem(dateofbirth(si.birthdate)[2]);
Don't always try to force you code into a single statement. Instead do something like:
String birthdate = dateofbirth(si.birthdate[2]);
System.out.println("year value : [" + birthdate +"]");
comboBoxYear.setSelectedItem(birthdate);
This helps with your debugging because now you know that the variable you display is the same variable that you are trying to use in the setSelectedItem() method. It saves typing the statement twice and avoids typing mistakes.
When you call comboBoxMonth.setSelectedItem("04"); you try to select a newly created String which is not equal to the one which is in your JComboBox. Ergo it does not get selected.
You can try something like this instead:
String[] months = new String[] {"01","02","03","04","05","06","07","08","09","10","11","12"};
comboBoxMonth.setModel(new DefaultComboBoxModel(months));
comboBoxMonth.setSelectedItem(months[3]);
Edit: Try this. It uses the index of the item instead. Just make sure you add the months in order to the array.
String[] months = new String[] {"01","02","03","04","05","06","07","08","09","10","11","12"};
comboBoxMonth.setModel(new DefaultComboBoxModel(months));
if(si.birthdate!=null)
{
comboBoxMonth.setSelectedIndex(Integer.parseInteger(dateofbirth(si.birthdate)[1]) - 1);
}
For other developer with the same issue:
A closer look into the implementation of setSelectedItem(Object anObject) from JComboBox might help:
public void setSelectedItem(Object anObject) {
Object oldSelection = selectedItemReminder;
Object objectToSelect = anObject;
if (oldSelection == null || !oldSelection.equals(anObject)) {
if (anObject != null && !isEditable()) {
// For non editable combo boxes, an invalid selection
// will be rejected.
boolean found = false;
for (int i = 0; i < dataModel.getSize(); i++) {
E element = dataModel.getElementAt(i);
if (anObject.equals(element)) {
found = true;
objectToSelect = element;
break;
}
}
if (!found) {
return;
}
}
...
In the loop your object is compared with an object of the dataModel with the specific type E. In the implementation of equals() from String you can see a verification of class/interface, length and each character one after another. That means, our object must have same type and all characters must be the same!
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
And this is the most annoying part if (anObject.equals(element)) in setSelectedItem! You cant override equals method from your element. For example StudentInfo and compare other types like strings or integers to it. Simple example. You implement combobox like this JComboBox<StudentInfo> and you want to select the student with int id = 2;. So it compares now Integer with StudentInfo. Here you have to override equals from Integer...
My proposal is to swap it. Create own class, add boolean selectingItem and override setSelectedItem(Object anObject) and contentsChanged(ListDataEvent e)(this method one-to-one). Nevertheless, I had side effects in one project...
Use the following:
comboBoxMonth.setSelectedItem(index of the array);
The item you wish to set as selected must share the class of the objects stored in the JComboBox.
public static void main(String[] args) {
String[] items = {"1", "2", "3"};
JComboBox jcb = new JComboBox(items);
jcb.setSelectedItem(3);
System.out.println(jcb.getSelectedItem());
jcb.setSelectedItem(3+"");
System.out.println(jcb.getSelectedItem());
}
Output of the above code:
1
3

In Java/Swing, is there a way to legally "attempt to mutate in notification"?

I was wondering if there is some sort of magic I can use to get around an IllegalStateException and allow a JTextField to "attempt to mutate in notification", or in other words to set its own text if its listener is triggered.
For your information, I am trying to program an auto-complete function which returns the most likely match in a range of 12 enums in response to a user's input in the JTextField.
Here is the code sample. You'll have to pardon my clumsy algorithm which creaks out enum results. I've highlighted the code which produces the exception with a comment:
jtfElement1.addCaretListener(new CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
String s = jtfElement1.getText();
int[] attributes = new int[13];
// iterate through each enum
for (BaseEnumAttributes b: BaseEnumAttributes.values()) {
// iterate through the length of the current text in jtfElement1
for (int i = 0; i < s.length(); i++) {
if (s.length() <= b.toString().length()) {
if (b.toString().charAt(i) == s.charAt(i)) {
// increase the number of "hits" noted for that enum
attributes[b.ordinal()] = attributes[b.ordinal()] + 1;
}
}
}
}
int priorC = 0;
int rightC = 0;
// iterate through the "array" of enums to find the highest score
for (int j = 0; j < attributes.length; j++) {
if (attributes[j] > priorC) {
priorC = attributes[j];
rightC = j;
}
}
if (!s.equals("")) {
// assign to b the Enum corresponding to the "array" with highest score
BaseEnumAttributes b = BaseEnumAttributes.values()[rightC];
iController.updateInputElement1String(b.toString());
// THIS TRIGGERS EXCEPTION
jtfElement1.setText(b.toString());
}
}
});
You are probably better off using a document filter or a custom document.
What are other listeners expected to see if the document doesn't stay the same during event dispatch?
Use SwingUtilities.invokeLater() placing all the modifications there
Maybe you can delay the setText() with a Thread to run after caretUpdate() has terminated.
i'm found on the same problem but i found an easy solution:
lock the caretUpdate() by a boolean if(false) while u'r setting the text to the jTextField than unlock it after . . something like this:
boolean caret = true;
private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {
caret = false;
name.setText((String)list.getSelectedValue());
caret = true;
}
private void nameCaretUpdate(javax.swing.event.CaretEvent evt) {
if(caret){
model = new DefaultListModel();
this.fillList(name.getText());
list.setModel(model);
}
}
Create a custom Document and override insertString( )
filenameText = new JTextField(new FilenameDocument(), "", 0);
...
/**
* document which adds .xml extension if not specified
*
*/
private class FilenameDocument extends PlainDocument {
#Override
public void insertString(int offset, String insertedText, AttributeSet set)
throws BadLocationException {
if (offset == 0) {
insertedText = insertedText.trim( );
}
super.insertString(offset, insertedText, set);
if (filenameText != null) {
final int caretPos = filenameText.getCaretPosition();
String text = filenameText.getText().trim();
if (text.indexOf('.') == -1) {
filenameText.setText(text + ".xml");
filenameText.setCaretPosition(caretPos);
}
}
}
}
Note that calling setText will result in a recursive call to insertString( ), so make sure you have a stopping condition.
I'm surprised no one has answered this, but would'nt you have been better off implementing an editable JSpinner with a SpinnerListModel?

Categories