1

希望我能尽可能清楚地回答我的问题。我正在使用用于 gui 的 JavaFX 库开发一个小型 Java 应用程序。我正在做一个 POP 连接并将消息存储为 ObservableList。为此,我使用 javax.mail。我将这个 observablelist 传递给一个 tableview,然后我将所需的值传递给 TableColumns:

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

Subject 和 sentDate 正在完美地读入。但不幸的是,“from”正在向 TableColumn 添加对象引用,因为 Message-Class 中的 From-Attribute 是 InternetAdress-Object 并且它的 toString() 方法不返回字符串,但可能返回引用。结果是 fromColumn 中显示的以下内容:

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

任何人都知道解决方案如何让 InternetAdress 的字符串值显示在提到的列中?

提前致谢

4

3 回答 3

1

我认为您需要定义一个自定义单元格值工厂以获取所需格式的地址信息,而不是使用 PropertyValueFactory。

以下示例是针对只读表的——如果表中的消息数据需要可编辑,那么解决方案将明显复杂得多。

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()));
    }
});

这是一个可执行示例(加上示例数据文件),它演示了自定义单元格值工厂的使用。将示例数据文件放在与应用程序 java 程序相同的目录中,并确保您的构建系统将示例文件复制到包含应用程序编译类文件的构建输出目录。您将需要路径上的javamail jar 文件来编译和运行应用程序。

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

示例程序输出: 带有邮件信息信息的示例 TableView

于 2012-11-01T21:31:16.813 回答
0

使用上面提到的解决方案,无论我是按原样使用它还是接受 Eclipse 的建议,我都会添加一个 try/catch 和一个进一步的返回值,最后看起来像这样:

        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;
        }
    });

结果是一样的,我得到一个(可视的)空表视图。这意味着即使使用此 setCellFactury() 解决方案,表格列也是空的。好吧,作为解决方法,我可以定义一个类,我可以在其中将所有三个值存储为字符串,然后使用 PropertyValueFactory 将其传递给 setCellValueFactory(),但我希望能正确完成。

有什么进一步的建议吗?

最好的祝福

于 2012-11-02T07:51:25.133 回答
0

这是 Jewelsea 解决方案的 Java 8 版本,但使用了很棒的 lambda:

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

大声笑,一定要喜欢 lambdas

于 2016-01-04T22:22:05.020 回答