JTable in JDialog - java

I have problem with JTable using in JDialog. I want to show my table in dialog with this code:
public class ShortcutKeys extends JDialog {
public ShortcutKeys( JFrame parent ) {
super( parent );
this.setTitle( "Shortcut Keys of..." );
this.setLocationRelativeTo( null );
this.setModal( true );
this.setResizable( false );
this.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
this.getContentPane().setLayout( new BorderLayout() );
JTable shortcutKeysTable = getShortcutKeysTable();
this.add( shortcutKeysTable, BorderLayout.CENTER );
this.pack();
}
private JTable getShortcutKeysTable() {
JTable shortcutKeysTable;
Object rowData[][] = { { "1", "11" }, { "2", "22"} };
Object columnNames[] = { "Column One", "Column Two" };
shortcutKeysTable = new JTable(rowData, columnNames);
JScrollPane scrollPane = new JScrollPane(shortcutKeysTable);
this.add(scrollPane, BorderLayout.CENTER);
this.setSize(300, 150);
return shortcutKeysTable;
}
}
So, problem is such that with exactly this code, doesn't show column names - only row data without my size, result is in small table not with my preference.
BUT when in method or in constructor I add this line:
this.setVisible( true );
Then this table shows row data and columns with my size 300x150 BUT when I click ok Exit 'X' then of course this dialog disappeared but show new empty dialog:
http://i.imgur.com/SzkF5iK.png
What I did wrong and how can I resolve this problem?

What must be added to the dialog is the scollPane, which itself contains the table. Not the table itself.
You should decide what the getShortcutKeysTable()does:
either it creates a table, a scrollPane, and adds the scollPane to the dialog (and should be refactored to void createAndAddTable())
or it simply creates a table and returns it, and the caller is responsible for wrapping it into a scollpane and adding the scrollpane to the dialog.
Mixing the two responsibilities makes the code confusing, even for you who wrote the code.
In any wase, setting the size of the dialog is not its responsibility, and it's unneeded, since you call pack() after anyway.

You need to call JDialog.setVisible(true); in order to show the dialog.
But you have a bug in your code: You put the table in a scrollpane and add the scrollpane to the dialog (in method getShortcutKeysTable) and then add the table to the dialog again (in the constructor).
Your code runs fine if you do in the constructor
...
getShortcutKeysTable();
this.pack();
this.setVisible(true);
}

Related

JTable not visible inside JScrollPane

I have a JTable inside a JScrollPane. I want to show the table only when a particular button is pressed otherwise it should not be shown.
Inorder to incorporate that I have set the setVisible method of the ScrollPane to false while declaring and I set it to true inside the actionPerformed method of the JButton.
But the JTable is not visible even when I press the JButton.
Here's my code:
public class TableSample{
private JTable table;
....
private void initialize() {
JScrollPane scrollPane = new JScrollPane();
table = new JTable(new DefaultTableModel(new Object[][] {{null, null}, {null, null}, }, new String[] {"column1", "column2"}));
scrollPane.setViewportView(table);
scrollPane.setVisible(false);
JButton button = new JButton("Show Table");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
....
scrollPane.setVisible(true);
....
}
});
....
}
I have used group layout so the ScrollPane is added to frame with group layout.
Also the JTable is visible when I do not change the setVisible at all (by default true)
Any help is appreciated...
When you add components to a visible GUI the basic logic is:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // sometimes needed to make sure panel is repainted

how to refresh contents of jtable on event of action listener?

i have used following code to display jtable in a new panel in existing dialog. i have used mytablemodel class for table model and setmodel method is just like constructor(since i have to create several table using same model object so i have used method instead of constructor).But some how my jtable does not change the contents on actionlisten..same contents reappera even if value of input is changed...plz help
btnShow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
showTable();
}
});
panel_1.add(btnShow);
private void showTable() {
fillData();
//filldata used to fill object data for table using date specified by user
MyTableModel model=new MyTableModel();
model.setModel(data,col,totalrow);
table = new JTable(model);
table.setForeground(new Color(255,0,0) );
System.out.println("after table");
panel_2.add(new JScrollPane(table));
panel_2.setVisible(true);
table.setVisible(true);
System.out.println("after scroll pane");
}
Don't create a new JTable each time. Instead, get the model and replace/edit the data (best), or give the table a new model ("ok").
After a model's data has been changed, you need to call a "fireTableXXX" method.
You can call .fireTableDataChanged() which will reload all data. There are also methods for specifying which rows or cells were changed, so that it doesn't have to reload it all.
But some how my jtable does not change the contents
That is because you are creating a new table but that table is not visible on the GUI.
panel_2.add(new JScrollPane(table));
This just adds a component to the GUI but the size of the component is (0, 0). When you add a component to a visible GUI you need code like:
panel.add(...);
panel.revalidate();
panel.repaint(); // sometimes needed
Then the layout manager will be invoked on the panel and the added component will be displayed in the appropriate position.
However, the better solution is to update/replace the existing model in the displayed table as suggested by Xabster.

