JTable in JPanel Not Displaying - java

I don't understand where is the problem. The JTable is embedded in a JScrollPanel which is embedded in a JPanel. The table is not displaying. Any help appreciated. I probably missed to add some elements. Checked thoroughly but cannot find anything. This is just the constructor:
public TableIssues() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 894, 597);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JPanel patientsPanel = new JPanel();
patientsPanel.setBounds(6, 152, 882, 417);
patientsPanel.setLayout(null);
String[] patientsColumns = {
"one",
"two",
"three"};
String[][] tableInput={{"first","second","third"},{"first","second","third"}};
patientsTable = new JTable(tableInput,patientsColumns);
JScrollPane scroll = new JScrollPane();
scroll.setBounds(0, 0, 882, 363);
scroll.setLayout(null);
scroll.setViewportView(patientsTable);
patientsPanel.add(scroll);
JButton addPatietsButton = new JButton("Add");
addPatietsButton.setFont(new Font("Lucida Grande", Font.PLAIN, 20));
addPatietsButton.setBounds(356, 375, 211, 36);
patientsPanel.add(addPatietsButton);
contentPane.add(patientsPanel);
}

NEVER do this:
scroll.setLayout(null);
You ruin the JScrollPane's layout, and so it completely loses its functionality, thereby shooting yourself in the foot. Remove that line.
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For example, this GUI
is created by this code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class TableIssues2 extends JPanel {
private static final int GAP = 5;
private static final String[] COL_NAMES = {"One", "Two", "Three"};
private DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0);
private JTable patientsTable = new JTable(model);
public TableIssues2() {
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
buttonPanel.add(new JButton("Add"));
buttonPanel.add(new JButton("Remove"));
buttonPanel.add(new JButton("Exit"));
JPanel bottomPanel = new JPanel();
bottomPanel.add(buttonPanel);
for (int i = 0; i < 5; i++) {
model.addRow(new String[]{"First", "Second", "Third"});
}
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(new JScrollPane(patientsTable), BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
TableIssues2 mainPanel = new TableIssues2();
JFrame frame = new JFrame("TableIssues2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Related

Can't position Buttons or JLabels

I am new to working with GUI's in Java and I am having a problem moving my text and buttons around. No matter what coordinates I give my button or any of the other JLabel it doesn't move, I was wondering how I could fix it this in such a way that I can place my components where ever I want on the JPanel
public class IntroPage extends JFrame {
public static void main(String[] args) {
IntroPage main = new IntroPage();
main.setVisible(true);
}
private JPanel contentPane;
public IntroPage (){
//make sure the program exits when the frame closes
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Welcome");
contentPane = new JPanel();
setSize(400,700);
//This will center the JFrame in the middle of the screen
setLocationRelativeTo(null);
//Welcome Page stuff :D
JLabel ApplauseLabel = new JLabel("Welcome to U.X.Dot.X");
ApplauseLabel.setFont(new Font("Gill Sans MT", Font.PLAIN, 30));
ApplauseLabel.setLocation(100, 50);
contentPane.add(ApplauseLabel);
JLabel slogan = new JLabel("Register below");
slogan.setFont(new Font("Gill Sans MT", Font.PLAIN, 15));
slogan.setLocation(100, 400);
contentPane.add(slogan);
//FacebookSignUp.
JButton FBbutton = new JButton("Login With FaceBook");
FBbutton.setBackground(Color.BLUE);
FBbutton.setSize(50,50);
FBbutton.setLocation(20, 40);
FBbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Add JPanel to go to FB API. Much later
}
});
contentPane.add(FBbutton);
add(contentPane);
//make sure the JFrame is visible
setVisible(true);
}
}
You're ignoring the layout managers of your contentPane JPanel. Understand that it uses FlowLayout by default, and will ignore your setLocation and setBounds statements. Ror the JPanel to accept absolute positioning, you would have to give it a null layout via contentPane.setLayout(null).
Having said that, I do not advise you to do this! While null layouts, setLocation(...) and setBounds(...) might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For example the following GUI
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import javax.swing.*;
public class IntroPage2 extends JPanel {
public static final String TITLE = "Welcome to U.X.Dot.X";
private JLabel welcomeLabel = new JLabel(TITLE, SwingConstants.CENTER);
private JButton fbButton = new JButton("Login With Facebook");
public IntroPage2() {
fbButton.setBackground(Color.BLUE);
fbButton.setForeground(Color.CYAN);
welcomeLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 30));
int wlGap = 20;
welcomeLabel.setBorder(BorderFactory.createEmptyBorder(wlGap, wlGap, wlGap, wlGap));
JLabel registerBelowLabel = new JLabel("Register Below");
registerBelowLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 15));
JPanel centralPanel = new JPanel(new GridBagLayout());
centralPanel.setPreferredSize(new Dimension(300, 600));
centralPanel.add(registerBelowLabel);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(fbButton, BorderLayout.LINE_START);
topPanel.add(welcomeLabel, BorderLayout.CENTER);
setLayout(new BorderLayout());
int ebGap = 8;
setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
add(topPanel, BorderLayout.PAGE_START);
add(centralPanel, BorderLayout.CENTER);
}
private static void createAndShowGui() {
IntroPage2 mainPanel = new IntroPage2();
JFrame frame = new JFrame("Welcome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
would create something like:

Java panel alignment

class CipherGUIFrame extends JFrame {
public CipherGUIFrame() {
super("Caesar Cipher GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 600);
JTextArea area1 = new JTextArea();
JTextArea area2 = new JTextArea();
JSpinner myspinner=new JSpinner();
JPanel mainframe = new JPanel();
mainframe.setLayout(new BoxLayout(mainframe, BoxLayout.Y_AXIS));
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
p1.setBorder(BorderFactory.createTitledBorder("Cleartext"));
p2.setBorder(BorderFactory.createTitledBorder("Spinner"));
p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
p3.setBorder(BorderFactory.createTitledBorder("Ciphertext"));
p1.add(area1);
p2.add(myspinner);
p3.add(area2);
mainframe.add(p1);
mainframe.add(p2);
mainframe.add(p3);
this.add(mainframe);
}
}
It seems that this code produces something which looks similar to this:
I am trying to tidy this up so it looks cleaner; is there a way to shrink the middle panel or to make the others bigger to make it look nicer?
Don't set the sizes of anything, but instead set the columns and rows of your JTextAreas. Don't use BoxLayout when you don't want its behaviors. Put your JTextAreas in JScrollPanes instead. And don't forget to pack() your JFrame.
import java.awt.BorderLayout;
import javax.swing.*;
public class Cipher2 extends JPanel {
public static final int ROWS = 12;
public static final int COLS = 30;
private JTextArea textArea1 = new JTextArea(ROWS, COLS);
private JTextArea textArea2 = new JTextArea(ROWS, COLS);
public Cipher2() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); // Box OK here
JScrollPane scroll1 = new JScrollPane(textArea1);
add(wrapComponentWithTitle(scroll1, "Fubar"), BorderLayout.PAGE_START);
add(wrapComponentWithTitle(new JSpinner(), "Spinner"), BorderLayout.CENTER);
scroll1 = new JScrollPane(textArea2);
add(wrapComponentWithTitle(scroll1, "Snafu"), BorderLayout.PAGE_END);
}
private JPanel wrapComponentWithTitle(JComponent component, String title) {
// BoxLayout NOT OK here. Use BorderLayout instead
JPanel wrapPanel = new JPanel(new BorderLayout());
wrapPanel.add(component);
wrapPanel.setBorder(BorderFactory.createTitledBorder(title));
return wrapPanel;
}
private static void createAndShowGui() {
Cipher2 mainPanel = new Cipher2();
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I figured out the answer: change Y_AXIS to X_AXIS.
<3

Issues setting the layout in JFrame

i am trying to set the text box and label in panel but the text box is getting inappropriate size and the layout is also not setting properly
public class FrameLayout1 implements ActionListener {
JTextField[] txtName;
JLabel[] lblname;
JCheckBox keyButton;
JCheckBox cascadeButton;
JComboBox SetList;
JComboBox ClassList;
JLabel[] lblType;
JTextField txtJoinColumn;
JLabel[] lblAssoType;
JTextField[] txtJoinColumnAssoc;
FrameLayout1(){
}
public void setDetailsPanel()
{
txtName = new JTextField[10];
txtJoinColumnAssoc = new JTextField[10];
lblname=new JLabel[10];
lblType=new JLabel[10];
lblAssoType=new JLabel[20];
JFrame ColumnFrame=new JFrame("Enter the Column Values");
int i=0;
JPanel panel = new JPanel(new GridLayout(0,1,5,10));
for (i=0;i<5;i++)
{
JPanel panelTxtLbl = new JPanel(new GridLayout(0,2));
lblname[i] = new JLabel("label"+i+":", JLabel.LEFT);
panelTxtLbl.add(lblname[i]);
txtName[i] = new JTextField(15);
panelTxtLbl.add(txtName[i]);
panel.add(panelTxtLbl);
lblType[i] = new JLabel("labeldata", JLabel.LEFT);
panel.add(lblType[i]);
String[] SetStrings = { "One to Many","Many to Many" };
SetList = new JComboBox(SetStrings);
SetList.setSelectedIndex(1);
panel.add(SetList);
cascadeButton = new JCheckBox("cascade");
cascadeButton.setSelected(true);
panel.add(cascadeButton);
JPanel panelSetClass = new JPanel(new GridLayout(0,2));
for(int j=0;j<3;j++)
{
lblAssoType[j]=new JLabel("Label Inner"+j+":", JLabel.LEFT);
panelSetClass.add(lblAssoType[j]);
txtJoinColumnAssoc[j] = new JTextField(15);
panelSetClass.add(txtJoinColumnAssoc[j]);
}
panel.add(panelSetClass);
panel.add(createHorizontalSeparator());
}
//detailsPanel.add(panel, BorderLayout.CENTER);
//detailsPanel.setAutoscrolls(true);
panel.setAutoscrolls(true);
JButton button = new JButton("Submit");
button.addActionListener(this);
//detailsPanel.add(button,BorderLayout.PAGE_END);
panel.add(button,BorderLayout.PAGE_END);
Color c=new Color(205, 222, 216);
ColumnFrame.setLayout(new BorderLayout());
ColumnFrame.add(panel,BorderLayout.CENTER);
//ColumnFrame.setSize(700,600);
ColumnFrame.setBackground(c);
ColumnFrame.pack();
ColumnFrame.setVisible(true);
ColumnFrame.setLocation(200, 200);
}
/*
* to add a horizontal line in the panel
*/
static JComponent createHorizontalSeparator() {
JSeparator x = new JSeparator(SwingConstants.HORIZONTAL);
x.setPreferredSize(new Dimension(3,2));
return x;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
createHorizontalSeparator function helps you add a horizontal line in the panel, as i was unable to segregate the fields .
current output
desired output
Today, I answered a similar question where GridLayout caused much the same
confusion. Do yourself a service and use a flexible layout manager
(if it is possible) like MigLayout to create your layouts. These
simple built-in layout managers either have very limited application
(GridLayout, FlowLayout, BorderLayout) or it can become challenging
to create sofisticated layouts with them (BoxLayout).
GridLayout and BorderLayout stretch their components and do not
honour the size bounds of their children. This is the reason why you
have those unnecessary spaces and why the button is expanded horizontally.
The following is an example that mimics your layout. It is created with
the powerful MigLayout manager.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class DetailsPanel extends JFrame {
public DetailsPanel() {
initUI();
setTitle("Details");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("ins 10, wrap 2", "[][grow]"));
add(new JLabel("Label 1:"));
add(new JTextField(), "w 200, growx");
add(new JLabel("Label 2:"));
add(new JTextField(), "growx");
add(new JLabel("Label 3:"));
add(new JTextField(), "gaptop 30, growx");
add(new JLabel("Label 4:"));
add(new JTextField(), "growx");
add(new JLabel("Label 5:"));
add(new JTextField(), "gaptop 30, growx");
add(new JLabel("Label 6:"));
add(new JTextField(), "growx");
add(new JButton("Submit"), "gaptop 30, skip, right");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DetailsPanel ex = new DetailsPanel();
ex.setVisible(true);
}
});
}
}
You need to dedicate some time to learn a more complex layout manager, but
it pays off. Especially, if you often build layouts in Swing.

Keep BoxLayout From Expanding Children

I want to stack some JComponents vertically inside a JPanel so they stack at the top and any extra space is at the bottom. I'm using a BoxLayout. The components will each contain a JTextArea that should allow the text to wrap if necessary. So, basically, I want the height of each of these components to be the minimum necessary for displaying the (possibly wrapped) text.
Here's a contained code example of what I'm doing:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args){
new TextAreaTester();
}
public TextAreaTester(){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.PAGE_AXIS));
panel.setPreferredSize(new Dimension(100,400));
for(int i = 0; i<3; i++){
JPanel item = new JPanel(new BorderLayout());
JTextArea textarea = new JTextArea("this is a line of text I want to wrap if necessary");
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
textarea.setMaximumSize( textarea.getPreferredSize() );
item.add(textarea,BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
frame.add(panel);
frame.setVisible(true);
frame.pack();
}
}
The child JPanels are expanding to fill the vertical space. I tried using glue because I thought that's what glue was for, but it seems to do nothing at all. Any help?
Note: I have found questions that look almost identical, but none with answers I can apply.
One solution: nest JPanels with the outer JPanel using Borderlayout and adding the BoxLayout using JPanel to this one BorderLayout.NORTH, also known as BorderLayout.PAGE_START:
Edit for Kleopatra:
import javax.swing.*;
import java.awt.*;
public class TextAreaTester {
public static void main(String[] args) {
new TextAreaTester();
}
public TextAreaTester() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
// panel.setPreferredSize(new Dimension(100,400));
for (int i = 0; i < 3; i++) {
JPanel item = new JPanel(new BorderLayout());
// item.setLayout(new BoxLayout(item,BoxLayout.LINE_AXIS));
JTextArea textarea = new JTextArea(
"this is a line of text I want to wrap if necessary", 3, 35);
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
// textarea.setMaximumSize(textarea.getPreferredSize());
// item.setMaximumSize( item.getPreferredSize() );
item.add(new JScrollPane(textarea), BorderLayout.NORTH);
panel.add(item);
}
panel.add(Box.createGlue());
JPanel mainPanel = new JPanel(new BorderLayout()) {
private final int prefW = 100;
private final int prefH = 400;
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
};
// mainPanel.setPreferredSize(new Dimension(100, 400));
mainPanel.add(panel, BorderLayout.PAGE_START);
frame.add(mainPanel);
frame.setVisible(true);
// frame.getContentPane().add(jp);
frame.pack();
}
}
Alternatively, you can use Box.Filler. Just replace your call to panel.add(Box.createGlue()) with
panel.add(new Box.Filler(new Dimension(0, 0),
new Dimension(0, Short.MAX_VALUE),
new Dimension(0, Short.MAX_VALUE)));
If you want to achieve the same for a horizontal layout, just use Short.MAX_VALUE for width instead of height in the Dimension call.

