12 Replies Latest reply: Jun 12, 2012 3:21 AM by 941623 RSS

    Conditionally update the list cell

    941623
      Is it possible to update the list cell based on a given condition?

      I was trying something like this, but it turns out that updateItem() is called later (and not when the Listview is updated from the ObservableList which i presumed)
       
       public class lCell extends ListCell<String> {
      ...
      @Override
      public void updateItem(String item, boolean empty) {
                  super.updateItem(item, empty);
                  label.setText(getItem());//hbox contains image & a label
                  System.out.println(item);
                  if (item != null && !isCurrentUser)
                    setGraphic(hbox);// Set the list cell as a hbox
                  else if (item!=null && isCurrentUser) 
                   setText(getItem()); //Set it as the message present in the ObservableList
                  
              }
      isCurrentUser is a "global" variable which changes it's value in a method (when another user - other than the one currently posting messages -enters the message)

      Is there a way to get an output like:

      <Image> User 1:
      msg1
      msg2
      msg3...
      <Image> User2:
      msg1
      msg2...
      <Image> User1:
      msgs...
        • 1. Re: Conditionally update the list cell
          JohnHendrikx
          It's even worse, those ListCells are temporary, so your check on that global variable is going to have different results next time the same contents must be displayed.

          You must make sure all the information that you need to render the ListCell the way you want it is present in the parameters to the updateItem call. You may need to create your own cell factory with ListCells that accept an object that contains both the messages + the user who created them, and then render the cell accordingly.

          Create a ListCell<UserMessage> for example, where UserMessage contains the user who typed the message and the message itself.
          • 2. Re: Conditionally update the list cell
            941623
            If you don't mind me asking could please tell me how to do this:
             >>You may need to create your own cell factory with ListCells that accept an object that contains both the messages + the user who created them, and then render the cell accordingly. 
            Preferably with an example.
            • 3. Re: Conditionally update the list cell
              JohnHendrikx
              Please read this tutorial about how to set a cell factoryl: http://docs.oracle.com/javafx/2/ui_controls/list-view.htm

              Then, instead of creating a ListView of Strings, create a ListView of UserMessage:
              ListView<UserMessage> list = new ListView<UserMessage>();
              Set the cell factory:
              list.setCellFactory(new Callback<ListView<UserMessage>, ListCell<UserMessage>>() {
                  @Override 
                  public ListCell<UserMessage> call(ListView<UserMessage> list) {
                     return new UserMessageCell();
                  }
              });
              And the cell class:
              public class UserMessageCell extends ListCell<UserMessage> {
                public void updateItem(UserMessage message, boolean empty) {
                  super.updateItem(message, empty);
              
                  if(!empty) {
                    // configure the cell here with your UserMessage object
                  }
                }
              }
              • 4. Re: Conditionally update the list cell
                941623
                Like you said, I created an object userMessage which has the username and the message. >>
                 public class userMessage {
                        private static String user;
                        private static String message;
                
                        public userMessage(String u, String m) {
                        this.user = u;
                        this.message=m;
                        }
                        public static String getUser() {
                        return user;
                        }       
                        public void setUser(String user) {
                        this.user = user;
                        }
                        public static String getMessage() {
                        return message;
                        }
                        public void setMessage(String message) {
                        this.message = message;
                        }
                }
                And my list cell class looks something like this:
                 public class lCell extends ListCell<userMessage> { 
                 @Override
                        public void updateItem(userMessage item, boolean empty) {
                            super.updateItem(item, empty);
                            if (item != null)
                            {
                                StringBuilder sb = new StringBuilder();
                                sb.append(item.getUser()).append(": \n").append(item.getMessage());
                                setText(sb.toString());
                            }
                }
                }
                Q). How do I add a <user name> and a <message> to the list?

                I thought, if i want a new message to be sent, i call a function add() which does the needful.>>
                public void add(String user, String message)
                {
                       userMessage um = new userMessage(user, message);
                       obs.addAll(um);
                }
                But it seems like the last known item (object) created over rides all the previous ones.

                so if for example I have:
                add(user1, Hi);
                add(user2, Hi!);
                add(user1, zzz); 
                The list view shows me:
                user1, zzz
                user1, zzz
                user1, zzz

                What do I do to prevent this? Do I have to create a different object every time? :\
                • 5. Re: Conditionally update the list cell
                  JohnHendrikx
                  You've declared your fields in your userMessage class with the 'static' keyword... which basically means something like 'global'...

                  So when you change the field, it changes for all the userMessage instances. Remove the static keyword, and it should be better:
                  public class UserMessage {
                          private String user;
                          private String message;
                   
                          public UserMessage(String u, String m) {
                          this.user = u;
                          this.message=m;
                          }
                          public String getUser() {
                          return user;
                          }       
                          public void setUser(String user) {
                          this.user = user;
                          }
                          public String getMessage() {
                          return message;
                          }
                          public void setMessage(String message) {
                          this.message = message;
                          }
                  }
                  ps. Java naming conventions recommends that you start class names with a capital letter, so "UserMessage" instead of "userMessage".

                  Good luck!
                  • 6. Re: Conditionally update the list cell
                    JohnHendrikx
                    You've declared your fields in your userMessage class with the 'static' keyword... which basically means something like 'global'...

                    So when you change the field, it changes for all the userMessage instances. Remove the static keyword, and it should be better:
                    public class UserMessage {
                            private String user;
                            private String message;
                     
                            public UserMessage(String u, String m) {
                            this.user = u;
                            this.message=m;
                            }
                            public String getUser() {
                            return user;
                            }       
                            public void setUser(String user) {
                            this.user = user;
                            }
                            public String getMessage() {
                            return message;
                            }
                            public void setMessage(String message) {
                            this.message = message;
                            }
                    }
                    ps. Java naming conventions recommends that you start class names with a capital letter, so "UserMessage" instead of "userMessage".

                    Good luck!
                    • 7. Re: Conditionally update the list cell
                      941623
                      Weird. Before it wouldn't run without static. (Can't call non static from static methods...).

                      Anyway, now it's working!!

                      And yes. I'll keep the naming of class convention different from that of variables.

                      Thanks a lot! :D
                      • 8. Re: Conditionally update the list cell
                        941623
                        How do I store the last used "username" so that it can be checked with the next incoming one?

                        Cause trying something like this, doesn't seem to work. >>

                        public class lCell extends ListCell<UserMessage> {
                               String userTemp="";
                        
                        @Override
                                public void updateItem(UserMessage item, boolean empty) {
                                  super.updateItem(item, empty);
                                    if (item != null)
                                     {
                                      StringBuilder sb = new StringBuilder();
                                      if (!userTemp.equals(item.getUser()))
                                      {
                                          sb.append(item.getUser()).append(": \n");
                                          userTemp=item.getUser();
                                      }
                                      sb.append(item.getMessage());
                                      setText(sb.toString());
                                    }
                                    
                                }
                        }
                        Wanted to print something like this:
                        User1:
                        msg1
                        msg2
                        msg3
                        User2:
                        msg1
                        msg2
                        User1:
                        ...

                        The above seems to print:
                        User1:
                        msg1
                        User1:
                        msg2
                        User1:
                        msg3
                        User2:
                        ...
                        • 9. Re: Conditionally update the list cell
                          JohnHendrikx
                          Donot do this in your Cell, that won't work (they are drawn in random order)....

                          Instead, when adding a new UserMessage, check if the previous one was of the same user... something like this:
                          UserMessage lastUserMessage = userMessages.get(userMessages.size() - 1);
                          
                          if(lastUserMessage.getUser().equals(currentUser)) {
                            lastUserMessage.append(message);
                          }
                          else {
                            userMessages.add(new UserMessage(currentUser, message));
                          }
                          • 10. Re: Conditionally update the list cell
                            941623
                            What is userMessages?
                            • 11. Re: Conditionally update the list cell
                              941623
                              Ok. userMessages is the ObservableList.

                              If I want to append more messages to the last user-message pair, first of all 'append' won't work in this object. So even if I create a function append in the UserMessage class:
                              public class UserMessage
                              {
                                      ....
                                      public void append(String message){
                                          this.message.concat("\n"+message);
                                      }
                              }
                              I would still need to add it (in the object format) to the ObservableList.
                              How would I reflect the above change (append) in the ObservableList?
                              ...
                              static currentUser=""; //global variable
                              ...
                              public void add(String user, String message)
                               {
                                     if(!user.equals(currentUser))
                                     {
                                         obs.add(new UserMessage(user, message));
                                         currentUser=user;
                                     }
                                     else
                                     {
                                         UserMessage lastUserMessage = obs.get(obs.size() - 1);
                                         lastUserMessage.append(message);
                                        //How do I reflect this change in the ObservableList?
                              
                                     }
                              }
                              • 12. Re: Conditionally update the list cell
                                941623
                                Got it. Got it.

                                Stupid error.>>
                                this.message=this.message.concat("\n"+message); 
                                Answer to my question:
                                ....
                                else
                                       {
                                           UserMessage lastUserMessage = obs.get(obs.size() - 1);
                                           lastUserMessage.add(message);
                                           obs.set(obs.size() - 1, lastUserMessage);//Answer
                                       }