?
Solved

Don't want cells in a JTable to receive focus

Posted on 2003-03-21
17
Medium Priority
?
281 Views
Last Modified: 2007-12-19
In a class that extends JTable, I am creating a table that uses a DefaultTableModel.  I need this table to be dynamic so I can load files and add records that are stored in those files and then allow the user to add records at runtime (all of this works).  My question is...how can I get the cells to not receive focus?  What I'm trying to do is receive a double click action.  The double click works, but ONLY if you double click on the "cell separators" - because when you double click on a cell, the first click gives focus to the cell so a double click on a cell isn't possible.

Below is the code I am currently using (again, this works fine, but double clicking doesn't work too well):
-----------------------------------------
setPreferredScrollableViewportSize(new Dimension(750, 550));
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
setRowSelectionAllowed(true);

dtm = new DefaultTableModel(columnNames, 0);

TableSorter sorter = new TableSorter(dtm);
sorter.addMouseListenerToHeaderInTable(this);

//addMouseListener(this);
addMouseListener(new MouseAdapter() {
     public void mouseClicked(MouseEvent e) {
          if (e.getClickCount() == 2) {
               System.out.println("double click");
          }
     }
} );

setModel(sorter);
-----------------------------------------

I found that I could use an AbstractTableModel to do what I want - but then it doesn't look like an ATM can give a dynamic table.

Thanks!

Chris

p.s. - sorry about the points - this is all i have left!  If this turns out to be kinda difficult, I will give you more points when I get some :)
0
Comment
Question by:ctjoumas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 6
17 Comments
 
LVL 9

Accepted Solution

by:
Ovi earned 75 total points
ID: 8181000
Try this (you will need to images: file.gif and folder.gif in the same directory as your classes):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

public class FileSystemView extends JFrame {
  private SystemView table;

  public FileSystemView() {
    getContentPane().setLayout(new BorderLayout());
    setSize(400, 300);
    setLocation(300, 100);
    table = new SystemView();
    getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
    setVisible(true);
  }

  class SystemView extends JTable {
    SystemViewModel model;

    public SystemView() {
      model = new SystemViewModel();
      setAutoCreateColumnsFromModel(false);
      loadDirectory("c:");
      setModel(model);
      createColumns();
      setGridColor(Color.white);
      setForeground(Color.black);
      setBackground(Color.white);
      setSelectionBackground(Color.black);
      setSelectionForeground(Color.white);
      addMouseListener(new TableMouseAdapter(this, model));
    }

    protected void loadDirectory(String dir) {
      Vector v = new Vector();
      File f = new File(dir);
      File[] files = f.listFiles();
      for(int i = 0; i < files.length; i++) {
        FileElement fe = new FileElement();
        fe.setFile(files[i]);
        v.addElement(fe);
      }
      model.addData(v);
    }

    protected void loadDirectory(File f) {
      Vector v = new Vector();
      File[] files = f.listFiles();
      for(int i = 0; i < files.length; i++) {
        FileElement fe = new FileElement();
        fe.setFile(files[i]);
        v.addElement(fe);
      }
      model.addData(v);
    }

    protected void createColumns() {
      for(int i = 0; i<model.cols.length; i++) {
        DefaultTableCellRenderer renderer = new FileRenderer();
        renderer.setHorizontalAlignment(model.cols[i].alignment);
        TableColumn column = new TableColumn(i, model.cols[i].width, renderer, null);
        setFont(new Font ("MicrosoftSanSerif", Font.PLAIN, 12));
        addColumn(column);
      }
    }
  }

  class TableMouseAdapter extends MouseAdapter {
    SystemView table;
    SystemViewModel model;
    public TableMouseAdapter(SystemView t, SystemViewModel m){table = t;model = m;}
    public void mouseClicked(MouseEvent e) {// simple update the path
      if(e.getClickCount()==2) {//execute the LS (or the program in the next future)
        int row = table.getSelectedRow();
        File file = model.getFileAt(row);
        if(file.isDirectory())
          table.loadDirectory(file);
        return;
      }
    }
  }

  class SystemViewModel extends AbstractTableModel {
    protected ColumnDescriptor cols[] =  {
      new ColumnDescriptor("Name", 40, JLabel.LEFT),
      new ColumnDescriptor("Size", 50, JLabel.LEFT),
    };
    protected Vector fileObjects;

    public SystemViewModel() {
      fileObjects = new Vector();
    }