Scrollpane gets disappeared when frame is maximized

My prob is this....
JFrame ActualFrame = new JFrame("Actual frame");
JScrollPane pane = new JScrollPane(new JTable(data, columns));
ActualFrame.add(pane);
ActualFrame.add(PrintPreviewBtn);
PrintPreviewBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame PreviewFrame = new JFrame("Preview");
PreviewFrame.add(pane, BorderLayout.CENTER);
}
When i run the program everything seems to b fine but when i press print preview button the preview frame shows off and when i maximize or resize the ActualFrame the table gets disappeared....
NOTE:
I m adding the pane to the preview frame to show as if it is a preview of the table displayed.....is ter any other method for print preview
A component can only belong to a single parent. When you add it to the PreviewFrame, it is been removed, automatically, from the ActualFrame.
Instead of using the previous panel, create a new JTable, using the model from the previous one.
Update
Printing tables is a little more complicated, as includes the headers, and the columns need to be resized to meet the requirements of the available space.
Take a look at the Printing Tables tutorial for some examples
For printing there is the java.awt.PrinterJob class. To show the standart print preview you should call:
PrinterJob job = PrinterJob.getPrinterJob();
job.printDialog();
The Reason for disappearance of JScrollPane from the ActualFrame is that: You are adding the same instance of pane in PreviewFrame. So the actual container of the pane is now PreviewFrame instead of ActualFrame. When you maximize or resize the ActualFrame,it repaint its child components. Since the pane now no longer belongs to the ActualFrame it does not show the pane now.
The best way to avoid this situation is to create a seperate JTabel instance first, instead of passing anonymous JTable class object within the constructor of JScrollPane while creating the object pane . Get the TableModel and TableColumnModel of that JTable instance. In previewFrame add a new instance of JScrollPane that will contain the new instance of JTable with same TableModel and TableColumnModel objects.
The Code would look something like this:
final JTable table = new JTable(data,columns);
JScrollPane pane = new JScrollPane(table);
ActualFrame.add(pane);
ActualFrame.add(PrintPreviewBtn);
PrintPreviewBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame previewFrame = new JFrame("Preview");
javax.swing.table.TableModel tabModel = table.getModel();
javax.swing.table.TableColumnModel colModel = table.getColumnModel();
JScrollPane previewPane = new JScrollPane(new JTable(tabModel,colModel));
previewFrame.getContentPane().add(previewPane, BorderLayout.CENTER);
previewFrame.pack();previewFrame.setVisible(true);
}

Adding Buttons inside cell of JTable along with data?

Is it possible to add buttons inside the JTable cell along with data?
What I am trying to do is to create a table with columns which display data(number) from the database, and two buttons to increase/decrease the number inside the same cell.
|ID | Quantity|
|06| 2 [+][-] |
it would be something like above with [+][-] being buttons. So when I press [+], the number will change to 3 and 1 if pressing [-].
Yes, it is possible, although It won't be easy.
You have to write your own custom cell renderer and your own cell editor.
This is a sample I made in 5 minutes:
It is far from perfect, but shows the concept.
Here's the source code:
import java.awt.Component;
import java.awt.Font;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.Dimension;
public class CustomCell {
public static void main( String [] args ) {
Object [] columnNames = new Object[]{ "Id", "Quantity" };
Object [][] data = new Object[][]{ {"06", 1}, {"08", 2} };
JTable table = new JTable( data, columnNames ) {
public TableCellRenderer getCellRenderer( int row, int column ) {
return new PlusMinusCellRenderer();
}
};
table.setRowHeight( 32 );
showFrame( table );
}
private static void showFrame( JTable table ) {
JFrame f = new JFrame("Custom Cell Renderer sample" );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.add( new JScrollPane( table ) );
f.pack();
f.setVisible( true );
}
}
class PlusMinusCellRenderer extends JPanel implements TableCellRenderer {
public Component getTableCellRendererComponent(
final JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
this.add( new JTextField( value.toString() ) );
this.add( new JButton("+"));
this.add( new JButton("-"));
return this;
}
}
Here's a thread that may be interesting and here.
As discussed in the tutorial you'll need both a renderer to display your value and an editor to detect events from the cell being edited. In this example, the Component is a JCheckBox. Note that this requires a custom DataModel that extends AbstractTableModel to supply the correct Class for a given column. Joonas' suggestion to use JSpinner is a good one that works well.
I think you need to create a custom cell renderer if you want to show anything else than text (or numbers) in the cell. The cell renderer's job is to paint whatever you need to show in the cell.
See Table Renderer documentation.
So in this case you could create a small JPane which contains the text field and the tiny + and - buttons - or a just a JSpinner component, if does what you need. A bit tricky, for sure, but should be possible.

