Since chemical structures are frequently stored in databases, the most common usage of molecule visualization is perhaps in tablular format allowing to browse the database, showing search results, selections of structures against particular criteria.
In typical Java applications, the javax.swing.JTable
is used to display tables
of data. This form visualization form will be referred to as tables.
This section demonstrates how can moecules be rendered with Marvin inside existing tables.
The following picture shows a simple table with a molecule column.
JTable
to bear in mind are as follows:
getColumnClass
method,
which gets the data type of the column's cells. Next, the table compares the
column's data type with a list of data types for which cell renderers are registered.
This list is initialized by the table, but you can add to it or change it.
ChemAxon recommends the following points to consider:
To use the MViewPane component as the cell renderer, it should implement the
getTableCellRendererComponent
method of the TableCellRenderer
interface.
The implementation of this method sets up the rendering component to display the passed-in molecule,
and then returns the component.
public class MViewRenderer extends MViewPane implements TableCellRenderer { public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { ... // setting backround color and border setM( 0, (Molecule)value ); return this; } }This renderer class is accessible from the public API: chemaxon.marvin.beans.MViewRenderer
In many cases it is sufficient to have only the static image of the molecule inside cells, i.e no need to rotate, change rendering mode or modify the structure itself. The renderer can be more compact in this case.
This renderer extends the JPanel
class overriding its paintComponent
method.
The getTableCellRenderer
method sets the molecule to be shown.
public class MolRenderer extends JPanel implements TableCellRenderer { private MolPrinter printer; public MolRenderer() { printer=new MolPrinter(); } public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { ... // Setting background color and border // Passing the current molecule to MolPrinter. printer.setMol((Molecule)value); return this; } public void paintComponent(Graphics g) { // It is very important to set the scale factor of MolPrinter, // otherwise the image will not appear. // The scale factor is computed by MolPrinter from // the current size. double scale = printer.maxScale(getSize()); // The scale factor can be maximized to prevent overscaling small molecules. if( scale > SketchPanel.DEFAULT_SCALE ) { scale = SketchPanel.DEFAULT_SCALE; } printer.setScale(scale); // When MolPrinter is properly initialized, it can paint the // molecule. printer.paint((Graphics2D) g, getSize()); } }
There are several ways to specify a cell renderer. In this example we use
type-specific renderers using the setDefaultRenderer
method of JTable:
table.setDefaultRenderer(Molecule.class, new MViewRenderer());for setting MViewPane renderer, while
table.setDefaultRenderer(Molecule.class, new MolRenderer());for setting MolPrinter renderer.
Using MViewPane as a cell editor provides two major advantages.
The image below shows indirect editing in use:
The code below shows the major parts of the simple cell editor.
class MViewEditor extends DefaultCellEditor { //returns the edited molecule public Object getCellEditorValue() { currentMol = ((MViewPane)editorComponent).getM(0); return currentMol; } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { currentMol = (Molecule)value; ... // setting background color and border ((MViewPane)editorComponent).setM(0,currentMol); return editorComponent; } }This editor class is accessible from the public API: chemaxon.marvin.beans.MViewEditor
In case the molecular structures can be modified by a cell editor, we can ensure that the modification affects all other data being in connection, like computed molecular data.
In this example the third column contains such computed molecular data, the mass.
When the editing of the molecule is finished, and fireEditingStopped
is called, the setValueAt(Object value, int row, int col)
method of the table model gets called.
In this example we have set the molecule masses inside this method, so that
when the molecule is initialized and every time it is modified,
its mass will be instantly updated.
public void setValueAt(Object value, int row, int col) { data[row][col] = value; if(col==1) { // setting the mass here keeps the column updated // upon editing the molecules setValueAt(""+((Molecule)value).getMass(), row, 2); } fireTableCellUpdated(row, col); }The code excerpts shown above were taken from the full sample code of