Related
I'm attempting to create a "sectioned" table, which are actually multiple tables laid out within a "scrollable" JPanel via GridBagLayout. The tables share the same table model (class), table header and column model, the JTableHeader is set as column header view of a JScrollPane that contains everything. There is only one JScrollPane.
frame (BorderLayout)
|- JScrollPane
|- JPanel (GridBagLayout)
|- Section title panel
|- JTable 1
|- Section title panel
|- JTable 2
|- JTable (fake)
|- vertical filler
Everything seemed to work as expected, until I tried to resize an arbitrary column with no values in either of the tables - if the tables had at least one row, it worked as expected. I considered having "null" rows in the table, but that interferes with filtering, sorting, etc. So I changed the code to contain an "obscured" fake table, that is meant to keep the header behaving nicely by always having one row.
This does not work however. As soon as one of the tables is empty and a column resize is attempted, the table header is corrupted (one of the columns shrinks).
Why is this happening and what can I do about it?
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class SectionTables extends JFrame {
public SectionTables() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
GridBagConstraints gbc;
JPanel tables = new ScrollableJPanel(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(tables);
JPanel section1Title = new JPanel(new BorderLayout());
section1Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section1 = new JLabel("Section One", null, JLabel.CENTER);
section1Title.add(section1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section1Title, gbc);
MyTableModel model1 = new MyTableModel();
JTable table1 = new MyTable(model1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table1, gbc);
JPanel section2Title = new JPanel(new BorderLayout());
section2Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section2 = new JLabel("Section Two", null, JLabel.CENTER);
section2Title.add(section2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section2Title, gbc);
MyTableModel model2 = new MyTableModel();
JTable table2 = new MyTable(model2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table2, gbc);
MyTableModel modelFake = new MyTableModel();
modelFake.addRow(new String[] {"", "", ""});
JTable tableFake = new MyObscuredTable();
tableFake.setModel(modelFake);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 4;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(tableFake, gbc);
Box.Filler filler1 = new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767));
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 5;
gbc.weighty = 1.0d;
gbc.fill = GridBagConstraints.VERTICAL;
tables.add(filler1, gbc);
add(scrollPane);
TableColumnModel columnModel = table1.getColumnModel();
table2.setColumnModel(columnModel);
tableFake.setColumnModel(columnModel);
JTableHeader tableHeader = new JTableHeader(columnModel);
scrollPane.setColumnHeaderView(tableHeader);
table1.setTableHeader(tableHeader);
table2.setTableHeader(tableHeader);
tableFake.setTableHeader(tableHeader);
// if tables are filled, the issue does not occur
// model1.addRow(new String[] {"", "", ""});
// model2.addRow(new String[] {"", "", ""});
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SectionTables().setVisible(true);
}
});
}
private class MyTableModel extends DefaultTableModel {
private String[] columnNames = new String[] {"First", "Second", "Third"};
private Class[] columnClasses = new Class[] {String.class, String.class, String.class};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return columnClasses[columnIndex];
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
private class ScrollableJPanel extends JPanel implements Scrollable {
public ScrollableJPanel(LayoutManager layout) {
super(layout);
}
public ScrollableJPanel() {
super();
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
private class MyObscuredTable extends JTable {
#Override
public Dimension getPreferredSize() {
int height;
height = 1; // obscure null row
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
private class MyTable extends JTable {
public MyTable(TableModel model) {
super(model);
}
#Override
public Dimension getPreferredSize() {
int height;
height = getRowHeight() * getRowCount();
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
}
Maybe you can modify this approach which uses a TableColumnModelListener to keep the column widths in sync when using multiple tables:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableColumnsShared implements Runnable
{
JTable table1, table2;
TableColumnModelListener columnListener1, columnListener2;
Map<JTable, TableColumnModelListener> map;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new TableColumnsShared());
}
public void run()
{
Vector<String> names = new Vector<String>();
names.add("One");
names.add("Two");
names.add("Three");
table1 = new JTable(null, names);
table2 = new JTable(null, names);
columnListener1 = new ColumnChangeListener(table1, table2);
columnListener2 = new ColumnChangeListener(table2, table1);
table1.getColumnModel().addColumnModelListener(columnListener1);
table2.getColumnModel().addColumnModelListener(columnListener2);
map = new HashMap<JTable, TableColumnModelListener>();
map.put(table1, columnListener1);
map.put(table2, columnListener2);
JPanel p = new JPanel(new GridLayout(2,1));
p.add(new JScrollPane(table1));
p.add(new JScrollPane(table2));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(p);
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class ColumnChangeListener implements TableColumnModelListener
{
JTable sourceTable;
JTable targetTable;
public ColumnChangeListener(JTable source, JTable target)
{
this.sourceTable = source;
this.targetTable = target;
}
public void columnAdded(TableColumnModelEvent e) {}
public void columnSelectionChanged(ListSelectionEvent e) {}
public void columnRemoved(TableColumnModelEvent e) {}
public void columnMoved(TableColumnModelEvent e) {}
public void columnMarginChanged(ChangeEvent e)
{
TableColumnModel sourceModel = sourceTable.getColumnModel();
TableColumnModel targetModel = targetTable.getColumnModel();
TableColumnModelListener listener = map.get(targetTable);
targetModel.removeColumnModelListener(listener);
for (int i = 0; i < sourceModel.getColumnCount(); i++)
{
targetModel.getColumn(i).setPreferredWidth(sourceModel.getColumn(i).getWidth());
}
targetModel.addColumnModelListener(listener);
}
}
}
Following #camickr's suggestion, ended up with this. Much more elegant that my original attempt.
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.*;
public class SectionTables extends JFrame {
private Map<JTable, TableColumnModelListener> tableToColModelListener;
public SectionTables() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
GridBagConstraints gbc;
JPanel tables = new ScrollableJPanel(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(tables);
JPanel section1Title = new JPanel(new BorderLayout());
section1Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section1 = new JLabel("Section One", null, JLabel.CENTER);
section1Title.add(section1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section1Title, gbc);
MyTableModel model1 = new MyTableModel();
JTable table1 = new MyTable(model1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table1, gbc);
JPanel section2Title = new JPanel(new BorderLayout());
section2Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section2 = new JLabel("Section Two", null, JLabel.CENTER);
section2Title.add(section2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section2Title, gbc);
MyTableModel model2 = new MyTableModel();
JTable table2 = new MyTable(model2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table2, gbc);
MyTableModel modelFake = new MyTableModel();
modelFake.addRow(new String[] {"", "", ""});
JTable tableFake = new MyObscuredTable();
tableFake.setModel(modelFake);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 4;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(tableFake, gbc);
Box.Filler filler1 = new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767));
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 5;
gbc.weighty = 1.0d;
gbc.fill = GridBagConstraints.VERTICAL;
tables.add(filler1, gbc);
add(scrollPane);
tableToColModelListener = new HashMap<JTable, TableColumnModelListener>();
scrollPane.setColumnHeaderView(tableFake.getTableHeader());
MyColumnChangeListener listener;
listener = new MyColumnChangeListener(tableFake, table1, table2);
tableFake.getColumnModel().addColumnModelListener(listener);
tableToColModelListener.put(tableFake, listener);
setSize(200, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SectionTables().setVisible(true);
}
});
}
private class MyColumnChangeListener implements TableColumnModelListener {
private JTable sourceTable;
private List<JTable> targetTables;
public MyColumnChangeListener(JTable source, JTable... targets) {
this.sourceTable = source;
if (targets.length < 1) {
throw new IllegalArgumentException();
}
this.targetTables = Arrays.asList(targets);
}
public void columnAdded(TableColumnModelEvent e) {}
public void columnRemoved(TableColumnModelEvent e) {}
public void columnMoved(TableColumnModelEvent e) {}
public void columnSelectionChanged(ListSelectionEvent e) {}
#Override
public void columnMarginChanged(ChangeEvent e) {
TableColumnModel sourceModel = sourceTable.getColumnModel();
for (JTable targetTable : targetTables) {
TableColumnModel targetModel = targetTable.getColumnModel();
TableColumnModelListener listener = tableToColModelListener.get(targetTable);
targetModel.removeColumnModelListener(listener);
try {
for (int i = 0; i < sourceModel.getColumnCount(); i++) {
targetModel.getColumn(i).setPreferredWidth(sourceModel.getColumn(i).getWidth());
}
} finally {
targetModel.addColumnModelListener(listener);
}
}
}
}
private class MyTableModel extends DefaultTableModel {
private String[] columnNames = new String[] {"First", "Second", "Third"};
private Class[] columnClasses = new Class[] {String.class, String.class, String.class};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return columnClasses[columnIndex];
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
private class ScrollableJPanel extends JPanel implements Scrollable {
public ScrollableJPanel(LayoutManager layout) {
super(layout);
}
public ScrollableJPanel() {
super();
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
private class MyObscuredTable extends JTable {
#Override
public Dimension getPreferredSize() {
int height;
height = 1; // obscure null row
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
private class MyTable extends JTable {
public MyTable(TableModel model) {
super(model);
}
#Override
public Dimension getPreferredSize() {
int height;
height = getRowHeight() * getRowCount();
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
}
In my FlashCardPanel class, I have a subpanel,LabelPanel, with a Grid Bag Layout. It consists of a constructor with an edit button, a button to "flip" the card, and the label to display the term/definition. My problem is that every time I click my "Flip" Button to display the definition of my term, the flip button will change size, usually matching the length of the definition.
Images of the problem
http://postimg.org/gallery/ymww3axq/
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class FlashCardPanel extends JPanel{
private String term;
private String definition;
// shows the current text whether it is a term or definition
private JLabel currentLabel;
private static String NO_CARDS = "This set is empty";
//current card being displayed
private FlashCard currentCard;
//new card that is added to the deck
private FlashCard newCard;
// true = term is showing; false = definition is showing
private boolean termShowing = true;
private AddNewCard frame;
private CardSet cardSet;
private int cardIndex = 0;
private ButtonPanel bPanel;
private LabelPanel lPanel;
private static JButton flipButton;
private static JButton nextButton;
private static JButton prevButton;
private static JButton addCard;
private static JButton deleteCard;
private static JButton editButton;
public FlashCardPanel(CardSet cardSet) {
this.cardSet = cardSet;
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
term = cardSet.get(0).getTerm();
definition = cardSet.get(0).getDefintion();
currentCard = cardSet.get(0);
createButtons();
lPanel = new LabelPanel();
bPanel = new ButtonPanel();
add(lPanel);
add(bPanel);
}
public FlashCardPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(lPanel);
add(bPanel);
}
private class LabelPanel extends JPanel {
public LabelPanel() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15,15,15,15);
currentLabel = new JLabel(term);
currentLabel.setText(cardSet.get(0).getTerm());
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
c.gridx = 0;
c.gridy = 0;
add(editButton,c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;
c.gridwidth = 0;
c.weightx = 0;
c.gridx = 2;
c.gridy = 0;
add(flipButton,c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;
c.weightx = 0;
c.gridwidth = 3;
c.gridx = 1;
c.gridy = 3;
add(currentLabel,c);
}
}
private class ButtonPanel extends JPanel {
public ButtonPanel() {
this.setLayout(new GridLayout(2,2));
add(prevButton);
add(nextButton);
add(addCard);
add(deleteCard);
}
}
/*
* creates buttons for the panel. Should be called before
* any subpanel is created.
*/
private void createButtons()
{
flipButton = new JButton(" Flip Card ");
flipButton.addActionListener(new ButtonListener());
flipButton.setActionCommand("1");
nextButton = new JButton(" Next Card ");
nextButton.addActionListener(new ButtonListener());
nextButton.setActionCommand("2");
prevButton = new JButton(" Previous Card ");
prevButton.addActionListener(new ButtonListener());
prevButton.setActionCommand("3");
addCard = new JButton(" Add Card ");
addCard.addActionListener(new ButtonListener());
addCard.setActionCommand("4");
deleteCard = new JButton(" Delete Card ");
deleteCard.addActionListener(new ButtonListener());
deleteCard.setActionCommand("5");
editButton = new JButton("Edit");
editButton.addActionListener(new ButtonListener());
editButton.setActionCommand("6");
}
private class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
int action = Integer.parseInt(e.getActionCommand());
switch(action){
case 1:
flipCard();
break;
case 2:
nextCard();
break;
case 3:
previousCard();
break;
case 4:
createFrame();
break;
case 5:
deleteCard();
case 6:
createFrame(term,definition);
}
}
}
private void flipCard()
{
if (!cardSet.isEmpty()) {
if (termShowing) {
termShowing = false;
currentLabel.setText(definition);
}
else {
termShowing = true;
currentLabel.setText(term);
}
}
else {
currentLabel.setText(NO_CARDS);
term = "";
definition = "";
JOptionPane.showMessageDialog(this, "This set is empty");
}
}
private void nextCard()
{
if (!cardSet.isEmpty()) {
if (cardIndex == cardSet.size()-1)
cardIndex = 0;
else
cardIndex++;
term = cardSet.get(cardIndex).getTerm();
definition = cardSet.get(cardIndex).getDefintion();
if(termShowing)
currentLabel.setText(term);
else
currentLabel.setText(definition);
currentCard = cardSet.get(cardIndex);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
private void previousCard()
{
if (!cardSet.isEmpty()) {
if (cardIndex == 0)
cardIndex = cardSet.size()-1;
else
cardIndex--;
term = cardSet.get(cardIndex).getTerm();
definition = cardSet.get(cardIndex).getDefintion();
if(termShowing)
currentLabel.setText(term);
else
currentLabel.setText(definition);
currentCard = cardSet.get(cardIndex);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
/*
* adding a card
*/
private void createFrame() {
frame = new AddNewCard(100,100,this);
}
/*
* editing an existing card
*/
private void createFrame(String t, String d)
{
frame = new AddNewCard(100,100,this,t,d);
}
public void addNewCard(String t, String d) {
newCard = new FlashCard(t,d);
cardSet.add(newCard);
if (cardSet.isEmpty()) currentLabel.setText(newCard.getTerm());
}
public void editCard(String t, String d) {
currentCard.setTerm(t);
currentCard.setDefinition(d);
if (termShowing) currentLabel.setText(t);
else currentLabel.setText(d);
}
/*
* Deletes current card on display
*/
private void deleteCard()
{
if (!cardSet.isEmpty()) {
// if on the last card of the set
if (cardIndex == cardSet.size()-1) cardIndex--;
cardSet.remove(currentCard);
if (!cardSet.isEmpty()) {
currentCard = cardSet.get(cardIndex);
currentLabel.setText(cardSet.get(cardIndex).getTerm());
}
else currentLabel.setText(NO_CARDS);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
}
You have several options including:
using a nested JPanels each with its own layout. For instance the buttons could be placed into a GridLayout JPanel, and this placed into a BorderLayout JPanel with the label BorderLayout.CENTER
I suggest that the long definition text be displayed within a JTextArea, not a JLabel. If you make it non-editable and remove borders, it could look like a JLabel.
If you go this route, you will want to turn on word wrap on the JTextArea.
You could swap JTextArea with JLabel (for the term) using a CardLayout.
Note, for future questions, please pare down your problem. For instance, if this were my question, I'd create something like the code below, small, self contained, runnable and demonstrates the problem:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class FlashCardPanel2 extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JLabel currentLabel;
private String term = "Term";
private String definition = "Definition: This will be a very long String to "
+ "illustrate the problem that you are having, and to try to help you get "
+ "a solution";
private JButton editButton = new JButton("Edit");
private JButton flipButton = new JButton(new FlipAction("Flip"));
public FlashCardPanel2() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15, 15, 15, 15);
currentLabel = new JLabel(term);
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
c.gridx = 0;
c.gridy = 0;
add(editButton, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;
c.gridwidth = 0;
c.weightx = 0;
c.gridx = 2;
c.gridy = 0;
add(flipButton, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;
c.weightx = 0;
c.gridwidth = 3;
c.gridx = 1;
c.gridy = 3;
add(currentLabel, c);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class FlipAction extends AbstractAction {
public FlipAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = currentLabel.getText();
text = (text.equals(term)) ? definition : term;
currentLabel.setText(text);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FlashCardPanel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FlashCardPanel2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
And here's a potential solution with CardLayout and GridLayout and BorderLayout:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class FlashCardPanel3 extends JPanel {
private static final long serialVersionUID = 1L;
private static final String CURRENT_LABEL = "current label";
private static final String DEFINITION = "definition";
private JLabel currentLabel;
private JTextArea currentDefinitionArea = new JTextArea(6, 20);
private CardLayout cardLayout = new CardLayout();
private JPanel cardHolder = new JPanel(cardLayout);
private String term = "Term";
private String definition = "Definition: This will be a very long String to "
+ "illustrate the problem that you are having, and to try to help you get "
+ "a solution";
private JButton editButton = new JButton("Edit");
private JButton flipButton = new JButton(new FlipAction("Flip"));
public FlashCardPanel3() {
currentDefinitionArea.setOpaque(false);
currentDefinitionArea.setText(definition);
currentDefinitionArea.setWrapStyleWord(true);
currentDefinitionArea.setLineWrap(true);
currentDefinitionArea.setEditable(false);
currentDefinitionArea.setFocusable(false);
currentLabel = new JLabel(term, SwingConstants.CENTER);
cardHolder.add(currentLabel, CURRENT_LABEL);
cardHolder.add(new JScrollPane(currentDefinitionArea), DEFINITION);
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 0));
buttonPanel.add(editButton);
buttonPanel.add(flipButton);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(buttonPanel, BorderLayout.PAGE_START);
add(cardHolder);
}
private class FlipAction extends AbstractAction {
public FlipAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// String text = currentLabel.getText();
// text = (text.equals(term)) ? definition : term;
// currentLabel.setText(text);
cardLayout.next(cardHolder);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FlashCardPanel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FlashCardPanel3());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I am trying to accomplish the following with GridBagLayout:
The frame will receive a collection of "fields" (JLabel, JTextField pairs), I want to arrange them in a 'Grid-like' fashion where a row will contain 2 such pairs (JLabel1 JField1 JLabel2 JField2). When a row has these four components, the next components are added to another row.
EDIT: I would like the components to start at the top of the panel
My code produces the following layout. I would like the components to be laid out more compactly (especially the vertical distance)
Here is the code:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Test extends JFrame{
private JPanel _panel;
public Test() {
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
this.setResizable(true);
this.setVisible(true);
Dimension size = new Dimension(600,600);
this.setMinimumSize(size);
this.setSize(size);
this.setPreferredSize(size);
_panel = new JPanel();
this.add(_panel);
}
public static void main(String[] args) {
Test t = new Test();
String[] labels = {"label1", "label2","label3","label4","label5"};
String[] fieldValues = {"value1","value2","value3","value4","value5"};
t.createFields(labels,fieldValues);
}
private void createFields(String[] labels, String[] fieldValues) {
_panel.setLayout(new GridBagLayout());
int col = 0;
int row = -1;
for(int i=0; i < labels.length;i++) {
JLabel label = new JLabel(labels[i] + ":", JLabel.TRAILING);
JTextField field = new JTextField(fieldValues[i]);
Dimension size = new Dimension(200,30);
field.setPreferredSize(size);
label.setLabelFor(field);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weighty = 1;
c.weightx = 1;
c.ipadx = 0;
c.ipady = 0;
c.insets = new Insets(0,0,0,0);
c.anchor = GridBagConstraints.LINE_START;
c.gridx = col%4;
if(i%2 == 0) row++;
c.gridy = row;
_panel.add(label,c);
col++;
c.gridx = col%4;
_panel.add(field,c);
col++;
}
this.setVisible(true);
}
If you don't mind your elements being in center of panel (vertically and horizontally), then remove
c.weighty = 1;
c.weightx = 1;
from your code.
If center is wrong place, add
GridBagConstraints c = new GridBagConstraints();
c.gridx=4;
c.gridy=labels.length;
c.weightx=1;
c.weighty=1;
_panel.add(new JLabel(),c);
after your loop
If you want your GUI to be that size, but have the components in a compact size, then place them in their own JPanel, one that uses GridBagLayout, and then add that JPanel to your main GUI JPanel. If you want the components to fill the width, then have the main JPanel use BorderLayout, and add your GBL using JPanel BorderLayout.NORTH or .SOUTH whatever your need is.
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class GridBagExample extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
public GridBagExample() {
super(new BorderLayout());
add(new GridBagUsingPanel(), BorderLayout.NORTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("GridBagExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GridBagExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class GridBagUsingPanel extends JPanel {
public static final int COLUMNS = 2;
public static final int ROWS = 3;
private static final int TF_COLS = 10;
private static int inset = 5;
private static final Insets INSETS = new Insets(inset, inset, inset, inset);
private static final Insets EXTRA_INSETS = new Insets(inset, inset, inset, 8 * inset);
private static final int EB_GAP = 10;
public GridBagUsingPanel() {
super(new GridBagLayout());
setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
for (int r = 0; r < ROWS; r++) {
for (int c = 0; c < COLUMNS; c++) {
addComponent(r, c);
}
}
}
private void addComponent(int r, int c) {
int count = 1 + r * COLUMNS + c;
JLabel label = new JLabel("label " + count);
JTextField textField = new JTextField("value " + count, TF_COLS);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 2 * c;
gbc.gridy = r;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.insets = INSETS;
gbc.weightx = 0.1;
gbc.weighty = 1.0;
add(label, gbc);
gbc.gridx++;
gbc.anchor = GridBagConstraints.EAST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
if (c != COLUMNS - 1) {
gbc.insets = EXTRA_INSETS;
}
add(textField, gbc);
}
}
I have a basic gui (it doesn't need to look pretty, it just needs to work. It's a gui to display several algorithms I'm implementing for my thesis.) but the checkboxes and button won't show up randomly. Sometimes they appear, sometimes they don't. I honestly have no clue why this could be happening and I'm pretty scrub at swing, so I'm lost.
EDIT: Here's what i want my gui to look like:
//import java.awt.*;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;
import javax.swing.ButtonGroup;
import javax.swing.*; //notice javax
public class MapWindowController extends JFrame implements ActionListener, ItemListener
{
private static final int WIDTH = 600, HEIGHT = 800;
private static final int SETTINGS_WIDTH = 600, SETTINGS_HEIGHT = 200;
private static final int NUM_MAP_TYPE = 2;
private static final int NUM_ALGORITHM_TYPE = 4;
private static final int MAP_IMAGE_SIZE = 400, ACTUAL_MAP_SIZE = 10;
private JButton run;
private JCheckBox[] map_type;
private JCheckBox[] algorithm_type;
JPanel panel = new JPanel();
JPanel settings_panel = new JPanel();
MapView map_view = new MapView(MAP_IMAGE_SIZE);
SettingsButtonsPanel settings = new SettingsButtonsPanel();
MapModel map_model = new MapModel(ACTUAL_MAP_SIZE, map_view);
ButtonGroup bgMap;
ButtonGroup bgAlgorithm;
public MapWindowController()
{
setLocationRelativeTo(null);
setTitle("HPA* Test");
setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(panel);
panel.setBounds(0, 0, 600, 800);
panel.setLayout(null);
/*GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;*/
instantiateSettingsPanel();
//panel.add(settings);
/*c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;*/
panel.add(map_view);
map_view.setBounds(0,200,600,600);
//button_panel.setBounds(0,0);
map_view.repaint();
}
public void instantiateSettingsPanel() {
settings_panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//this.setLayout(null);
map_type = new JCheckBox[NUM_MAP_TYPE];
map_type[0] = new JCheckBox("Sparse");
map_type[0].setSelected(true);
map_type[1] = new JCheckBox("Maze");
map_type[1].setSelected(false);
algorithm_type = new JCheckBox[NUM_ALGORITHM_TYPE];
algorithm_type[0] = new JCheckBox("A*");
algorithm_type[0].setSelected(true);
algorithm_type[1] = new JCheckBox("HPA*");
algorithm_type[1].setSelected(false);
algorithm_type[2] = new JCheckBox("TA*");
algorithm_type[2].setSelected(true);
algorithm_type[3] = new JCheckBox("PTHPA*");
algorithm_type[3].setSelected(false);
bgMap = new ButtonGroup( );
bgAlgorithm = new ButtonGroup( );
settings_panel.setMaximumSize(new Dimension(600,200));
for(int i = 0; i < NUM_MAP_TYPE; i++)
{
bgMap.add(map_type[i]);
map_type[i].addItemListener(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = i+1;
settings_panel.add(map_type[i], c);
}
for(int i = 0; i < NUM_ALGORITHM_TYPE; i++)
{
bgAlgorithm.add(algorithm_type[i]);
algorithm_type[i].addItemListener(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = i+1;
settings_panel.add(algorithm_type[i], c);
}
run = new JButton("Run");
run.addActionListener(this);
settings_panel.add(run);
panel.add(settings_panel);
settings_panel.setBounds(0,0,SETTINGS_WIDTH,SETTINGS_HEIGHT);
}
public void itemStateChanged(ItemEvent e)
{
Object source = e.getItemSelectable();
//if(source == )
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String algorithm = "A*";
String map = "Sparse";
for(int i = 0; i < algorithm_type.length; i++) {
if(algorithm_type[i].isSelected()) {
algorithm = algorithm_type[i].getText();
break;
}
}
for(int i = 0; i < map_type.length; i++) {
if(map_type[i].isSelected()) {
map = map_type[i].getText();
break;
}
}
if(source == run) {
if(map.equals("Sparse"))
map_model.createRandomObstaclesSparse(10, 1);
else
map_model.createRandomObstaclesMaze(1);
map_model.startPathfinding(algorithm, 0, true);
map_view.setMapScale(ACTUAL_MAP_SIZE);
map_view.setMapModel(map_model);
}
}
}
Your first mistake is using a null layout, your second mistake is calling setVisible before the UI is completed.
Your basic idea is sound, separating the various areas of responsibility into separate components, this will make you life much easier.
Basically, I used a GridBagLayout as it allows you to define fill weights for each component, providing a 1/4 of the vertical space to the buttons and the remainder to the map...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MapWindowController extends JFrame implements ActionListener, ItemListener {
private static final int WIDTH = 600, HEIGHT = 800;
private static final int SETTINGS_WIDTH = 600, SETTINGS_HEIGHT = 200;
private static final int NUM_MAP_TYPE = 2;
private static final int NUM_ALGORITHM_TYPE = 4;
private static final int MAP_IMAGE_SIZE = 400, ACTUAL_MAP_SIZE = 10;
private JButton run;
private JCheckBox[] map_type;
private JCheckBox[] algorithm_type;
JPanel content = new JPanel();
JPanel settings_panel = new JPanel();
private JPanel mapPane = new JPanel(new BorderLayout());
ButtonGroup bgMap;
ButtonGroup bgAlgorithm;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
new MapWindowController();
}
});
}
public MapWindowController() {
setLocationRelativeTo(null);
setTitle("HPA* Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
content.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 0.25;
gbc.weightx = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
content.add(settings_panel, gbc);
gbc.gridy++;
gbc.weighty = 0.75;
content.add(mapPane, gbc);
try {
mapPane.add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/Map.png")))));
} catch (IOException ex) {
ex.printStackTrace();
}
add(content);
/*GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;*/
instantiateSettingsPanel();
//panel.add(settings);
/*c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;*/
pack();
setLocationByPlatform(true);
setVisible(true);
}
public void instantiateSettingsPanel() {
settings_panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//this.setLayout(null);
map_type = new JCheckBox[NUM_MAP_TYPE];
map_type[0] = new JCheckBox("Sparse");
map_type[0].setSelected(true);
map_type[1] = new JCheckBox("Maze");
map_type[1].setSelected(false);
algorithm_type = new JCheckBox[NUM_ALGORITHM_TYPE];
algorithm_type[0] = new JCheckBox("A*");
algorithm_type[0].setSelected(true);
algorithm_type[1] = new JCheckBox("HPA*");
algorithm_type[1].setSelected(false);
algorithm_type[2] = new JCheckBox("TA*");
algorithm_type[2].setSelected(true);
algorithm_type[3] = new JCheckBox("PTHPA*");
algorithm_type[3].setSelected(false);
bgMap = new ButtonGroup();
bgAlgorithm = new ButtonGroup();
settings_panel.setMaximumSize(new Dimension(600, 200));
for (int i = 0; i < NUM_MAP_TYPE; i++) {
bgMap.add(map_type[i]);
map_type[i].addItemListener(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = i + 1;
settings_panel.add(map_type[i], c);
}
for (int i = 0; i < NUM_ALGORITHM_TYPE; i++) {
bgAlgorithm.add(algorithm_type[i]);
algorithm_type[i].addItemListener(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = i + 1;
settings_panel.add(algorithm_type[i], c);
}
run = new JButton("Run");
run.addActionListener(this);
settings_panel.add(run);
}
public void itemStateChanged(ItemEvent e) {
Object source = e.getItemSelectable();
//if(source == )
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String algorithm = "A*";
String map = "Sparse";
for (int i = 0; i < algorithm_type.length; i++) {
if (algorithm_type[i].isSelected()) {
algorithm = algorithm_type[i].getText();
break;
}
}
for (int i = 0; i < map_type.length; i++) {
if (map_type[i].isSelected()) {
map = map_type[i].getText();
break;
}
}
if (source == run) {
// if (map.equals("Sparse")) {
// map_model.createRandomObstaclesSparse(10, 1);
// } else {
// map_model.createRandomObstaclesMaze(1);
// }
// map_model.startPathfinding(algorithm, 0, true);
// map_view.setMapScale(ACTUAL_MAP_SIZE);
// map_view.setMapModel(map_model);
}
}
}
Don't use setSize of setBounds on a window, instead, use pack to automatically set the optimal size of the window based on it's contents preferred size.
The program consists of a tabbed view with a few JTextField's and JButtons in the first two and 2 JTables and JButton in the third. The buttons work fine in the first two tabs, but on the third it is un-clickable. I tried changing the button to something else like a JComboBox or JTextField but those are uneditable and unclickable also. Setting the setEnabled() and setEditable() functions to true doesn't seem to work. I have no idea what's going on.
The only thing i have done different from normal is this piece of code to forcefully repaint the tab when I click on a cell in the table. But even when this hasn't been called i still cant
ContentIWantToRepaint.this.paintImmediately(ContentIWantToRepaint.this.getVisibleRect());
Some other information about the layout:
The contents of the tab are held in a JPanel with a GridBagLayout
JTextField
Table Header
Table Contents
JTextField
Table Header
Table Contents
Button
Any suggestions?
checkOutPanel.java
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.table.DefaultTableModel;
public class checkOutPanel extends JPanel {
private JTable userTable;
private JTable bookTable;
private JScrollPane scrollUserTable, scrollBookTable;
private JLabel userLabel, bookLabel;
private DefaultTableModel userTableModel = new DefaultTableModel(){
public boolean isCellEditable(int row, int column){return false;}
};
private DefaultTableModel bookTableModel = new DefaultTableModel(){
public boolean isCellEditable(int row, int column){return false;}
};
private int selectedUser, selectedBook;
private JComboBox date_month, date_day, date_year;
public checkOutPanel(){
JPanel mainGrid = new JPanel();//panel that will hold all stuff in tab
JPanel buttonPanel = new JPanel();//panel for holding buttons
mainGrid.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx=0; c.gridy=0; //first row first column
c.anchor = GridBagConstraints.WEST;//align left
c.fill = GridBagConstraints.HORIZONTAL;
//1 row, 2 columns, 15 horizontal padding, 0 vertical padding
//buttonPanel.setLayout(new GridLayout(1,2,15,0));
//labels to describe what the user has to do
userLabel = new JLabel("User :");
bookLabel = new JLabel("Book :");
JLabel dateLabel = new JLabel("Date :");
JPanel datePanel = new JPanel();
bookTable = new JTable(bookTableModel);
bookTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
userTable = new JTable(userTableModel);
userTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
Dimension d = new Dimension(500, 120);
scrollBookTable = new JScrollPane(bookTable);
scrollBookTable.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollBookTable.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollBookTable.setMaximumSize(d);
scrollBookTable.setMinimumSize(d);
scrollBookTable.setPreferredSize(d);
scrollUserTable = new JScrollPane(userTable);
scrollUserTable.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollUserTable.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollUserTable.setMaximumSize(d);
scrollUserTable.setMinimumSize(d);
scrollUserTable.setPreferredSize(d);
updateTables();
//String[] month = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
//Vector<Integer> days = new Vector<Integer>();
//for (int i=1 ; i<=31 ; i++) { days.add(i); }
//Vector<Integer> years = new Vector<Integer>();
//for (int i=2012 ; i>=1900 ; i--) { years.add(i); }
//date_month = new JComboBox(days);
JButton testButton = new JButton("WORK!!!!!!!");
//date_day = new JTextField(6);
//date_year = new JTextField(6);
//datePanel.add(dateLabel);
//datePanel.add(date_month);
//datePanel.add(date_day);
//datePanel.add(date_year);
mainGrid.add(userLabel, c); c.gridy++;
mainGrid.add(userTable.getTableHeader(), c); c.gridy++;
mainGrid.add(scrollUserTable, c); c.gridy++;
c.insets = new Insets(15, 0, 0, 0);//put some padding between users and books
mainGrid.add(bookLabel, c); c.gridy++;
c.insets= new Insets(0,0,0,0);//back to no padding
mainGrid.add(bookTable.getTableHeader(), c); c.gridy++;
mainGrid.add(scrollBookTable, c); c.gridy++;
c.insets = new Insets(15, 0, 0, 0);//put some padding between books and date
mainGrid.add(testButton, c); c.gridy++;
this.add(mainGrid);//add contents to tab
userTable.addMouseListener(new mouseListener());
bookTable.addMouseListener(new mouseListener());
}
public class mouseListener implements MouseListener{
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {
if(e.getSource()==userTable){
selectedUser=userTable.getSelectedRow();
userLabel.setText("User : "+ (selectedUser!=-1 ? selectedUser : ""));
//don't know why i should need to use this, but it makes it work
checkOutPanel.this.paintImmediately(checkOutPanel.this.getVisibleRect());
}else if(e.getSource()==bookTable){
selectedBook = bookTable.getSelectedRow();
System.out.println("Date Month : "+date_month.getSelectedItem().toString());
bookLabel.setText("Book : "+ (selectedBook!=-1 ? selectedBook : ""));
//don't know why i should need to use this, but it makes it work
checkOutPanel.this.paintImmediately(checkOutPanel.this.getVisibleRect());
}
}
}
private void updateTables(){
bookTableModel.setDataVector(fillBookData(SystemStart.getDbName()), fillBookColNames());
userTableModel.setDataVector(fillUserData(SystemStart.getDbName()), fillUserColNames());
}
private Vector<String> fillUserColNames(){
Vector<String> colNames = new Vector<String>();
colNames.add("ID");
colNames.add("First");
colNames.add("Last");
colNames.add("Phone");
colNames.add("Email");
colNames.add("Address");
colNames.add("City");
colNames.add("State");
colNames.add("Zip");
return colNames;
}
private Vector<String> fillBookColNames(){
Vector<String> colNames = new Vector<String>();
colNames.add("Title");
colNames.add("Format");
colNames.add("Author");
colNames.add("ISBN");
colNames.add("Year Pub.");
colNames.add("Publisher");
colNames.add("Call #");
colNames.add("Copy #");
return colNames;
}
private Vector<Vector<String>> fillUserData(String dbName){
Vector<Vector<String>> v = new Vector<Vector<String>>();
Vector<String> u;
for (int i=0; i<10; i++){
u = new Vector<String>(9);
u.add(""+i);
u.add("First");
u.add("Last");
u.add("Phone");
u.add("Email");
u.add("Address");
u.add("City");
u.add("State");
u.add("Zip");
v.add(u);
}
return v;
}
private Vector<Vector<String>> fillBookData(String dbName) {
Vector<Vector<String>> v = new Vector<Vector<String>>();
Vector<String> b;
for (int i=0; i<10; i++){//only include books that arent check out
b = new Vector<String>(8);
b.add("Title "+i);
b.add("Format");
b.add("Author");
b.add("ISBN");
b.add("Year Pub.");
b.add("Publisher");
b.add("Call #");
b.add("Copy #");
v.add(b);
}
return v;
}
}
Use this file to see how it doesn't work:
import javax.swing.JFrame;
public class SystemStart{
private static String dbName = "dbnamehere.db";
public static void main(String[] args) {
//new TabbedFrame("Libary System");
JFrame jf = new JFrame("WORK!");
jf.add(new checkOutPanel());
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static String getDbName(){return dbName;}
}
You're adding to the panel a label, then the table's header and then the scrollpane which contains the table (...and the table header). Remove the two lines where you're adding to mainGrid the table headers (you should just add the scrollpanes):
mainGrid.add(userTable.getTableHeader(), c); c.gridy++;
mainGrid.add(bookTable.getTableHeader(), c); c.gridy++;
Your button will work now.