JList pre/post rendering hook? - java

I am doing custom rendering in a JList. My custom ListCellRenderer uses a static String so that it can test the value of a particular variable against the previous occurance of that variable.
private static String lastUsername = "";
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
User user = (User)value;
if (lastUsername == user.getUsername()) {
// Do something
} else {
// Do something else
lastUsername = user.getUsername();
}
Now, that works fine when the program first loads but if I then scroll the list it causes problems as the lastUsername variable is still set to the last username it encountered when in fact it should be an empty string. Basically lastUsername needs to be reset to an empty string before or after all the cells have been rendered. Does anyone know if there is an JList post/pre AllCellsRendered event/hook that I can override to achieve this?

Common mistake to compare String objects with == instead of equals. Try if (lastUsername.equals( user.getUsername() )) instead.

Related

JList - `setListData()` causes `getSelectedValue()` to return null

When I create my JList I am able to use getSelectedValue() to print out the string I have selected in the list. As soon as I change what is inside the list everything that is returned is null.
When the list is created I have this:
matchList.setModel(new javax.swing.AbstractListModel<String>() {
String[] playerList = {"test"};
public int getSize() { return playerList.length; }
public String getElementAt(int i) { return playerList[i]; }
});
Later I change the JList to contain an array of strings:
matchList.setListData(Bracket.wr1);
Everything inside the array displays in the JList but if I try to use getSelectedValue() to get the String being displayed it just returns null.
What am I doing wrong?
It seems there is no selection anymore. According to the Oracle Documentation getSelectedValue()
[r]eturns null if there is no selection.
So if there is no default selection anymore, you should probably just set the first element as the default:
list.setSelectedIndex(0);

How can I use an array to validate an element length from another array?

I'm trying to create a file validator, so, import a csv file, check the contents, check each field isn't blank, then check the length of each field. If it's bigger than a specified value (different for each field), then I want to display it as a different colour, so that I can easily identify any fields that won't fit into my database.
I managed to read the file into an array, check that it's not null, and check the field length against a static value. I have another array containing the field sizes, but I can't seem to get cross reference dataArrayElement 0 with valaidateArrayElement 0.
I've got it outputting to a JTable, and displaying anything that hits "TOOBIG" in a different colour.
Integer[] validateLength = {8,2,22,11,25,13,6,2,34,11,35,35,34,11,1};
class checkValue{
public String validate(String value){
// Check to see if the cell is null or blank
if (StringUtils.isNullOrBlank(value)) {
return "EMPTY";
} else if (value.length() > 8) { //Work out how to set this as differing field lengths
return "TOOBIG";
}
else {
return "OK";
}
}
}
class CustomRenderer extends DefaultTableCellRenderer
{
private static final long serialVersionUID = 6703872492730589499L;
private checkValue cv = new checkValue();
public JComponent getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
JComponent cellComponent = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (cv.validate(table.getValueAt(row, column).toString()).equals("TOOBIG")){
cellComponent.setBackground(Color.RED);
cellComponent.setForeground(Color.YELLOW);
cellComponent.setToolTipText("Data is too big for the DB");
} else if(cv.validate(table.getValueAt(row, column).toString()).equals("EMPTY")){
cellComponent.setBackground(Color.GRAY);
cellComponent.setForeground(Color.WHITE);
cellComponent.setToolTipText("Field is empty in import file!");
} else {
cellComponent.setBackground(Color.WHITE);
cellComponent.setForeground(Color.BLACK);
}
return cellComponent;
}
}
Any help on this would be appreciated!
Thanks
You can pass index of your data element in validate method and check corresponding value from validateLength
Integer[] validateLength = {8,2,22,11,25,13,6,2,34,11,35,35,34,11,1};
public String validate(String value, int index){
// Check to see if the cell is null or blank
if (StringUtils.isNullOrBlank(value)) {
return "EMPTY";
} else if (value.length() > validateLength[index]) {
return "TOOBIG";
}
else {
return "OK";
}
}
And while calling this method pass the index (assuming values to validate are across columns)
validate(table.getValueAt(row, column).toString(), column);
Hope this helps

