ObservableList<Message> to TableView

Hope I will get my question as clear as possible. I am working on a small java application using the JavaFX library for the gui. am doing a POP Connection and storing Messages as ObservableList. For this I am using javax.mail. I am passing this observablelist to a tableview and with the following i am passing the required values to the TableColumns:

        fromColumn.setCellValueFactory(
            new PropertyValueFactory<Message,String>("from")
        );
        subjectColumn.setCellValueFactory(
            new PropertyValueFactory<Message,String>("subject")
        );
        dateColumn.setCellValueFactory(
            new PropertyValueFactory<Message,String>("sentDate")
        );

Subject and sentDate are beeing read-in perfectly. But unfortunately "from" is adding object-references to TableColumn, since the From-Attribute in the Message-Class is a InternetAdress-Object and its toString()-method isnt returning a string but probably a reference. And the result is the follwoing being shown in fromColumn:

[Ljavax.mail.internet.InternetAddress;@3596cd38

Anybody knows the solution how I could get the String-Value of the InternetAdress being showed in the mentioned Column?

Thanks in Advance


I think you need to define a custom cell value factory to get at the address information in the format you need rather than using the PropertyValueFactory.

The following sample is for a read only table - if the message data in the table needs to be editable, then the solution will be significantly more complicated.

fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
    @Override public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
        // m.getValue() returns the Message instance for a particular TableView row
        return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
    }
});

Here is an executable sample (plus sample data files) which demonstrate use of the custom cell value factory. Place the sample data files in the same directory as the application java program and ensure your build system copies the sample files to the build output directory which contains the compiled class file for the application. You will need the javamail jar files on your path to compile and run the application.

import java.io.*;
import java.util.Arrays;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.mail.*;
import javax.mail.internet.MimeMessage;

public class MailTableSample extends Application {
  private TableView<Message> table = new TableView<Message>();
  public static void main(String[] args) { launch(args);}

  @Override public void start(Stage stage) {
    stage.setTitle("Table View Sample");

    final Label label = new Label("Mail");
    label.setFont(new Font("Arial", 20));

    table.setEditable(false);

    TableColumn subjectColumn = new TableColumn("Subject");
    subjectColumn.setMinWidth(100);
    subjectColumn.setCellValueFactory(
      new PropertyValueFactory<Message, String>("subject")
    );

    TableColumn sentDate = new TableColumn("Sent");
    sentDate.setMinWidth(100);
    sentDate.setCellValueFactory(
      new PropertyValueFactory<Message, String>("sentDate")
    );

    TableColumn fromColumn = new TableColumn("From");
    fromColumn.setMinWidth(200);
    fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
        @Override public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
          try {
            // m.getValue() returns the Message instance for a particular TableView row
            return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
          } catch (MessagingException ex) {
            Logger.getLogger(MailTableSample.class.getName()).log(Level.SEVERE, null, ex);
            return null;
          }
        }
    });    

    table.setItems(fetchMessages());
    table.getColumns().addAll(fromColumn, subjectColumn, sentDate);
    table.setPrefSize(600, 200);

    final VBox vbox = new VBox();
    vbox.setSpacing(5);
    vbox.setPadding(new Insets(10));
    vbox.getChildren().addAll(label, table);

    stage.setScene(new Scene(vbox));
    stage.show();
  }

  private ObservableList<Message> fetchMessages() {
    ObservableList<Message> messages = FXCollections.observableArrayList();
    try {
      Session session = Session.getDefaultInstance(System.getProperties());
      for (int i = 0; i < 3; i++) {
        InputStream mboxStream = new BufferedInputStream(
          getClass().getResourceAsStream("msg_" + (i+1) + ".txt")
        );
        Message message = new MimeMessage(session, mboxStream);
        messages.add(message);
      }
    } catch (MessagingException ex) {
      Logger.getLogger(MailTableSample.class.getName()).log(Level.SEVERE, null, ex);
    }

    return messages;
  }
}

msg_1.txt

From cras@irccrew.org  Tue Jul 23 19:39:23 2002
Received: with ECARTIS (v1.0.0; list dovecot); Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Return-Path: <cras@irccrew.org>
Delivered-To: dovecot@procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
    by danu.procontrol.fi (Postfix) with ESMTP id 434B423848
    for <dovecot@procontrol.fi>; Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
    id 175FA4C0A0; Tue, 23 Jul 2002 19:39:23 +0300 (EEST)
Date: Tue, 23 Jul 2002 19:39:23 +0300
From: Timo Sirainen <tss@iki.fi>
To: dovecot@procontrol.fi
Subject: [dovecot] first test mail
Message-ID: <20020723193923.J22431@irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 1
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce@procontrol.fi
Errors-to: dovecot-bounce@procontrol.fi
X-original-sender: tss@iki.fi
Precedence: bulk
X-list: dovecot
X-IMAPbase: 1096038620 0000010517
X-UID: 1                                                  
Status: O