JScrollPane won't work

Hey guys I wanted to create a JScrollPane but it won't work... and I don't know why... here's my code...
public class test extends JFrame{
public test(){
setSize(1000,600);
}
private static JButton[] remove;
private static JPanel p = new JPanel();
public static void main(String[]args){
p.setLayout(null);
JFrame t=new test();
remove = new JButton[25];
for(int i=0;i<25;i++){
remove[i]=new JButton("Remove");
remove[i].setBounds(243,92+35*i,85,25);
p.add(remove[i]);
}
JScrollPane scrollPane = new JScrollPane(p);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
t.add(scrollPane);
t.setVisible(true);
}
Umm and Im pretty sure the frame isn't big enough for these 25 buttons... But if i delete that p.setLayout(null); A horizontal scroll bar will be created automatically... I don't really know what is wrong with my code... Pls help thank you very much!
You need to set p's preferredSize for this to work.
p.setPreferredSize(new Dimension(800, 2000));
Or you could have p extend JPanel and then override the getPreferredSize() method to return the proper dimension.
And I agree -- get rid of your null layouts. Learn about and use the layout managers if you want to use Swing correctly and have robust Swing GUI's.
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Foo extends JFrame {
private static final int BUTTON_COUNT = 25;
public static void main(String[] args) {
JPanel btnPanel = new JPanel(new GridLayout(0, 1, 0, 20));
btnPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
AbstractAction removeAction = new AbstractAction("Remove") {
#Override
public void actionPerformed(ActionEvent evt) {
JButton src = (JButton) evt.getSource();
JPanel container = (JPanel) src.getParent();
container.remove(src);
container.revalidate();
container.repaint();
}
};
for (int i = 0; i < BUTTON_COUNT; i++) {
JButton removeBtn = new JButton(removeAction);
btnPanel.add(removeBtn);
}
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.add(btnPanel, BorderLayout.NORTH);
JScrollPane scrollpane = new JScrollPane(borderPanel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setPreferredSize(new Dimension(400, 800));
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The issue is that a scroll pane checks the component inside it for a "preferred size" so a pane with a null layout has a preferred size of (0,0). Which it ignores.
You should do something along the lines of:
p.setPreferredSize(1000,600);
And you should see some scroll bars appear, I'm not sure how accurate they will be though.

Categories