JTable selects wrong cell on click

I am working inside of a quite complex eclipse based application, and having a problem with a JTable based custom component inside of a JSplitPane. The part of the application that I actually have access to is a panel, within a tab, within a panel, within the actual application, so there are a lot of things that can go wrong.
The specific problem that I'm having right now is that the table component is selecting the wrong cell when I click on it. If I select a cell in row 0, column 0, the cell that actually gets selected is at row 2, column 0, which is about 20 pixels below the actual click. This only happens if the table is in a JSplitPane though: if I just add the table itself to a panel, cell selection is correct.
What it seems like to me is that because the table is in a JSplitPane, the boundaries of the table (or maybe the viewport of the scroll pane containing the table?) are off by about 20 pixels somewhere. Another problem that I had which can back this theory up, is that scrolling the table caused repaints above the table: so for example, as I scrolled down, instead of the table scrolling, it actually moved upwards (painting over the components above the table) about 20 pixels before scrolling. I was able to workaround this problem by adding
jscrollpane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
to the scrollpane that contained the table.
Because of all the custom components involved, I can't actually get a small app that shows the problem, but I have the next best thing, which is an app that shows the layout that I have (of course, it doesn't actually have the same problems). Any ideas on what might be causing the problem?
//Test class showing layout of table/splitpane
import javax.swing.*;
import java.awt.*;
public class SplitTest
{
private static JFrame frame;
private static JPanel buildTable()
{
JPanel tblPanel = new JPanel();
tblPanel.setLayout(new BorderLayout());
String[] cols = new String[]{"one", "two", "three", "four", "five", "six", "seven"};
Object[][] data = new Object[30][7];
for(int x = 0;x < data.length;x++)
for(int y = 0;y < data[x].length;y++)
data[x][y] = x + ", " + y;
JTable tbl = new JTable(data, cols);
JScrollPane scrollPane = new JScrollPane(tbl);
tblPanel.add(scrollPane, BorderLayout.CENTER);
return tblPanel;
}
private static JPanel buildTab()
{
JPanel pnl = new JPanel();
pnl.setLayout(new BorderLayout());
JPanel menuPnl = new JPanel();
menuPnl.setLayout(new FlowLayout(FlowLayout.LEFT));
menuPnl.add(new JLabel("label"));
menuPnl.add(new JComboBox(new String[]{"one", "two"}));
menuPnl.add(new JButton("Button"));
pnl.add(menuPnl, BorderLayout.NORTH);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setLeftComponent(buildTable());
JPanel bottomPnl = new JPanel();
bottomPnl.setPreferredSize(new Dimension(800, 200));
bottomPnl.setBackground(Color.RED);
splitPane.setRightComponent(bottomPnl);
splitPane.setDividerLocation(.5);
pnl.add(splitPane, BorderLayout.CENTER);
return pnl;
}
private static JTabbedPane buildGUI()
{
JTabbedPane topLevelTabbedFrame = new JTabbedPane();
topLevelTabbedFrame.addTab("Tab 1", buildTab());
topLevelTabbedFrame.addTab("Tab 2", new JPanel());
topLevelTabbedFrame.addTab("Tab 3", new JPanel());
return topLevelTabbedFrame;
}
private static void createAndShowGUI()
{
frame = new JFrame("Split Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buildGUI(), BorderLayout.CENTER);
// frame.setSize(new Dimension(800, 600));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Because of all the custom components involved, I can't actually get a small app that shows the problem, but I have the next best thing, which is an app that shows the layout that I have (of course, it doesn't actually have the same problems).
I was about to tell you the posted code workd just fine, and the I read this.
Anyway, it seems the problem lies in all the custom components you added to the mix. For JTable and JSplitPane work fine alone.
What I would do is to remove components one by one until it works ( probably I will work when the code is similar to the one posted and there is nothing else there )
Or you can go the opposite way which is easier. Start with your sample code and then add more and more components until it fail.
You can take this opportunity to refactor and clean your code and move unneeded components. And even ( why not ) add test cases in the process.
Good luck.
Have you tries running it on a different box to check if its hardware related.
May be related to this bug
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4763448
As it turns out, the problem was with the order that the components were initialized and added to the split pane. So the eventual fix was to delay adding the table to the split pane until after the split pane was actually added to the panel, rather than adding the table to the split pane before adding the split pane to the panel. Making that small change fixed the issue.

Categories