    public void addData(Vector v) {
      fileObjects.removeAllElements();
      for(int i = 0; i<v.size(); i++) {
        fileObjects.addElement(v.elementAt(i));
      }
      updateObjects();
    }
    public File getFileAt(int row) {return(((FileElement)fileObjects.elementAt(row)).file);}
    protected void updateObjects() {fireTableDataChanged();}
    public int getColumnCount() {return(cols.length);}
    public int getRowCount() {return(fileObjects.size());}
    public String getColumnName(int c) {return(cols[c].name);}

    public Object getValueAt(int row, int col) {
      if(getRowCount() <= 0)
        return "";
      if(row<0||row>=getRowCount())
        return "";
      Object o = fileObjects.elementAt(row);
      if(o instanceof FileElement) {
        FileElement fd = (FileElement) o;
        switch(col) {
          case 0: return fd.getName();
          case 1: return new Long(fd.getSize());
        }
      }
      return "";
    }

    class ColumnDescriptor {
      public String name;public int width;public int alignment;
      public ColumnDescriptor(String n, int w, int a) {name = n;width = w;alignment = a;}
    }
  }

  class FileUI {
    public ImageIcon icon = null;private String fileName;
    public FileUI(ImageIcon img, String fn) {icon = img;fileName = fn;}
    public String getFileName() {return(fileName);}
    public String toString() {return(fileName);}
  }

  public class FileElement {
    private File file;
    private long size;
    private FileUI name = null;

    public FileElement() {}

    public void setFile(File f) {
      ImageIcon icon = null;
      file = f;
      if(f.isDirectory())
        icon = new ImageIcon(FileSystemView.this.getClass().getResource("folder.gif"));
      else
        icon = new ImageIcon(FileSystemView.this.getClass().getResource("file.gif"));
      name = new FileUI(icon, f.getName());
      long size = f.length();
    }

    public long getSize() {return(size);}
    public FileUI getName() {return (name);}
    public boolean isDirectory() {return(file.isDirectory());}
  }

  public class FileRenderer extends DefaultTableCellRenderer {
    public void setValue(Object cell) {
      setFont(new Font ("MicrosoftSanSerif", Font.PLAIN, 12));
      if(cell instanceof FileUI) {
        FileUI fui = (FileUI)cell;
        setIcon(fui.icon);
        setText(fui.getFileName());
        setToolTipText(fui.getFileName());
      }
      else {
        super.setValue(cell);
        setToolTipText(cell.toString());
      }
    }
  }
  public static void main(String[] args) {FileSystemView t = new FileSystemView();}
}
0
 

Author Comment

by:ctjoumas
ID: 8181677
Hmm... basically, the SystemViewModel that you have is what I want.  I don't really need any of the other things.  My program already saves and loads info to and from a file...  and I can add and delete records.  I'm trying to mess with the SystemViewModel and integrate it into my program....all I need is to change my DefaultTableModel to the AbstractTableModel so that I can't "select" a cell.

I will be trying to fix this - but you seem to be a lot more knowledgable about Java than me, so if you can possibly help me with just the SystemViewModel and make this a lot less confusing for me, I thank you very much :)  So, I guess i just need the SystemViewModel to add, delete, and retrieve records for me.  I think I am close - it is just adding blank records (and about 8 of them) right now!

Thanks,

Chris
0
 

Author Comment

by:ctjoumas
ID: 8181720
One question i have is - im not so sure what the fileObjects vector is doing.  Is this vector being "put" to the table?  If so...how is it doing this?  So, if I have 7 fields (or columns) in one record and I want to add this record - how can I add this to the table?

Thanks,

Chris
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ctjoumas
ID: 8181777
One question i have is - im not so sure what the fileObjects vector is doing.  Is this vector being "put" to the table?  If so...how is it doing this?  So, if I have 7 fields (or columns) in one record and I want to add this record - how can I add this to the table?

Thanks,

Chris
0
 

Author Comment

by:ctjoumas
ID: 8181781
One question i have is - im not so sure what the fileObjects vector is doing.  Is this vector being "put" to the table?  If so...how is it doing this?  So, if I have 7 fields (or columns) in one record and I want to add this record - how can I add this to the table?

Thanks,

Chris
0
 

Author Comment

by:ctjoumas
ID: 8181790
oops..sorry about the multiple posts!
0
 

Author Comment

by:ctjoumas
ID: 8182672
OK...  I have gotten it to add the correct amount of rows now... basically,  the addData function looks like:

