基本思路,左侧一个JTree,右侧一个JTable,JTable的第一列为Filename。使用TableCellRenderer重绘Filename列,使得此列由一个JLable与一个JTextFiled组成。
代码运行的第一个界面,显示正常,达到预期效果,如图:
可当点击左侧树节点,进入其它文件夹(其实就是改变了JTable的数据)后,Filename就显示不出来了,如图:
有没有好心人帮忙分析下怎么回事啊?代码随后附上ps:如果不加TableCellRenderer的话,展开/收缩左侧树是没问题的。
ps2:我就20分了,千万别嫌少,不够的话您说,俺去打工挣……

解决方案 »

  1.   

    PART1:
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.Toolkit;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Vector;import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JSplitPane;
    import javax.swing.JTable;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.JTree;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.ToolTipManager;
    import javax.swing.UIManager;
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.TitledBorder;
    import javax.swing.event.TableModelEvent;
    import javax.swing.event.TableModelListener;
    import javax.swing.event.TreeExpansionEvent;
    import javax.swing.event.TreeExpansionListener;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeCellRenderer;
    import javax.swing.tree.TreePath;public class MainFrame extends JFrame {    DefaultTableModel ttm=null;
    JTable tt=new JTable(ttm);
    public static void main(String[] args) {
    MainFrame mf = new MainFrame();
    } public MainFrame() {
    GUIInit();
    } private void GUIInit() {
    this.setVisible(true);
    this.setTitle("explorer");
    this.setSize(new Dimension(Toolkit.getDefaultToolkit()
    .getScreenSize()));
    this.getContentPane().setLayout(new BorderLayout());
    this.setBackground(Color.lightGray); //初始化左侧目录导航树
    initLeftTree();
    jScrollPaneLeft.setPreferredSize(new Dimension(400, 400));
    jScrollPaneLeft.getViewport().add(jTree, null); //初始化右侧显示table
    ttm=new FileDeafaultTableModel("");
    jScrollPaneRight.getViewport().add(tt,null);
    tt.setModel(ttm);
    tt.setShowGrid(false);
    tt.setBackground(Color.lightGray); tt.getModel().addTableModelListener(new TableModelListener(){
    public void tableChanged(TableModelEvent e) {
    System.out.println("tableChanged");
    }
    }); //给右侧table的第一列添加TableCellRenderer。如果将此行注释,JTable显示无异常。
    initializeFilenameColumn(); jSplitPane.add(jScrollPaneLeft, JSplitPane.TOP);
    jSplitPane.add(jScrollPaneRight, JSplitPane.BOTTOM);
    jSplitPane.setDividerLocation(200);
    jSplitPane.setDividerSize(3);
    jSplitPane.setOneTouchExpandable(true);
    this.getContentPane().add(jSplitPane, BorderLayout.NORTH);
    jl=new JLabel("NOTE:");
    this.getContentPane().add(jl, BorderLayout.SOUTH);
    addMenuBar();
    this.pack();
    this.show();
    } private TableCellRenderer render = new FilenameRenderer();
    private void initializeFilenameColumn(){
    TableColumn filenameColumn=tt.getColumn("FILENAME");
    filenameColumn.setCellRenderer(render);
    Dimension ps=((JPanel)render).getPreferredSize();
    tt.setRowHeight(ps.height);
    } private void initLeftTree() {
    root = new FileMutableTreeNode("");
    root.expands(root);
    treeModel = new DefaultTreeModel(root);
    jTree = new JTree(treeModel);
    registerTreeListener();
    } /**
     * 左侧导航树的鼠标事件
     * 当双击树上某节点(其实就是某个目录)时,右侧的表格会显示此目录下的文件
     */
    private void registerTreeListener() {
    jTree.addTreeExpansionListener(new TreeExpansionListener() {
    public void treeCollapsed(TreeExpansionEvent tee) {
    TreePath treePath = tee.getPath();
    FileMutableTreeNode fileNode = (FileMutableTreeNode) treePath.getLastPathComponent();
    tt.removeAll();
    ((FileDeafaultTableModel)tt.getModel()).changeData(fileNode.filepath);
    } public void treeExpanded(TreeExpansionEvent tee) {
    TreePath treePath = tee.getPath();
    FileMutableTreeNode fileNode = (FileMutableTreeNode) treePath
    .getLastPathComponent();
    DefaultTreeModel model = (DefaultTreeModel) jTree.getModel(); jl.setText("explore...");
    if (!fileNode.isExplore()) {
    fileNode.expands(fileNode);
    model.nodeStructureChanged(fileNode);
    new UpdateStatus(fileNode.filepath).start();
    } tt.removeAll();
    ((FileDeafaultTableModel)tt.getModel()).changeData(fileNode.filepath);
    //下面这几句加不加效果都一样
    // initializeFilenameColumn();
    // tt.getColumn("FILENAME").setCellRenderer(new FilenameRenderer());
    // tt.repaint();
    } class UpdateStatus extends Thread{
    private String text;
    public UpdateStatus(String text){
    this.text=text;
    }
    public void run(){
    try{
    Thread.sleep(300);
    }catch(Exception e){
    e.printStackTrace();
    }
    SwingUtilities.invokeLater(new Runnable(){
    public void run(){
    jl.setText(text);
    }
    });
    }
    } });
    } /**
     * 获取某目录下的子目录和文件
     * @param filePath
     * @return
     */
    private ArrayList getSystemDriverList(String filePath) {
    File[] drivers = new File[] {};
    int driversNum = 0;
    if (filePath == "") {
    drivers = File.listRoots();
    } else {
    drivers = (new File(filePath)).listFiles();
    } try{
    driversNum = drivers.length;
    }catch (Exception e){
    System.out.println("Can't access");
    }
    ArrayList al = new ArrayList(driversNum);
    for (int i = 0; i < driversNum; i++) {
    if(!drivers[i].isDirectory()) continue;
    FileMutableTreeNode tempNode=new FileMutableTreeNode(drivers[i]);
    al.add(tempNode );
    }
    return al;
    } /**
     * 菜单栏,基本未实现
     */
    private void addMenuBar() {
    exitItem.setEnabled(true);
    fileMenu.add(exitItem);
    fileMenu.setEnabled(true);
    menuBar.add(fileMenu);
    this.setJMenuBar(menuBar);
    }
      

  2.   

    PART2:
    /**
     *自己的 TableCellRenderer,基本思路是重绘右侧table的第一列(即FILENAME列)
     *由一个JLabel和一个JTextField组成
     */
    class FilenameRenderer extends JPanel implements TableCellRenderer{
    private JTextField jtf=new JTextField();
    private JLabel jl =new JLabel("ICON");
    private Component glue = Box.createHorizontalGlue();
    int i=0;
        private Color unselectedForeground;
        private Color unselectedBackground;     String temp;
    public FilenameRenderer(){
    // super();     jtf.setBorder(BorderFactory.createEtchedBorder());
        jl.setBorder(BorderFactory.createEtchedBorder());
        jtf.setOpaque(true);
        jl.setOpaque(true);
    jl.setHorizontalAlignment(JLabel.LEFT);
    jtf.setHorizontalAlignment(JLabel.CENTER);
    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    this.add(jl,BorderLayout.WEST);
    this.add(jtf,BorderLayout.CENTER);
    //   jl.setIcon(new Icon();
    } public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelect,
                                           boolean hasFocus,int row,int col){
    setOpaque(false);
    jtf.setVisible(true);
    jl.setVisible(true);
        jtf.setOpaque(true);
        jl.setOpaque(true); temp=(String)table.getValueAt(row,col);
    setFont(table.getFont()); jtf.setText((String)table.getValueAt(row,col)); Component c[]=this.getComponents();
    setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, table.getBackground()));
    for (int k=0;k<c.length;k++){
    if (c[k] instanceof JLabel){
    ((JLabel)c[k]).setHorizontalAlignment(SwingConstants.LEFT);
    ((JLabel)c[k]).setAlignmentX((float)0.0);
    ((JLabel)c[k]).setOpaque(true);
    ((JLabel)c[k]).setForeground(Color.DARK_GRAY);
    System.out.println("isLabel == "+((JLabel)c[k]).getText());
    }
    if (c[k] instanceof JTextField){
    ((JTextField)c[k]).setHorizontalAlignment(SwingConstants.LEFT);
    ((JTextField)c[k]).setAlignmentX((float)0.0);
    ((JTextField)c[k]).setOpaque(false);
    ((JTextField)c[k]).setForeground(Color.DARK_GRAY);
    System.out.println("isTextField == "+((JTextField)c[k]).getText());
            table.setValueAt(((JTextField)c[k]).getText(),row,col);
    }
    }
        add(glue);
        add(jl);
        add(jtf);
    // SwingUtilities.updateComponentTreeUI(this);
    // super.updateUI();
    // this.updateUI();
    // super.show();
    // this.show();
    return this;
    }
    protected void setValue(Object value){
    jtf.setText(value.toString());
    }
    } /**
     * 左侧导航树树节点
     */
    class FileMutableTreeNode extends DefaultMutableTreeNode {
    private String filepath; private String filename; private File currentFile; private FileMutableTreeNode currentNode; boolean isExplore = false; public FileMutableTreeNode(String filepath) {
    this.filepath = filepath;
    }
    public boolean isLeaf() {
    if (filepath == "") {
    return false;
    } else {
    return (!(new File(filepath)).isDirectory());
    }
    }
    /**
     *
     */
    public void expands(FileMutableTreeNode currentNode) {
    if (currentNode == null) {
    System.out.println("currentFile==null return");
    return;
    } else {
    this.currentNode = currentNode;
    } if (!isExplore) {
    ArrayList al = getSystemDriverList(currentNode.filepath);
    for (int i = 0; i < al.size(); i++) {
    currentNode.add((FileMutableTreeNode) al.get(i));
    }
    isExplore = true;
    }
    } public FileMutableTreeNode(File file) {
    this.filename = file.toString();
    this.filepath = file.getPath();
    this.currentFile = file;
    } /**
     * @return
     */
    public boolean isExplore() {
    return isExplore;
    } public String toString() {
    if (filename == null) {
    return "comp";
    } else {
    int index=filename.lastIndexOf("\\");
    return (index!=-1&&index !=filename.length()-1)?filename.substring(index+1):filename;
    }
    }
    } /**
     * 右侧table模型
     */
    class FileDeafaultTableModel extends DefaultTableModel implements TableModelListener{
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 3258415023478355249L;
    String filePath;
    File[] files;
    Object[][] data;
        String[] columnName;
    public FileDeafaultTableModel(String filePath){
    this.filePath=filePath;
    initT();
    } private void initT(){
    if(filePath==""||filePath==null){
     files=File.listRoots();
    }else {
    files=new File(filePath).listFiles();
    }
    columnName= new String[]{"FILENAME", "ISDIRECTORY", "LAST MODIFY DATE",};
    data=new Object[files.length][columnName.length];
    for (int i=0;i<files.length;i++){
    if(files[i].getName().equalsIgnoreCase("")){
    data[i][0]=files[i].toString();
    }else{
    data[i][0]=files[i].getName();
    }
    data[i][1]=String.valueOf(files[i].isDirectory());
    data[i][2]=new Date(files[i].lastModified());
    }
    } public Object getValueAt(int row,int col){
    return data[row][col];
    }
    public int getRowCount(){
    if(data==null){
    return 0;
    }else{
    return data.length;
    }
    }
    public int getColumnCount(){
    if(data==null){
    return 0;
    }else{
    return columnName.length;
    }
    }
    public String getColumnName(int col){
    return columnName[col];
    }
    public Class getColumnClass(int col){
    return data[0][col].getClass();
    }
    public void setValueAt(Object value,int row,int col){
    data[row][col]=value;
    }
    public boolean isCellEditable(int row,int col){
    Class cls=getColumnClass(col);
    String name=getColumnName(col);
    return name=="FILENAME";
    }
    public void changeData(String filePath){
    this.filePath=filePath;
    initT();
    } public void tableChanged(TableModelEvent e) {
    System.out.println("tableChanged2");
    }
    }
    /**
     * 抽象状态树根结点
     */
    protected FileMutableTreeNode root;// = new DefaultMutableTreeNode("root"); /**
     * 抽象状态树模型
     */
    protected DefaultTreeModel treeModel;// = new DefaultTreeModel(root); /**
     * 抽象状态树
     */
    protected JTree jTree;// = new JTree(treeModel); private JMenuBar menuBar = new JMenuBar(); private JMenu fileMenu = new JMenu("File"); private JMenuItem exitItem = new JMenuItem("Exit"); private JSplitPane jSplitPane = new JSplitPane(); private JScrollPane jScrollPaneLeft = new JScrollPane(); private JScrollPane jScrollPaneRight = new JScrollPane(); private JLabel jl=new JLabel(); private JPanel jp=new JPanel(); private DefaultTableModel fileTableModel;//=new DefaultTableModel();
    private JTable fileTable=new JTable();
    private ArrayList tableFileList=new ArrayList();
    }
      

  3.   

    有什么错误没有?debug看一下展开时第一列是否有数据
      

  4.   

    没有Exception。展开时是确实有数据的
    我怀疑是图像绘制的问题
      

  5.   

    windows xp homeediton service pack 2java version "1.7.0-ea"
    Java(TM) SE Runtime Environment (build 1.7.0-ea-b17)
    Java HotSpot(TM) Client VM (build 1.7.0-ea-b17, mixed mode, sharing)