2

I have an application in which there is two Jtables in two different InternalFrames, one that does have a model with its columns, and the other doesn't, and the idea is to drag some of the columns from one to the other for print purposes.. Because in this app i'm doing, all of the columns are important to keep but not all of them have to be printable, we only need some columns to print.

So my question is: is it possible to to drag and drop columns between the two jtables that are in two different internalframes to create a model to print. and if it is how to do it?

Thanks in advance.

Well after trying @Kleopatra 's solution, i still am not able to drop the columns, at least now i can drag them :p!

At first, the problem was a JavaNullPointerExeption when i run the program, it's something about getting the source table model; "JXTable target=new JXTable(source.getModel())", and then i created two models for the two tables (with the same structure), but now the problem is that when i try to drop it, there's the "stop" sign; you know the circle with a diagonal line in it. I tried everything to fix this problem,but in vain... so i appreciate the help.

Here's the code of the source table:

package presentation;
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.EventQueue;

import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;
import org.jdesktop.swingx.JXTable;
import domain.Bulletin_Assurance;

public class Presentation_Bulletin_assur extends JInternalFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;



/**
 * Launch the application.
 */



public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {

                final Presentation_Bulletin_assur frame = new Presentation_Bulletin_assur();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */




TransferHandler handler;
final static String[] columnNames = { "Num du bulletin", "Num d'adhésion", "Pièce", "Nom du Beneficiaire", "Nom du malade", "Nom Medecin", "Date de consultation","Frais Medecin", "Honoraire", "Pharmacie", "Injection", "Laboratoire", "Radio", "Monture", "Verre", "Soins", "Prothése", "Hospitalisation", "Divers 1", "Divers 2", "Divers 3" };





final static Object[][] data = {
    {new Integer(Bulletin_Assurance.getNum_bulletin()),
    new Long (Bulletin_Assurance.getNum_adhesion()), 
    new Long(Bulletin_Assurance.getPiece()), 
    Bulletin_Assurance.getNom_Beneficiaire(),
    Bulletin_Assurance.getNom_du_malade(),
    Bulletin_Assurance.getNom_Medecin(),
    Bulletin_Assurance.getDate_Consultation(),
     new Double(Bulletin_Assurance.getMedecin()),
     new Float(Bulletin_Assurance.getHonor()),
     new Float(Bulletin_Assurance.getPharmacie()),
     new Float(Bulletin_Assurance.getInjection()),
     new Float(Bulletin_Assurance.getLaboratoire()),
     new Float(Bulletin_Assurance.getRadio()),
     new Float(Bulletin_Assurance.getMonture()),
     new Float(Bulletin_Assurance.getVerre()),
     new Float(Bulletin_Assurance.getSoins()),
     new Float(Bulletin_Assurance.getProthese()),
     new Float(Bulletin_Assurance.getHospitalisation()),
     new Float(Bulletin_Assurance.getDiver_1()),
     new Float(Bulletin_Assurance.getDiver_2()),
     },
     };

static DefaultTableModel model=new DefaultTableModel(data, columnNames);;
public static JXTable table=new JXTable(model);







public Presentation_Bulletin_assur() {
    setFrameIcon(null);
    setBounds(100, 100, 511, 492);
    setResizable(true);
    setLayout(new FlowLayout());
        handler = new DragDropConfig();
    table.setTransferHandler(handler);
    table.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
    table.setRowSelectionAllowed(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setSurrendersFocusOnKeystroke(true);
    table.setFont(new Font("Times New Roman", Font.PLAIN, 13));
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

    table.setDragEnabled(true);

    getContentPane().setLayout(new BorderLayout());
    setClosable(true);

    final JScrollPane scrollPane = new JScrollPane(table);
    table.setFillsViewportHeight(true);
    scrollPane.getViewport();
    getContentPane().add(scrollPane);
}

And here's the code of the target table:

package presentation;
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.table.TableColumnExt;
public class Imprimer_bordereau extends JInternalFrame implements ActionListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private JScrollPane sc;
static JXTable bordereau;
private JButton imprimer;

Presentation_Bulletin_assur pr;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Imprimer_bordereau frame = new Imprimer_bordereau();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public Imprimer_bordereau() {
    setBounds(100, 100, 450, 300);
    setResizable(true);



    DefaultTableModel model=(DefaultTableModel) Presentation_Bulletin_assur.table.getModel();

    bordereau=new JXTable(model);
    bordereau.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    bordereau.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
    bordereau.setRowSelectionAllowed(true);
    bordereau.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    bordereau.setSurrendersFocusOnKeystroke(true);
    bordereau.setFont(new Font("Times New Roman", Font.PLAIN, 13));
    bordereau.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

    sc= new JScrollPane(bordereau);
    bordereau.setFillsViewportHeight(true);
    sc.getViewport();
    getContentPane().add(sc, BorderLayout.CENTER);



    List<TableColumn> columns = bordereau.getColumns();
    for (TableColumn tableColumn : columns) 
    {
        ((TableColumnExt) tableColumn).setVisible(false);
    }

    TransferHandler handler=new DragDropConfig();
    bordereau.setTransferHandler(handler);
    bordereau.setDragEnabled(true);




    imprimer= new JButton("Imprimer");
    imprimer.setFont(new Font("Times New Roman", Font.PLAIN, 14));
    imprimer.addActionListener(this);
    getContentPane().add(imprimer, BorderLayout.SOUTH);

}

public void actionPerformed(ActionEvent arg0) 
{
    if(arg0.getSource()==imprimer)
    {
        pr=new Presentation_Bulletin_assur();
        pr.setTitle("Les informations à imprimer");
        Presentation_Bulletin_assur.table.setToolTipText("Pour choisir les informations à imprimer, \n il suffit de maintenir le clic de souris sur une case, \nd e les faire glisser vers la fenêtre intitulée fenêtre d'impression,\n et de les déposer");
        MainPage.dp.add(pr);
        pr.setVisible(true);
    }


}
}

And last, the transferhandler:

package presentation;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.util.List;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import javax.swing.table.TableColumn;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.table.TableColumnExt;


public class DragDropConfig extends TransferHandler {
/**
 * 
 */
private static final long serialVersionUID = 1L;
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(
        Integer.class, DataFlavor.javaJVMLocalObjectMimeType,
        "Integer Column Model Index");



protected Transferable createTransferable(JComponent c) {
    JXTable table = (JXTable) c;
    int index = table.getSelectedColumn();
    TableColumnExt column = table.getColumnExt(index);
    return new DataHandler(column.getModelIndex(),
            localObjectFlavor.getMimeType());
}


public boolean canImport(TransferHandler.TransferSupport info) {
    return info.isDataFlavorSupported(localObjectFlavor);
}


public int getSourceActions(JComponent c) {
    return TransferHandler.COPY;
}


public boolean importData(TransferHandler.TransferSupport info) {
    JXTable bordereau = (JXTable) info.getComponent();
    JXTable.DropLocation dl = (JXTable.DropLocation) info.getDropLocation();
    try {
        Integer columnFrom = (Integer) info.getTransferable().getTransferData(
                localObjectFlavor);
        TableColumnExt tableColumn = null;
        List<TableColumn> columns = bordereau.getColumns(true);
        for (TableColumn column : columns) {
            if (column.getModelIndex() == columnFrom) {
                ((TableColumnExt) column).setVisible(true);
                return true;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
}

By the way, in the transferhandler, the droplocation "dl" in line 48 and "tableColumn" in line 52 are marked as unused variables. (maybe it has something to do with that, sorry for my ignorance :p )

  • 1
    first thingy I would try is a custom transferHandler. BTW, where the tables are located is irrelevant to the problem :-) – kleopatra Apr 24 '14 at 12:10
  • So you are saying that it's possible, great :). Is it possible to give me an example of how to add transferHandler that allows you to drag and drop columns? and also, what should be the model of the "blank" table, or the table that is going to be printed? –  Apr 24 '14 at 12:27
  • @user3568400: Start [here](http://docs.oracle.com/javase/tutorial/uiswing/dnd/intro.html). – trashgod Apr 24 '14 at 12:50
  • Thank you very much for your help, but i also found [this](http://fr.openclassrooms.com/informatique/cours/apprenez-a-programmer-en-java/creer-son-propre-transferhandler)which will be easier for me since it's in french. –  Apr 24 '14 at 13:17
  • something wrong in the code you are not showing ;-) – kleopatra Apr 25 '14 at 09:43
  • Haha, well i'll add the code for the two tables and the transferhandler. And thank you again for your help, you are a life savior! –  Apr 25 '14 at 10:39
  • you should show a _runnable, stand-alone_ example, not tons of your original code ... (which I'm not going to wade through ;-) And when you are preparing that example, please learn java naming convention and stick to them :-) – kleopatra Apr 25 '14 at 11:34

1 Answers1

2

Easiest (assuming you are doing the printing with the in-built support, that is printing the visible part of the table) would be

  • use the same model on both tables
  • start the printable table without any columns (or set their visible property to false)
  • on dropping, add a column corresponding the transfered column (model!) column index (or set its visibility to true)

Below is a (very quick) example that uses SwingX, specifically its support of column visibility and the activation framework

// a TransferHandler for dragging a column between tables
// by changing its visiblity property
public class TableColumnTransferHandler extends TransferHandler {
    private final DataFlavor localObjectFlavor = new ActivationDataFlavor(
            Integer.class, DataFlavor.javaJVMLocalObjectMimeType,
            "Integer Column Model Index");


    @Override
    protected Transferable createTransferable(JComponent c) {
        JXTable table = (JXTable) c;
        int index = table.getSelectedColumn();
        TableColumnExt column = table.getColumnExt(index);
        return new DataHandler(column.getModelIndex(),
                localObjectFlavor.getMimeType());
    }

    @Override
    public boolean canImport(TransferHandler.TransferSupport info) {
        return info.isDataFlavorSupported(localObjectFlavor);
    }

    @Override
    public int getSourceActions(JComponent c) {
        return TransferHandler.MOVE;
    }

    @Override
    public boolean importData(TransferHandler.TransferSupport info) {
        JXTable target = (JXTable) info.getComponent();
        JTable.DropLocation dl = (JTable.DropLocation) info.getDropLocation();
        try {
            Integer columnFrom = (Integer) info.getTransferable().getTransferData(
                    localObjectFlavor);
            TableColumnExt tableColumn = null;
            List<TableColumn> columns = target.getColumns(true);
            for (TableColumn column : columns) {
                if (column.getModelIndex() == columnFrom) {
                    ((TableColumnExt) column).setVisible(true);
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

// its usage
JXTable source = new JXTable(new AncientSwingTeam());
JXTable printable = new JXTable(source.getModel());
TransferHandler handler = new TableColumnTransferHandler();
List<TableColumn> columns = printable.getColumns();
for (TableColumn tableColumn : columns) {
    ((TableColumnExt) tableColumn).setVisible(false);
}
source.setTransferHandler(handler);
source.setDragEnabled(true);
printable.setTransferHandler(handler);
printable.setDragEnabled(true);
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • Thank you for you answer, it's not what i had in mind but your solution theoretically works just fine for me, i need exactly this result, all i have to do is test it and i'll give you feedback. Although i just have a last question, since i made my application with Swing, and since i just knew about the SwingX toolkit in your answer, i'd like to know if i have to remake my whole application in SwingX or can i just use the SwingX for when i need it (in this case for JXTable) and keep other components of Swing? –  Apr 24 '14 at 14:05
  • just use what you need, it's an extension of Swing and works perfectly fine side-by-side :-) But then, this is just an example to get you started, you _don't have to_ use the extended features. Simply add/remove columns (instead of showing/hiding) in the printable table as needed. JTable's api doc is your friend ... – kleopatra Apr 24 '14 at 14:13
  • It actually worked, the problem was that the visibility of the target table was set as false (i don't even know how), so when i tried to drop the column it didn't work (Logic, because just the scrollpane that contains the target table is not an accepted dropTarget). Then i changed the visibility of the target table, and now it works.. Thank you again :) –  Apr 29 '14 at 15:30