public void addData(Vector v) {
    table.add(v.toArray());
    fireTableRowsInserted(table.size(), table.size()+1);
}

where table is my table vector - it contains all of the data that the table shows.  So, my thinking is, that the vector v that is sent to addData contains the customer record (a vector of size 7...which contains the 7 elements of each of the 7 columns I have) and this is added to my table vector...and when I fireTableRowsInserted, this vector v should now show up as a new row in the table.

However, this doesn't happen.  A new row appears, but it is empty.  I don't get any errors or anything..

Chris
0
 

Author Comment

by:ctjoumas
ID: 8195179
For the most part - what you gave me helped...it is doing what I want it to do.  But, when I add a row, no data gets added - just a blank row is added.  Is there some way I need to "link" my data vector into my table model?  I think I'm missing something simple.

Thanks,

Chris
0
 
LVL 9

Expert Comment

by:Ovi
ID: 8195269
Sorry for absence!
0
 
LVL 9

Expert Comment

by:Ovi
ID: 8195289
try with fireTableDataChanged() instead of rowsAdded. Follow my source code and see if it works. There is a method call on every model metod which modify the internal data, called updateObjects(). Focus on that one.
0
 

Author Comment

by:ctjoumas
ID: 8195656
I have already tried fireTableDataChanged() :)  Here is the code I am working with right now (i've left out unimportant methods and library imports...):

----------------------------
public class RecordsTable extends JTable {

  /**
   * Handle to the parent application object.
   */  
  private HelpDesk helpDeskObj;

  private RecordsViewModel rvm = null;

  public RecordsTable(HelpDesk helpDesk) {

    dtm = new RecordsViewModel();

    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
       System.out.println("double click");
     }
      }
    });

    setModel(rvm);
  }

  // this gets called from another class, which
  // passes in a vector that holds the customer data
  public void addRow(Vector record) {
    rvm.addData(record);
  }
}


class RecordsViewModel extends AbstractTableModel {

  protected ColumnDescriptor cols[] =  {
    new ColumnDescriptor("FirstName", 40, JLabel.LEFT),
    new ColumnDescriptor("LastName", 50, JLabel.LEFT),
    new ColumnDescriptor("Phone", 50, JLabel.LEFT),
    new ColumnDescriptor("City", 50, JLabel.LEFT),
    new ColumnDescriptor("State", 50, JLabel.LEFT),
    new ColumnDescriptor("Street", 50, JLabel.LEFT),
    new ColumnDescriptor("Notes", 50, JLabel.LEFT),
    new ColumnDescriptor("WorkOrder", 50, JLabel.LEFT),
  };

  private Vector table;

  public RecordsViewModel() {
    table = new Vector();
  }  

  public void addData(Vector v) {
    table.addElement(v);
    fireTableDataChanged();
  }

  class ColumnDescriptor {
    public String name;
    public int width;
    public int alignment;

    public ColumnDescriptor(String n, int w, int a) {
      name = n;
      width = w;
      alignment = a;
    }
  }
}
----------------------------


Thanks,

Chris
0
 

Author Comment

by:ctjoumas
ID: 8195667
Sorry, the line:
dtm = new RecordsViewModel();

is:
rvm = new RecordsViewModel();

Just letting you know that that isn't hte problem :)

Thanks,

Chris
0
 
LVL 9

Expert Comment

by:Ovi
ID: 8195739
I see that uou are holding a Vector of vectors structure into your model. In my original code there was a dedicated object to actually represent a row in the table/model, called FileElement. Check your getValueAt(int row, int col) method in your model.
0
 

Author Comment

by:ctjoumas
ID: 8195783
Ah...ok - that was my problem.  I didn't know that getValueAt gets called when displaying (or adding) a record.  I need to read up somewhere (Hopefully Java's API has explanations) on how all this works together!

Thanks!!

Chris
0
 
LVL 9

Expert Comment

by:Ovi
ID: 8195845
Yes, the methods are called

Eg: getValueAt() request the value of a particular cell
getColumnName() should return the column name stored by your collumns array
getColumnCount should return columns.length
getRowCount should return table.size()
... and so on ...
0
 

Author Comment

by:ctjoumas
ID: 8196028
Gotcha..  thank you very much and sorry I didn't have any more points to give you!
0
 
LVL 9

Expert Comment

by:Ovi
ID: 8196061
no problem, sorry for late feedback :-)
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Suggested Courses
Course of the Month13 days, 11 hours left to enroll

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question