Validating user input in JTextFields (Java)

I am trying to validate user input into text boxes. I am checking whether the text box is populated or not and if it's not I need to alert the user to which text box isn't populated. My problem is that I need a way of returning which text box / variable is empty. I am aware I will need to pass 2 values in, one being the content of the text box and the other, an identifier of the text box.
Currently I have this (found on StackOverflow) which checks if each variable in the array is populated.
public boolean areAllNotEmpty(String... text){
for(String s : text) {
if(s == null || "".equals(s)) {
return false;
}
}
return true;
}
I would like it to also return something like this (commented):
public boolean areAllNotEmpty(String... text){
for(String s : text) {
if(s == null || "".equals(s)) {
// return textbox name / value OR show alert box with "Forename missing" etc
return false;
}
}
return true;
}
I implemented this method before on a C# project but it requires passing in one text box at a time with multiple method calls which I'm guessing isn't great.
public static bool IsFieldNull(TextBox currentText, string type)
{
bool allOk = false;
if (currentText.Text == "")
{
MessageBox.Show("Error - '" + type + "' field cannot be left blank, please enter some data in this field");
currentText.Focus();
return allOk;
}
else
{
allOk = true;
return allOk;
}
This is how it is called in C#.
Validation.IsFieldNull(txtBoxFixtureDate, "Fixture Date") && Validation.IsFieldNull(txtBoxTime, "Time")
If any of that doesn't make sense, let me know.
Thanks for any help.
You could pass the components to the method and return ones that are empty like this:
public List<JTextField> getEmptyFields(JTextField... textFields) {
List<JTextField> emptyFields = new ArrayList<JTextField>();
for (JTextField field : textFields) {
if (field.getText().isEmpty()) {
emptyFields.add(field);
}
}
return emptyFields;
}
Then you can just check the size() of the returned list to determine if there was an empty field and deal with them accordingly.
It's not pretty useful to validate when a submit button is pressed, it's better to validate when the error is happening. You may consider using InputVerifier . Then you know when it's in valid state or not. Apart from that if you are using java7 or above you could take a look to JLayer to decorate components which are not in valid state. See here for more examples Decorate components with JLayer.

How to update JList while adding or removing elements with using DefaultListModel()

i know this question asked many times before. However, i spent on hours to research about a way to update a JList, and i couldn't handle with this issue. I'm trying to implement a JList which shows who is online or offline.(It holds JLabels i guess this is the only way for holding a string with an icon). I have my own CellRenderer() which is like;
public class UserRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,int index, boolean isSelected, boolean hasFocus) {
if(value instanceof ClientObject){
final ClientObject clientObject = (ClientObject) value;
JLabel label = (JLabel) super.getListCellRendererComponent(list, clientObject.getNickName(), index, isSelected, hasFocus);
if(clientObject.isIsOnline()){
label.setIcon(iconArray[1]);
}
else{
label.setIcon(iconArray[0]);
}
return label;
}
else {
return super.getListCellRendererComponent(list, value, index, isSelected, hasFocus);
}
}
}
Moreover, i construct client's list whenever he/she gets connected to server with this way;
private void buildBuddyList(ClientObject tempClientObject){
if( tempClientObject.getBuddyList().size() > 0 ){
mainClient.setBuddyList(tempClientObject.getBuddyList());
for (Iterator<ClientObject> iter = mainClient.getBuddyList().iterator(); iter.hasNext();) {
ClientObject tempon = iter.next();
if(tempon.isIsOnline()){
model.addElement(tempon);
labelIconList.put(tempon, iconArray[1]);
}
else{
model.addElement(tempon);
labelIconList.put(tempon, iconArray[0]);
}
}
}
}
The trick which i use when a client changed his/her status (becomes online/offline) is i get rid off all elements with model.clear() and start to construct the list again. Here is the code segment;
if(tempClientObject.isStatusChanged()){
if(tempClientObject.isIsConnected()){
System.out.println(tempClientObject.getUserName() + " is ONLINE");
model.clear();
for (Iterator<Map.Entry<ClientObject,ImageIcon>> iter = labelIconList.entrySet().iterator(); iter.hasNext();) {
Map.Entry<ClientObject,ImageIcon> pairs = iter.next();
ClientObject changedOnlineStatusClient = (ClientObject) pairs.getKey();
if(changedOnlineStatusClient.getUserName().equals(tempClientObject.getUserName())){
changedOnlineStatusClient.setIsOnline(tempClientObject.isIsOnline());
}
model.addElement(changedOnlineStatusClient);
}
}
else{
System.out.println(tempClientObject.getUserName() + " is OFFLINE");
model.clear();
for (Iterator<Map.Entry<ClientObject,ImageIcon>> iter = labelIconList.entrySet().iterator(); iter.hasNext();) {
Map.Entry<ClientObject,ImageIcon> pairs = iter.next();
ClientObject changedOnlineStatusClient = (ClientObject) pairs.getKey();
if(changedOnlineStatusClient.getUserName().equalsIgnoreCase(tempClientObject.getUserName())){
changedOnlineStatusClient.setIsOnline(tempClientObject.isIsOnline());
}
model.addElement(changedOnlineStatusClient);
}
}
}
I can assure that logical system works fine.(I can check the actions if they are working properly on background). Only the problem is sometimes when a client connected to server JList looks blank even though it adds elements into model. i will appreciate for every answer. And thanks anyway
only comment, not an answer
there no require for one dimensional JList
if(value instanceof ClientObject){
because Object from
getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean hasFocus) {
returns the same value, then to test this value if == or equeals ...
First of all thanks for all your replies. On the other hand, i corrected my issue with creating a new model whenever it has to be get updated. So the code segment is like this;
DefaultListModel tempModel = new DefaultListModel();
// add or remove elements from tempModel
buddyList.setModel( tempModel );
i'm not sure about if it is the only correct way but at least it works.
Call model.fireContentsChanged() method.
JavaDoc on AbstractListModel

java-how to check a list of textField with a loop validation function

i want to check a list of textfield with a validation loop function
if anyone can explain me how to do this thks ;)
i do this :
public void validation()
{
List<String> list = new ArrayList<>();
list.add("LastNameTextField");
list.add("nameTextField");
list.add("ageTextField");
list.add("AdressTextField");
list.add("PhoneTextField1");
for(String check :list )
{
if(validator((check.toString()).toString()))
/*here i just want to get the field name and this value */
JOptionPane.showMessageDialog(null, check+ " Empty value");
}
}
public static boolean validator(String TextFieldTextToCheck)
{
if ((TextFieldTextToCheck== null) || (TextFieldTextToCheck.length() == 0)) {
return true ;
}
else return false;
}
i dont find the way to get the field value if anyone can help
thank you for your time
For the record, I don't have allot of Java experience. If I understand correctly, you are trying to validate the contents of several TextFields in a GUI. And the validation only makes certain that the textfield is empty. I would recommend that instead of using a collection of the textField names, you simply use a collection of references to the textfields you wish to validate.
So your ArrayList is populated with textfield references instead:
ArrayList<TextField> textFields = new ArrayList<TextField>();
textFields.add(textbox1);
textFields.add(textbox2);
textFields.add(textbox3);
textFields.add(textbox4);
You iterate through the ArrayList like before. I used a System.Out call for my own testing.:
for(TextField textField : textFields) {
if(validateTextField(textField)) {
//JOptionPane.showMessageDialog(null, textField.getText() + " Empty value");
System.out.println(textField.getName() + " has an Empty value");
}
}
The validate function now looks like this. I added a test for a NULL reference, but you could leave that out.:
public static boolean validateTextField(TextField textField) {
if(textField == null) throw new NullPointerException("The validate function received a null textfield reference. Check your loop.");
return textField.getText().length() == 0;
}
Your if condition is incorrect.
if(validator((check.toString()).toString()))
It should be corrected as:
if(YourClass.validator(check))
Explanation:
check is already String. There is not need to call toString() on it.
validator method is a static method so call it in static way as YourClass.validator where YourClass is your class name.
validator method return boolean and if expects boolean so no need to get a String again.

Categories