lets see if it works

msg_2.txt

From cras@irccrew.org  Mon Jul 29 02:17:12 2002
Received: with ECARTIS (v1.0.0; list dovecot); Mon, 29 Jul 2002 02:17:12 +0300 (EEST)
Return-Path: <cras@irccrew.org>
Delivered-To: dovecot@procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
    by danu.procontrol.fi (Postfix) with ESMTP id 8D21723848
    for <dovecot@procontrol.fi>; Mon, 29 Jul 2002 02:17:12 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
    id 8BAD24C0A0; Mon, 29 Jul 2002 02:17:11 +0300 (EEST)
Date: Mon, 29 Jul 2002 02:17:11 +0300
From: John Smith <jsmithspam@yahoo.com>
To: dovecot@procontrol.fi
Subject: [dovecot] Dovecot 0.93 released
Message-ID: <20020729021711.W22431@irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 2
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce@procontrol.fi
Errors-to: dovecot-bounce@procontrol.fi
X-original-sender: tss@iki.fi
Precedence: bulk
X-list: dovecot
X-UID: 2                                                  
Status: O

First alpha quality release, everything critical is now implemented. From
now on it's mostly stabilization and optimization. Features that can't break
existing code could still be added, especially SSL and authentication stuff.

msg_3.txt

From cras@irccrew.org  Wed Jul 31 22:48:41 2002
Received: with ECARTIS (v1.0.0; list dovecot); Wed, 31 Jul 2002 22:48:41 +0300 (EEST)
Return-Path: <cras@irccrew.org>
Delivered-To: dovecot@procontrol.fi
Received: from shodan.irccrew.org (shodan.irccrew.org [80.83.4.2])
    by danu.procontrol.fi (Postfix) with ESMTP id F141123829
    for <dovecot@procontrol.fi>; Wed, 31 Jul 2002 22:48:40 +0300 (EEST)
Received: by shodan.irccrew.org (Postfix, from userid 6976)
    id 42ED44C0A0; Wed, 31 Jul 2002 22:48:40 +0300 (EEST)
Date: Wed, 31 Jul 2002 22:48:39 +0300
From: Timo Sirainen <tss@iki.fi>
To: dovecot@procontrol.fi
Subject: [dovecot] v0.95 released
Message-ID: <20020731224839.H22431@irccrew.org>
Mime-Version: 1.0
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
Content-Type: text/plain; charset=us-ascii
X-archive-position: 3
X-ecartis-version: Ecartis v1.0.0
Sender: dovecot-bounce@procontrol.fi
Errors-to: dovecot-bounce@procontrol.fi
X-original-sender: tss@iki.fi
Precedence: bulk
X-list: dovecot
X-UID: 3                                                  
Status: O

v0.95 2002-07-31  Timo Sirainen <tss@iki.fi>

    + Initial SSL support using GNU TLS, tested with v0.5.1.
      TLS support is still missing.
    + Digest-MD5 authentication method
    + passwd-file authentication backend
    + Code cleanups
    - Found several bugs from mempool and ioloop code, now we should
      be stable? :)
    - A few corrections for long header field handling

Sample program output: 带有邮件消息信息的示例TableView


Using the above mentioned solution, wether I use it as it is or I accept the advices of Eclipse i add a try/catch and a further return value, which looks like this at the end:

        fromColumn.setCellValueFactory(new Callback<CellDataFeatures<Message, String>, ObservableValue<String>>() {
        public ObservableValue<String> call(CellDataFeatures<Message, String> m) {
            // m.getValue() returns the Message instance for a particular TableView row
            try {
                return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
            } catch (MessagingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    });

The result is the same, I am getting a (visual) empty tableview. This means that even the tablecolumns are empty using this setCellFactury()-solution. Well, as workaround I could define a class where I could store al the three values as a String and then pass it to setCellValueFactory() using PropertyValueFactory, but I hope to get it done properly.

Any further advices?

best regards


This is a Java 8 version of jewelsea's solution but in awesome lambdas:

fromColumn.setCellValueFactory(m -> {
        // m.getValue() returns the Message instance for a particular TableView row
        return new ReadOnlyObjectWrapper<String>(Arrays.toString(m.getValue().getFrom()));
    }
});

Lol, gotta love lambdas

链接地址: http://www.djcxy.com/p/80138.html

上一篇: JavaFX,如何冻结TableView中某些列的位置

下一篇: ObservableList <Message>到TableView