I have a small Java swingui app where I display a JList and the user is able to cut, copy, paste and sort the list.
I use a custom TransferHandler to allow drag and drop on this Jlist. Here is the code in building the JList, it basically builds it from an ArrayList. "lstScripts" is the JList.
ListTransferHandler lh = new ListTransferHandler();
...
DefaultListModel listModelScripts = new DefaultListModel();
for(Script s : scripts) {
listModelScripts.addElement(s.getName());
}
this.lstScripts = new JList(listModelScripts);
this.lstScripts.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.lstScripts.addListSelectionListener(this);
JScrollPane sp = new JScrollPane(this.lstScripts);
sp.setPreferredSize(new Dimension(400,100));
this.lstScripts.setDragEnabled(true);
this.lstScripts.setTransferHandler(lh);
this.lstScripts.setDropMode(DropMode.ON_OR_INSERT);
setMappings(this.lstScripts);
...
On my custom TransferHandler class, I've got the importData routine working so that it handles the copy/paste/cut/sort.
public boolean importData(TransferHandler.TransferSupport info) {
String scriptname = null; // The script name on the list
//If we can't handle the import, bail now.
if (!canImport(info)) {
return false;
}
JList list = (JList)info.getComponent();
DefaultListModel model = (DefaultListModel)list.getModel();
//Fetch the scriptname -- bail if this fails
try {
scriptname = (String)info.getTransferable().getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ufe) {
System.out.println("importData: unsupported data flavor");
return false;
} catch (IOException ioe) {
System.out.println("importData: I/O exception");
return false;
}
if (info.isDrop()) { //This is a drop
JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
int index = dl.getIndex();
model.add(index, scriptname);
return true;
} else { //This is a paste
int index = list.getSelectedIndex();
// if there is a valid selection,
// insert scriptname after the selection
if (index >= 0) {
model.add(list.getSelectedIndex()+1, scriptname);
// else append to the end of the list
} else {
model.addElement(scriptname);
}
return true;
}
}
So up to here, everything works fine as far as the GUI. But my problem is I need the original JList "lstScripts" to be automatically updated with the user GUI changes. For example, if the user cuts or reorders the list, I want it to show on in "lstScripts".
I'm not seeing how to make this connection between the TransferHandler and original GUI controller where "lstScripts" resides.
#kleopatra - you helped me! sorry I didnt understand how the model was working.
So in the controller, I create the "lstScripts" JList and add it to my panel (this is the first block of my code above).
pnlScripts.add(lstScripts, BorderLayout.WEST);
And as my code above showed, the listScripts JList had a custom transferhandler set as such:
this.lstScripts.setTransferHandler(lh);
So the transferhandler does all the user dnd (drag and drop) stuff. In the controller, I can get the updated list by doing:
DefaultListModel model = (DefaultListModel)lstScripts.getModel();
for (int i = 0; i < model.getSize(); i++){
scriptnames += model.getElementAt(i).toString() + ",";
}
The scriptnames String variable now contains the updated list.
Thanks!
Related
Question Now once the data is fetched from the database and shown in the JTable object "table" embedded in the scrollPane, how do we create a print job that makes it possible to print the displayed table as such in A3 sized paper ?
My code to fetch the data from the database is shown below:
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/newb","root","pass");
Statement stat=con.createStatement();
ResultSet res=stat.executeQuery("select * from table where name = '"+name+"'");
ResultSetMetaData rsmd = res.getMetaData();
int colcount = rsmd.getColumnCount();
Vector columns = new Vector(colcount);
for(int i=3; i<=colcount; i++)
{
columns.add(rsmd.getColumnName(i));
}
Vector data = new Vector();
Vector row;
// Store row data
while(res.next())
{
row = new Vector(colcount);
for(int i=3; i<=colcount; i++)
{
row.add(res.getString(i));
}
data.add(row);
}
table = new JTable(data, columns);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scrollPane.setViewportView(table);
}
catch(Exception ex)
{
System.out.println(ex);
}
I am using vector class to fetch the data from the table. How do we print the data shown in the displayed table to a paper?
just use JTable.print() method. here is an article about sending JTable into printer and another one with more parameters
You obviously didn't read the links provided in your previous question.
From the Printing section of How to use Tables
Printing
JTable provides a simple API for printing tables. The easiest way to
print out a table is to invoke JTable.print with no arguments:
try {
if (! table.print()) {
System.err.println("User cancelled printing");
}
} catch (java.awt.print.PrinterException e) {
System.err.format("Cannot print %s%n", e.getMessage());
}
Invoking print on a normal Swing application brings up a standard printing
dialog box. (On a headless application, the table is simply printed.)
The return value indicates whether the user went ahead with the print
job or cancelled it. JTable.print can throw
java.awt.print.PrinterException, which is a checked exception; that's
why the above example uses a try ... catch.
JTable provides several overloads of print with various options. The
following code from TablePrintDemo.java shows how to define a page
header:
MessageFormat header = new MessageFormat("Page {0,number,integer}");
try {
table.print(JTable.PrintMode.FIT_WIDTH, header, null);
} catch (java.awt.print.PrinterException e) {
System.err.format("Cannot print %s%n", e.getMessage());
}
For more sophisticated printing applications, use JTable.getPrintable to obtain
a Printable object for the table. For more on Printable, refer to the
Printing lesson in the 2D Graphics trail.
i hope help you with this code try it its for How to print JTable in Java netbeans
private void btn_printActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
MessageFormat header = new MessageFormat("Print Report");
MessageFormat footer = new MessageFormat("Page{0,number,integer}");
try {
table_employee.print(JTable.PrintMode.FIT_WIDTH, header, footer);
} catch (java.awt.print.PrinterAbortException e) {
} catch (PrinterException ex) {
Logger.getLogger(employee_info.class.getName()).log(Level.SEVERE, null, ex);
}
}
I've been searching through this website for numerous hours now on how to get my button to an a row to an already existing table, this table created by simply clicking the swing Controls, and adding a table and altering the fields through the properties.
The table's variable name is 'table'.
And when confronted with this line of code:
table.getModel().insertRow(table.getRowCount(),new Object[]{nome[i],data[i]});
The 'insertRow' part is redded and I can't seem to fix it.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String direcdate=direc1.getText();
File folder = new File(direcdate);
File[] listOfFiles=folder.listFiles();
String[] nome = new String[250];
String[] data = new String[250];
int i=0;
for (File listOfFile : listOfFiles) {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
if (listOfFile.isFile()) {
nome[i]= listOfFile.getName ();
data[i] =sdf.format(listOfFile.lastModified());
i++;
}
else if (listOfFile.isDirectory()) {
nome[i]= "Folder: " + listOfFile.getName ();
data[i] =sdf.format(listOfFile.lastModified());
i++;
}
}
for(int increm=0;increm<i;increm++)
{
table.getModel().insertRow(table.getRowCount(),new Object[]{nome[i],data[i]});
}
}
Any ideas or suggestions?
EDIT: where the table model is located:
public class GAPAC_TESTE extends javax.swing.JFrame {
public GAPAC_TESTE() {
initComponents();
ultimaalt.setText("0");
jTextPane2.setText("Após escolher a diretoria, escolha uma das opções.");
DefaultTableModel model = new javax.swing.table.DefaultTableModel();
table = new javax.swing.JTable(model);
}
table.getModel().
That method return a TableModel. Did you look at the API for the TableModel interface? It does not contain an insertRow(...) method.
The DefaultTableModel has the insertRow(...) method. So assuming your table is using a DefaultTableModel the code would be:
DefaultTableModel model = (DefaultTableMode)table.getModel();
model.insertRow(...);
Don't always write you code in a single statmentment. Break the statement up into multiple statements so you understand exactly which part of the statement causes the problem and it makes sure you assign the variable to the proper class.
If you implement a TableModel, you will be able to exactly determine how data is added and which data types are displayed in your table.
I create a jtable like this :
String name = temp.getName();
String enemy = namaFileUtama.toString();
DefaultTableModel models = (DefaultTableModel) Main_Menu.jTable4.getModel();
List<ReportMomentOfTruth> theListRMOT = new ArrayList<ReportMomentOfTruth>();
ReportMomentOfTruth rmot = new ReportMomentOfTruth();
rmot.setNameOfMainFile(name);
rmot.setNameOfComparingFile(enemy);
theListRMOT.add(rmot);
for (ReportMomentOfTruth reportMomentOfTruth : theListRMOT) {
models.addRow(new Object[]{
reportMomentOfTruth.getNamaFileUtama(),
reportMomentOfTruth.getNamaFilePembanding(),
});
}
You know, I dont get an idea. How can I get the contains the file if I click one row in jtable then the contains will be show in jTextArea ? Any suggestion ? any example perhaps ?
Thanks
edit
You know, I am using netbeans, I can get a method like this
private void jTable4MouseClicked(java.awt.event.MouseEvent evt) {
if (evt.getClickCount() == 1) {
}
}
Now how to ?
How can I get the contains the file if I click one row in jtable then the contains will be show in jTextArea?
You can better use JEditorPane that has a method setPage() that can be used to initialize the component from a URL.
Just get the values of selected row and use below code to set the content in JEditorPane.
sample code:
final JEditorPane document = new JEditorPane();
document.setPage(new File(".../a.java").toURI().toURL());
Add ListSelectionListener to detect the selection change event in the JTable
final JTable jTable = new JTable();
jTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
int row = jTable.getSelectedRow();
if(row != -1){
String firstColumnValue = jTable.getModel().getValueAt(row, 0).toString();
String secondColumnValue = jTable.getModel().getValueAt(row, 1).toString();
// load the JEditorPane
}
}
});;
Read more...
This Code is in a While Loop, and each time I run a new Query it will go through this block after I have chosen what to filter it by, the problem is when I run it a second time and click on a cell in my table it will revert to cells in my previous table/query. I attached an image to show what I mean(I need 10 reputation for that so nevermind on the picture), I filtered the table by procsessState = -1 and when I clicked on some cells it reverted to what the previous table had. Help would be greatly appreciated. The program is around 1000 lines long and I did a terrible job of splitting it into different classes So I just posted where I am almost certain the issue arises.
I declared
final String columnNamesForTable[] = {"Error Message", "ID", "Locked By", "Message Id", "Process State",
"Row Date", "Sender", "Sent Date", "Subject" };
At The top, then I have this a bit later on.
else if (checkBoxCounter != 0)
{
DefaultTableModel tableModel = new DefaultTableModel(columnNamesForTable, 0);
tableModel.fireTableDataChanged();
try
{
Connection conn = DatabaseConnection.getConnection();
System.out.println("Connected");
PreparedStatement statement = conn.prepareStatement(sb.toString(),
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
// Change CONCUR_READ_ONLY to CONCUR_UPDATABLE
ResultSet resultSet = statement.executeQuery();
int errorMessageIndex = resultSet.findColumn("ErrorMessage");
int idIndex = resultSet.findColumn("Id");
int lockedByIndex = resultSet.findColumn("LockedBy");
int messageIdIndex = resultSet.findColumn("MessageId");
int processStateIndex = resultSet.findColumn("ProcessState");
int rowDateIndex = resultSet.findColumn("RowDate");
int senderIndex = resultSet.findColumn("Sender");
int sentDateIndex = resultSet.findColumn("SentDate");
int subjectIndex = resultSet.findColumn("Subject");
while (resultSet.next()) {
Object[] rowsForTable = { resultSet.getString(errorMessageIndex),
resultSet.getString(idIndex), resultSet.getString(lockedByIndex),
resultSet.getString(messageIdIndex), resultSet.getString(processStateIndex),
resultSet.getString(rowDateIndex), resultSet.getString(senderIndex),
resultSet.getString(sentDateIndex), resultSet.getString(subjectIndex)};
tableModel.addRow(rowsForTable);
}
resultSet.close();
statement.close();
conn.close();
filterFrame.setVisible(false);
JTable resultsTable = new JTable(tableModel);
JScrollPane pane = new JScrollPane(resultsTable);
displayPnl.add(pane);
pack();
resultsTable.repaint();
isDone= true;
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Database error");
ex.printStackTrace();
isDone = true;
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Error loading database driver");
ex.printStackTrace();
isDone = true;
}
}
This Code is in a While Loop
Why would it be in a while loop. Swing is event driven. Code should only be executed when the uses generates some kind of event like clicking on a button, typing text, editing a cell.
I have chosen what to filter it by,
Don't create a whole new table and scroll pane. Just update the TableModel of the existing JTable.
pack();
Why would you pack the frame. The query could have 100's of rows of data. Pick a reasonable size for the table when the frame is created and there is no need to use pack() or repaint(). When you invoke the setModel(...) method of the JTable to replace the current model the table will be repainted automatically.
So all the code you need should be:
//filterFrame.setVisible(false);
//JTable resultsTable = new JTable(tableModel);
//JScrollPane pane = new JScrollPane(resultsTable);
//displayPnl.add(pane);
//pack();
//resultsTable.repaint();
existingTable.setModel( tableModel );
I cant comment I do not have enough reputation.
You fire tabledatachanged before changing data.
TableDataChanged does not always properly update rows , it seems better to fire update rows.
If your table is editable , if you clicked the table you need to release the editor.
I have the following method which creates a JTable then prints it out by its appearing as a rectangle no the page with the header and footer.
public void printModules(){
MessageFormat header = new MessageFormat("Modules " + new Date());
MessageFormat footer = new MessageFormat("Created by Assignments Database");
try {
JTable jtModules = new JTable(new ModulesTableModel(Controller.getInstance().getModules()));
jtModules.setShowHorizontalLines(true);
jtModules.setShowVerticalLines(true);
jtModules.setShowGrid(true);
boolean complete = jtModules.print(JTable.PrintMode.NORMAL, header, footer, true, null, false, null);
if(complete){
System.out.println("Printed");
} else{
System.out.println("Printing Cancelled");
}
} catch (PrinterException e) {
e.printStackTrace();
}
}
What else is wrong? There is data in the table as one that is created from the same data is showing in one of the panels.
In my abstract table model I have implemented the following methods:
Constructor
getRowCount
getColumnCount
getValueAt
getColumnNames
Is there any other methods that need to be created?
JTable has very reduced support for printing, there are some descriptions about printing in the tutorials about JTable (inc. code example) and Printing
You need to display the table in order to print it, so add it to a JFrame, then frame.setVisible(true); then frame.setVisible(false);
This will make it print.