I have a JComboBox that displays 2 columns. Now I would like to enable to search by key on all columns. Example:
Column1 | Column2
A1 | S1
A2 | B1
A3 | P1
The search by key on the first column works fine with default Implementation of KeySelectionManager for JComboBox. However, I would also like to be able to search for the second column as well, meaning when I press 'B' the second item is selected.
I have taken a look at the KeySelectionManager but didn't find anything useful. I have attached a screenshot of the ComboBox to show what I mean.
Thanks for any pointers.
Check KeySelectionManager implemetation in JComboBox's source code
class DefaultKeySelectionManager implements KeySelectionManager, Serializable {
public int selectionForKey(char aKey,ComboBoxModel aModel) {
....
for ( i = ++currentSelection, c = aModel.getSize() ; i < c ; i++ ) {
Object elem = aModel.getElementAt(i);
if (elem != null && elem.toString() != null) {
v = elem.toString().toLowerCase();
if ( v.length() > 0 && v.charAt(0) == aKey )
return i;
}
}
So try to override your model's Element's class toString() method to include both columns.
If you display two columns in the combo box then you must be using a custom renderer.
So maybe the approach presented in Combo Box With Custom Renderer can help. The solution in the blog combines the renderer and KeySelectionManager into a single class. All you need to do is implement the getDisplayValue() method to return the text to renderer.
In your case you have two pieces of text to render and search, so you might be able to just change the getDisplayValue() method to return List of text you want to display.
Then the renderer can use both items in the List and the getNextMatch() method of the class would also be modified to check each item in the list for a match.
Related
my Main contains a conveyor, which transports a carton (my agent) from A to B. I added a radio button with which the user can choose the size of the box ("small", "medium", "big" & "very big"). I now want every carton to save the value of the radio button. I tried a lot of different stuff like linking it to a parameter, but I didn't manage to figure it out.
Picture of my model:
the code I used for the radio button is:
if( value == 0 )
radioValue = 1;
else if( value == 1 )
radioValue = 2;
else if( value == 2 )
radioValue = 3;
else if( value == 3 )
radioValue = 4;
radioValue being the parameter in the Main i linked my radio-button to.
How do I give this parameter to the agent and how do I read it out later?
Thanks in advance for helping!
in your Kist agent create a variable called size of type int.
in the source block, in the properties, on the "on at exit" action, under the action section of the properties write the following code:
agent.size=radioValue;
This is one of the most basic things to do in AnyLogic... so I suggest for you to go through a training before even starting to work on any model. This can be done by going through the tutorials, the anylogic in 3 days book or my course here: noorjax.teachable.com/p/anylogic
later you can use agent.size to access the size of your agent, in any of the blocks.
Without seeing more of the code, my general suggestion would be to consider looping through the agents (e.g., with a for loop) and having them all set a local variable cartSize equal to radioValue (I wouldn't use "size" because its also used for agentsets I believe). Just spitballing here, but something like this?
for (int x = 0; x < carton.size(); x++) {
carton.get(x).cartSize = radioValue;
}
For a Java Schoolproject I would like to have a table from witch you can select a Item that then shows up on a new window. In that window you can change things like ComboBoxes and others. My only problem is, that I dont know how to select the Item of the ComboBox I need. All the ComboBoxItems are Objects and I dont know how to handle this.
My ComboBoxItem looks like this:
Apprentice [person=Person, DB ID: 9, Kappa Kappa, Kappastrasse 21,
CityID: 4521, kappa.kappa#kappa.ch, idpersonen=9,
vertragsstart=2020-01-02, ausbildungsct=2, id=6]
Now, my Question is, how do I select the ComboBoxitem where the id=6, all the things I found needed the whole Object to select a special Item. How would you guys go at this problem?
Good luck and thanks for the Help.
Bono
All I had to do was a really simple while with a for and a if.
int trys = 0;
while (0 == apprenticeComboBoxZeugnis.getItemCount() && trys < 10000) {
System.out.println(apprenticeComboBoxZeugnis.getItemCount());
for (int i = 0; i < apprenticeComboBoxZeugnis.getItemCount(); i++) {
apprenticeComboBoxZeugnis.setSelectedIndex(i - 1);
int spacko = getApprenticeCombo();
if (spacko == lehrlingsid) {
TableFilterListenerZeugnis tableFilterListenerZeugnis = new TableFilterListenerZeugnis(
this);
tableFilterListenerZeugnis.updateNoten();
break;
}
}
trys++;
}
This first trys until the number of Objects is not = 0 and after that looks at every object, cuts out the id with getApprenticeCombo() and compares it with my id I allready have. If they match it breaks out and is done with it.
I have a simple interface that is designed to select one or more seats in a theater and reserve them for yourself.
I have three columns: zone / row / seat. You select the first to populate the second, and the second to populate the third.
When I select them the first time no problem.
If I change the second row, the third row re-populates (in this case all rows have the same number of seats) it does not break!
However if I change the first row everything breaks!
Now the reason for this is kinda clear, but I don't understand exactly why this is.
This is the first list event trigger:
List_Zona.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent arg0) {
if (! arg0.getValueIsAdjusting()){
RowListModel.clear(); // second list
SeatListModel.clear(); // third list
List_Rand.clearSelection(); // second list
List_Scaun.clearSelection(); // third list
int[] rows = self.repository.getRowsForZone(
List_Zona.getSelectedValue().toString()
);
int index = 0;
while (rows[index]!=0) {
RowListModel.addElement(String.valueOf(rows[index]));
index++;
}
}
}
});
It should clear the other column selections so it should not interfere with this next trigger (second column), but apparently it does, or something happens which I don't get:
List_Rand.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent arg0) {
if (! arg0.getValueIsAdjusting()){
SeatListModel.clear();
int[] seats = self.repository.getSeatByZoneAndRow(
List_Zona.getSelectedValue().toString(),
Integer.parseInt(List_Rand.getSelectedValue().toString())//HERE
);
int index = 0;
while (seats[index]!=0) {
SeatListModel.addElement(String.valueOf(seats[index]));
index++;
}
}
}
});
It can't parse the integer because the second column should be cleared, but it's not ? But even though it's not ... it is ?
What I'm trying to say: The second column should be clear (it's not) but if it's not then the error should not occur, but it does.
I hope this makes some sense!
Can anyone spot the problem ? Should I provide more code ?
The error is a NullPointerException at the second column, because something fishy is happening there (again: at the integer parsing).
By my mind the second column's valueChanged should not trigger at all when I click an item in the first column. It should just clear the other two and that's that. Why am I wrong ?
P.S. First Code snippet is responsible for the second one breaking the program.
Maybe I should also rephrase the question How can I safely clear everything when I re-select a new "Zone" (Zona) - Column one ?
The first listener clears the selection of List_Rand. That makes the selection change: it goes from "the index i is selected" to "no index is selected", so the second listener is invoked. And in the second listener, you're trying to call a method on the selected value of List_Rand. Since you just cleared the selection, there's no selected value anymore, hence the NullPointerException.
Side note: your code is very hard to read, because it doesn't respect the Java naming conventions. Variables start with a lowercase letter, and are camelCased (no underscore in their name).
Other side note : what's the point in calling parseInt(selectedValue.toString())? If the list contains Integer instances, the cast the value to Integer directly. If it contains String, then why not store Integers instead, since this is what you want the list to contain?
I am using a Bonded JComboBox. What I want to know is how do I check if that JComboBox has any items in it or not.
Thank you.
To test if the JComboxBox reference is null, you can compare it with null using the == operator. To test if the combo-box contains any items, you can use the instance method getItemCount, which returns the number of items it contains.
JComboxBox box = ...
boolean boxIsNull = (box == null); // answers the title of the question
boolean boxHasItems = (box.getItemCount() > 0);
I'm new to JTable.I'm working in Swings using JTable & Toplink(JPA). I have two buttons "add Row", "Del Row" and I have some records displayed from db. when ever "add row" is clicked a new record, row header should be added to JTable with an auto increment number displayed in sequential order to the JTable Row Header.
During deletion using "Del row " button the record has to be deleted & not its corresponding header so that next rows got updated to the previous headers & the auto increment number remain unchanged and always be in sequence.
please help me on this regard.
Thanks in advance,
Chandu
As you are new to JTable, I'd start with How to Use Tables. As suggested there, I'd extend AbstractTableModel, overriding getValueAt(), setValueAt(), getRowCount(), etc. to use the corresponding JPA entity and controller classes and methods. The NetBeans IDE, for example, can generate such classes automatically. There is also a feature to bind the classes to Swing components, including JTable and JList, but I haven't tried it.
If the row id is an auto increment number managed by the database, I'm not sure there's a reliable way to maintain the appearance of sequential order in a multi-user environment. If the field is displayed at all, isCellEditable() should probably return false for that column. Is that what you mean by Row Header?
Addendum: See also What’s the best way get the ID of the item just inserted?
Do you mean like this?
likeThis http://img705.imageshack.us/img705/8920/screenshot7ry.png
When a new record is added its id is set as a row header ( as in records, 1,2,3 ) and when a record is deleted, the row header remains, but the information is gone ( as in records 4,5 which use to have data, but after being removed only leave the id )
IF that's what you mean.
What you have to do is create two table models, one wrapping the other.
The only functionality of the wrapper will be to show an extra column ( the id ) and keep an internal "copy" of the data.
When a row is added, the wrapper will get a new record, it will assign a new id and then it will take all the fields and copy the value into his own data and then will forward it to the wrapped table model.
When a row is removed, the wrapper will not remove its own record, it will only clean up ( set to "" ) the column values and will keep the id column. Then it will forward the event to the wrapped column which in turn will actually remove the row.
Something like the following noncompiling-java
// Wrapper table model
class IdTableModel implements TableModelListener {
TableModel original;
// Analog to: Object[][]
List<List<Object> data = new ArrayList<List<Object>();
// will take a copy of the data in original
public IdTableModel( TableModel original ) {
this.original = original;
// fillData with values from original
for( int row = 0 ; row < original.getRowCount(); row++ ) {
List<Object> shadowRow = new ArrayList<Object>();
shadowRow.add( row ); // the id
// copy the values from original to this shadow
for( int column = 0 ; column < original.getColumnCount(); column++ ) {
shadowRow.add( original.getValueAt(row,i));
}
// add the shadow to the data
data.add( shadowRow );
}
original.addTableModelListener( this );
}
// for Object getValueAt( x, y ) get the data from your "data" not from the original
....
//Here's the magic. this wapper will be a listener of the original
// then this method will be invoked when the original gets more data
// or when it is removed.....
public void tableChanged( TableEvent e ) {
int row = e.getFirstRow();
List<Object> shadowRow = data.get( row);
switch( e.getType() ) {
case TableEvent.INSERT:
if( ( shadowRow =) == null ) {
// there wasn't shadow data at that position
data.add( ( shadowRow = new ArrayList<Object>()));
}
// takevalues from original
shadowRow.add( row ); // the id
for( int i = 0 ; i < original.getColumnCount();i++ ) {
shadowRow.add( original.getValueAt(row,i));
}
break;
case TableEvent.UPDATE:
// similar to insert, but you don't create a new row
// takevalues from original
for( int i = 0 ; i < original.getColumnCount();i++ ) {
shadowRow.set( i+1, original.getValueAt(row,i));
}
break;
case TableEvent.DELETE:
// You don't delete your shadow rows, but just clean it up
for( int i = 0 ; i < original.getColumnCount();i++ ) {
shadowRow.set( i+1, "");
}
break;
}
// forward calls to the original
public int getColumnCount(){
return original.getColumnCount()+1;
}
public String getColumnName( int columnIndex ) {
if( columnIndex == 0 ) {
return "id";
} else {
return original.getColumnName( columnIndex -1 );
}
}
// and so on for, isEditable etc. etc
}
Well that was much more code that what I initially wanted.
The idea is to have a table model wrapper that adds that fictional id column for you and don't delete it, you just use it like this:
JTable yourTable = new JTable( new IdTableModel( originalTableModel ));
If nothing of what I said make sense to you, start reading this: How to use tables
This page might be what you're looking for: http://www.chka.de/swing/table/row-headers/JTable.html