我正在做一个java项目,其中我必须在JTable中显示一个使用jsoup从Web获取的文章列表。多行文本渲染器的问题并不新鲜,我已经在其他帖子中遇到过它(例如这个http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx)。但是在这个问题中,表是静态的,行数首先是固定的,并且保持不变。在我的项目中,初始行数为1,并在单元格(0,0)中编辑查询,表格应通过在新行中显示文章列表(包含标题,内容,数据和文章链接)来更新。 这是主类的代码:
public class ClientGrafico {
public static void main(String[] args) throws UnsupportedOperationException{
JTable table = new JTable();
table.setDefaultRenderer(String.class, new MultiLineTableCellRenderer1());
table.setModel(TabellaDati.getTabellaDati());
JFrame frame = new JFrame("TableDemo");
frame.add(new JScrollPane(table), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//display the window
frame.pack();
frame.setVisible(true);
}
}
这是MultiLineTableCellRenderer1类的代码:
public class MultiLineTableCellRenderer1 extends JTextArea
implements TableCellRenderer {
private ArrayList<ArrayList<Integer>> rowColHeight = new ArrayList<ArrayList<Integer>> ();
public MultiLineTableCellRenderer1() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(new EmptyBorder(1, 2, 1, 2));
}
if (value != null) {
setText(value.toString());
} else {
setText("");
}
adjustRowHeight(table, row, column);
return this;
}
/**
* Calculate the new preferred height for a given row, and sets the height on the table.*/
private void adjustRowHeight(JTable table, int row, int column) {
//The trick to get this to work properly is to set the width of the column to the
//textarea. The reason for this is that getPreferredSize(), without a width tries
//to place all the text in one line. By setting the size with the with of the column,
//getPreferredSize() returnes the proper height which the row should have in
//order to make room for the text.
int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth();
setSize(new Dimension(cWidth, 1000));
int prefH = getPreferredSize().height;
while (rowColHeight.size() <= row) {
rowColHeight.add(new ArrayList<Integer>(column));
}
ArrayList<Integer> colHeights = rowColHeight.get(row);
while (colHeights.size() <= column) {
colHeights.add(0);
}
colHeights.set(column, prefH);
int maxH = prefH;
for (Integer colHeight : colHeights) {
if (colHeight > maxH) {
maxH = colHeight;
}
}
if (table.getRowHeight(row) != maxH) {
table.setRowHeight(row, maxH);
}
}
}
这是表格模型的代码:
public class TabellaDati extends AbstractTabellaDati{
private EditListener listener;
private WriteListener listener1;
private String[] nomi_colonne;
private ArrayList<Article> dati;
public TabellaDati(){
nomi_colonne = new String[]{"Titolo","Articolo","Data","Link all'articolo"};
dati= new ArrayList<Article>();
listener = new EditListener(this);
listener1 = new WriteListener(this);
//for(int i=0;i <20; i++)
dati.add(new Article()); //aggiunta di un articolo vuoto per creare la prima riga della tabella
this.setValueAt("PRESS TO UPDATE", 0, 1);
}
public static AbstractTabellaDati getTabellaDati()
{
return new TabellaDati();
}
public void riempi_tabella (String token)
{
/*rimuove tutte le righe tranne la prima*/
int data_size = dati.size();
for(int k=1; k< data_size;++k)
dati.remove(1);
Document ciao = null;
estrazioneDati extr = new estrazioneDati();
try {
ciao=extr.connessione(token);
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<String> a1= extr.titoli_articoli(ciao);
ArrayList<String> a2= extr.parte_articoli(ciao);
ArrayList<String> a3= extr.data_notizia(ciao);
ArrayList<String> a4= extr.link_art(ciao);
for(int j=0;j<extr.return_count();j++)
this.addArticle(new Article(a1.get(j),a2.get(j),a3.get(j),a4.get(j)));
}
public void addArticle(Article c) {
this.dati.add(c);
}
public boolean isCellEditable(int rowIndex,int columnIndex)
{
if(rowIndex==0)
return true;
else
return false;
}
public int getRowCount()
{
return dati.size();
}
public int getColumnCount()
{
return nomi_colonne.length;
}
public String getColumnName(int columnIndex)
{
return nomi_colonne[columnIndex];
}
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public Object getValueAt(int rowIndex, int columnIndex){
Article ar = dati.get(rowIndex);
/*switch(columnIndex){
case(0):
return ar.getTitle();
case(1):
return ar.getContent();
case(2):
return ar.getDate();
case(3):
return ar.getLink();
default:
return null;
}*/
if(columnIndex==0)
return ar.getTitle();
else if(columnIndex==1)
return ar.getContent();
else if(columnIndex==2)
return ar.getDate();
else if(columnIndex==3)
return ar.getLink();
return null;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
Article ar = dati.get(rowIndex);
String str = (String)aValue;
/*switch(columnIndex){
case(0):
ar.setTitle(str);
break;
case(1):
ar.setContent(str);
break;
case(2):
ar.setDate(str);
break;
case(3):
ar.setLink(str);
break;
}*/
if(columnIndex==0)
ar.setTitle(str);
else if(columnIndex==1)
ar.setContent(str);
else if(columnIndex==2)
ar.setDate(str);
else if(columnIndex==3)
ar.setLink(str);
/*---Con TableModelListener---*/
TableModelEvent event = new TableModelEvent(this, rowIndex, rowIndex, columnIndex, TableModelEvent.UPDATE);
if(rowIndex+columnIndex==0)
listener.tableChanged(event);
/*---Con ChangeListener---*/
/*ChangeEvent event = new ChangeEvent(this);
if(rowIndex+columnIndex==0)
listener1.stateChanged(event);*/
}
public void addTableModelListener(TableModelListener l){
}
public void removeTableModelListener(TableModelListener l){
}
}
这是AbstractTabellaDati类的代码:
public abstract class AbstractTabellaDati implements TableModel{
/* Da utilizzare per creare oggetti (no costruttori) */
public static AbstractTabellaDati getTabellaDati() {
throw new UnsupportedOperationException("da implementare");
}
/* Restituisce true se la cella in posizione
(rowIndex,columnIndex) è modificabile. Deve restituire sempre true
per tutte le celle con rowIndex == 0 */
abstract public boolean isCellEditable(int rowIndex, int columnIndex);
}
这是类文章的代码:
public class Article {
private String title;
private String content;
private String date;
private String link;
public Article()
{
this("", "", "","");
}
public Article(String title, String content, String date, String link)
{
this.title = title;
this.content = content;
this.date = date;
this.link = link;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.date = link;
}
}
这是EditListener类的代码:
public class EditListener implements TableModelListener
/*per la gestione degli eventi tramite TableModelListener*/
{
private TabellaDati tab;
public EditListener(TabellaDati tab){
this.tab=tab;
}
public void tableChanged(TableModelEvent e) {
//if(e.getColumn() + e.getFirstRow() ==0) {
String keyword= tab.getValueAt(0,0).toString();
System.out.println(keyword);
tab.riempi_tabella(keyword);
//}
//TabellaDati.getTabellaDati();
}
}
这是类estrazioneDati的代码:
import org.jsoup.Jsoup;
import org.jsoup.nodes.*;
import java.io.IOException;
import java.util.ArrayList;
import org.jsoup.select.Elements;
public class estrazioneDati {
private int count;
private ArrayList<String> titolo_pronto;
private ArrayList<String> testo_articolo;
private ArrayList<String> dataEora;
private ArrayList<String> link_articolo;
public estrazioneDati(){
count=0;
titolo_pronto= new ArrayList<String>();
testo_articolo=new ArrayList<String>();
dataEora=new ArrayList<String>();
link_articolo=new ArrayList<String>();
}
public Document connessione(String richiesta) throws IOException
{
if(richiesta.equalsIgnoreCase("Sport")){
Document doc= Jsoup.connect("http://www.unionesarda.it/sport").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Sardegna")){
Document doc= Jsoup.connect("http://www.unionesarda.it/cronaca_sardegna").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Cronaca")){
Document doc= Jsoup.connect("http://www.unionesarda.it/cronaca_italiana").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Spettacolo")){
Document doc= Jsoup.connect("http://www.unionesarda.it/spettacoli_e_cultura").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Politica")){
Document doc=
Jsoup.connect("http://www.unionesarda.it/politica_italiana").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Esteri") || richiesta.equalsIgnoreCase("Estero")){
Document doc= Jsoup.connect("http://www.unionesarda.it/notizie_mondo").get();
return doc;
}
else if(richiesta.equalsIgnoreCase("Economia")){
Document doc= Jsoup.connect("http://www.unionesarda.it/notizie_economia").get();
return doc;
}
return null;
}
public ArrayList<String> titoli_articoli(Document doc)
{
Elements titoli=doc.select("[class^=box_elenco_titolo] > a");
for(Element titolo : titoli) {
titolo_pronto.add(titolo.attr("title"));
count ++;
}
return titolo_pronto;
}
public ArrayList<String> parte_articoli(Document doc)
{
Elements parte_articolo= doc.select("[class^=georgia font15 interlinea20]");
for(Element titolo : parte_articolo)
testo_articolo.add(titolo.text());
return testo_articolo;
}
public ArrayList<String> data_notizia(Document doc)
{
Elements data_ora= doc.select("span.ora_notizia");
for(Element time : data_ora)
dataEora.add(time.text());
return dataEora;
}
public ArrayList<String> link_art(Document doc)
{
Elements link=doc.select("[class^=box_elenco_titolo] > a");
for(Element colleg : link )
link_articolo.add(colleg.attr("href"));
return link_articolo;
}
public int return_count()
{
return count;
}
}
软件运行正常,但是我无法更新表格,以至于新行显示在ArrayList dati中显示dati,只要执行单元格(0,0)中的查询,就会更新。 有人有想法吗?
答案 0 :(得分:0)
我同意Jonathan的观点,我在代码中没有看到添加行的位置。
添加行后,尝试在代码中添加以下行。 tableModel.fireTableRowsInserted(tableData.size() - 1,tableData.size() - 1);
答案 1 :(得分:0)
如果我不使用自定义渲染器,那么该软件效果很好,但当然我无法获取单元格内的包装文本。所以问题似乎出现在自定义渲染器中,在这种情况下在MultiLineTableRenderer类中实现。使用自定义渲染器时,Jtable似乎不明白行的行数会改变。