GridBag Layout alignment issue - java

I had been practicing GridBagLayout from some time, but still I feel confused when I want desired output. I want this kind of output
but i mess up creating one on which table is on one side and the two buttons are on other sides. The table gets squeezed.
Can anybody give me code to align the components (buttons and a table) like this. References for components are
activateServer, addFiles and table
Thanks in advance !
EDIT : this is the code which i am using (Short code for illustrating only prob)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ServerCode extends JFrame
{
ServerCode()
{
JTable table = new JTable(10,3);
JButton addFiles= new JButton("Add files"),activateServer = new JButton("Activate Button");
setLayout(new GridBagLayout());
add(table,new GridBagConstraints(0,0,6,6, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
add(addFiles,new GridBagConstraints(1,6,2,1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
add(activateServer,new GridBagConstraints(6,6,2,1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
setSize(700,400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String...args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ServerCode();
}
});
}
}
And its output is :

Heck, I'd just use a BorderLayout for this. Forget GridBagLayout if it is not needed. For example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
#SuppressWarnings("serial")
public class LayoutFoo extends JPanel {
private static final int PREF_W = 800;
public LayoutFoo() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("Foo"));
buttonPanel.add(Box.createHorizontalStrut(10));
buttonPanel.add(new JButton("Bar"));
String[] columnNames = {"Mon", "Tues", "Wed"};
DefaultTableModel model = new DefaultTableModel(columnNames, 25);
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.getViewport().setPreferredSize(table.getPreferredSize());
// scrollPane.getViewport().setPreferredSize(table.getPreferredScrollableViewportSize());
JLabel southLabel = new JLabel("Foobars!");
southLabel.setForeground(Color.white);
JPanel southPanel = new JPanel();
southPanel.setBackground(Color.black);
southPanel.add(southLabel);
setLayout(new BorderLayout(5, 5));
add(buttonPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER );
add(southPanel, BorderLayout.SOUTH);
}
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
int width = PREF_W > superSize.width ? PREF_W : superSize.width;
return new Dimension(width, superSize.height);
}
private static void createAndShowGUI() {
LayoutFoo paintEg = new LayoutFoo();
JFrame frame = new JFrame("Smart File Transfer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

If you want to keep the GridBagLayout i believe you need something like this:
add(activateServer,new GridBagConstraints(0,0,1,1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
add(addFiles,new GridBagConstraints(1,0,1,1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
add(table,new GridBagConstraints(0,1,2,1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));
if you are having problems using the creator of GridBagConstraints you should try using the easier way like in this example
for more info try the oracle documentation

Related

How to make the JTextArea fill width and buttonsContainer fill height?

I've tried to use GridBagLayout. It makes the JTextArea parent container occupy a big width, but the text area itself didn't fill the width. Why?
And I hope the first button is close to the top and the second button is close to the bottom. How can I implement it?
Could you please advise how to correct my code?
The following code is all code for the demo.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
public class Demo extends JFrame {
public Demo() throws HeadlessException {
add(new MainPanel());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
class MainPanel extends JPanel {
private final InputComponent inputComponent = new InputComponent();
private final ButtonsContainer buttons = new ButtonsContainer();
public MainPanel() {
setPreferredSize(new Dimension(800, 100));
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(5, 5, 5, 5));
add(inputComponent,
buildConstraints(0, 0, 1, 1, GridConstraints.FILL_BOTH, 1.0, 1.0));
add(buttons,
buildConstraints(1, 0, 1, 1, GridConstraints.FILL_BOTH, 0.0, 1.0));
}
}
class InputComponent extends JComponent {
private final JTextArea textArea = new JTextArea();
public InputComponent() {
setLayout(new BorderLayout());
textArea.setLineWrap(true);
add(textArea, BorderLayout.CENTER);
}
}
class ButtonsContainer extends JComponent {
private final JButton button1 = new JButton("Button 1");
private final JButton button2 = new JButton("Button 2");
public ButtonsContainer() {
setLayout(new GridBagLayout());
add(button1, buildConstraints(0, 0, 1, 1, GridBagConstraints.HORIZONTAL, 1.0, 0.0));
add(button2, buildConstraints(0, 1, 1, 1, GridBagConstraints.HORIZONTAL, 1.0, 0.0));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
final Demo demo = new Demo();
});
}
private GridBagConstraints buildConstraints(
int x,
int y,
int gWidth,
int gHeight,
int fill,
double weightX,
double weightY
) {
final GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = x;
constraints.gridy = y;
constraints.gridwidth = gWidth;
constraints.gridheight = gHeight;
constraints.fill = fill;
constraints.weightx = weightX;
constraints.weighty = weightY;
return constraints;
}
}
Original Answer
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Netbeans section.
Don't use a GUI builder. You wind up learning the idiosyncracies of the GUI builder, and not learning Java Swing.
I created the following GUI using a JFrame, a main JPanel, and a button JPanel. If you maximize the GUI, you'll see that the JTextArea expands and the JButtons stay towards the top and bottom.
Don't extend Swing components, or any other Java class, unless you want to override one or more of the class methods. Use composition over inheritance.
You can use multiple simple JPanels to create a complex GUI. The GridBagLayout has its uses, like creating a form. But all that was needed was multiple BorderLayouts.
Don't make Swing components class fields unless you need to access the field instance from more than one method.
Organize your code so it reads like an essay, with the most important code towards the top and the more detailed code towards the bottom. Ideally, the reader of your code will never have to page up to find out something. No, the compiler doesn't care about the order of the methods. But human readers sure do.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ExampleBorerLayoutGUI {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new ExampleBorerLayoutGUI();
});
}
public ExampleBorerLayoutGUI() {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JTextArea textArea = new JTextArea(5, 40);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton button1 = new JButton("Button 1");
panel.add(button1, BorderLayout.NORTH);
JButton button2 = new JButton("Button 2");
panel.add(button2, BorderLayout.SOUTH);
return panel;
}
}
Edited to Add
Here's the GUI with three JButtons. You didn't say whether you wanted the third button on the top or the bottom. I chose the top.
I chose a GridLayout for the upper button JPanel. It's easy to add more JButtons to a GridLayout.
Here's the modified complete runnable code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ExampleBorderLayoutGUI {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new ExampleBorderLayoutGUI();
});
}
public ExampleBorderLayoutGUI() {
JFrame frame = new JFrame("Example Border Layout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JTextArea textArea = new JTextArea(5, 40);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(createUpperButtonPanel(), BorderLayout.NORTH);
panel.add(createLowerButtonPanel(), BorderLayout.SOUTH);
return panel;
}
private JPanel createUpperButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton button1 = new JButton("Button 1");
panel.add(button1);
JButton button2 = new JButton("Button 2");
panel.add(button2);
return panel;
}
private JPanel createLowerButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton button = new JButton("Button 3");
panel.add(button, BorderLayout.SOUTH);
return panel;
}
}
You can auto-generate the right UI code if you use Eclipse IDE's Window Builder:
https://www.eclipse.org/windowbuilder/
It is far easier to design your application that way. Set this up on your IDE and let it do the heavy lifting for you. If you wish to incorporate dynamic resizing of your UI elements, design the code to be responsive.

Arrange JPanel on JFrame

I have one frame (600X500), A JPanel (50X100) and another JPanel (200X150) and
I am trying to get the following result:
My code is:
public class BtnsPanel extends JPanel{
public BtnsPanel()
{
setSize(50,100);
setBackground(Color.RED);
}
}
public class DialogPanel extends JPanel{
public DialogPanel() {
setSize(150,150);
setBackground(Color.BLUE);
}
}
public class MainFrame extends JFrame{
public MainFrame()
{
setSize(600,500);
setLayout(new BorderLayout());
add(new BtnsPanel(), BorderLayout.CENTER);
add(new DialogPanel(), BorderLayout.CENTER);
}
public static void main(String[] args){
new MainFrame().setVisible(true);
}
}
Code result:
And that is not the expected result.
Your picture is not to scale, but if you are not trying to reach the exact scale of the dimensions you have provided, I would suggest using GridBagLayout instead of BorderLayout:
public class MainFrame extends JFrame {
private JPanel btnsPanel;
private JPanel dialogPanel;
public MainFrame() {
getContentPane().setBackground(Color.BLUE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setPreferredSize(new Dimension(600,500));
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[]{0, 0, 0, 0};
gridBagLayout.rowHeights = new int[]{0, 0, 0, 0};
gridBagLayout.columnWeights = new double[]{0.2, 0.1, 0.5, 0.2};
gridBagLayout.rowWeights = new double[]{0.3, 0.3, 0.15, 0.25};
getContentPane().setLayout(gridBagLayout);
btnsPanel = new JPanel();
btnsPanel.setBackground(Color.RED);
GridBagConstraints gbc_btnsPanel = new GridBagConstraints();
gbc_btnsPanel.insets = new Insets(0, 0, 5, 5);
gbc_btnsPanel.fill = GridBagConstraints.BOTH;
gbc_btnsPanel.gridx = 0;
gbc_btnsPanel.gridy = 0;
gbc_btnsPanel.gridheight = 2;
getContentPane().add(btnsPanel, gbc_btnsPanel);
dialogPanel = new JPanel();
dialogPanel.setBorder(new LineBorder(new Color(0, 0, 0)));
dialogPanel.setBackground(Color.BLUE);
GridBagConstraints gbc_dialogPanel = new GridBagConstraints();
gbc_dialogPanel.insets = new Insets(0, 0, 0, 5);
gbc_dialogPanel.fill = GridBagConstraints.BOTH;
gbc_dialogPanel.gridx = 2;
gbc_dialogPanel.gridy = 1;
gbc_dialogPanel.gridheight = 2;
getContentPane().add(dialogPanel, gbc_dialogPanel);
pack();
}
}
Code Result:
Using GridbagLayout as proposed by EvT is a good and valid solution.
However, if you want to avoid the complexity of GridBagConstraints you can achieve similar results by wrapping btnsPanel and dialogPanel, each by a JPanel like so:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class MainFrame extends JFrame {
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cPane = getContentPane();
cPane.setBackground(Color.BLUE);
cPane.setLayout(new BorderLayout());
JPanel leftPane = new JPanel();
leftPane.setLayout(new BoxLayout(leftPane, BoxLayout.Y_AXIS));
leftPane.setOpaque(false);
JPanel btnsPanel = new JPanel();
btnsPanel.setBackground(Color.RED);
btnsPanel.setPreferredSize(new Dimension(50,100));
leftPane.add(btnsPanel);
leftPane.add(Box.createVerticalGlue());
cPane.add(leftPane, BorderLayout.LINE_START);
JPanel centerPane = new JPanel(new GridBagLayout());
centerPane.setPreferredSize(new Dimension(500,500));
centerPane.setOpaque(false);
JPanel dialogPanel = new JPanel();
dialogPanel.setBorder(new LineBorder(new Color(0, 0, 0)));
dialogPanel.setBackground(Color.BLUE);
dialogPanel.setPreferredSize(new Dimension(200,150));
centerPane.add(dialogPanel);
cPane.add(centerPane, BorderLayout.CENTER);
pack();
}
public static void main(String[] args){
new MainFrame().setVisible(true);
}
}

CardLayout appearing without asking for it

This is my SSCE (though in three seperate classes).
StartUp.java
public class Startup {
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MainFrame gui = new MainFrame();
}
});
}
}
MainFrame.java
package gui;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class MainFrame {
private JFrame mainFrame;
private JMenuBar menuBar;
private JMenu menuRoboControl;
private JMenuItem menuItemStart;
private JMenuItem menuItemShutdown;
private JPanel cardPanel;
private final JPanel comListCard = new ComListCard();
public MainFrame() {
initComponents();
}
private void menuItemStartActionPerformed(ActionEvent e) {
CardLayout cardLayout = (CardLayout) cardPanel.getLayout();
cardLayout.show(cardPanel, "selectPort");
}
private void menuItemShutdownActionPerformed(ActionEvent e) {
mainFrame.dispose();
System.exit(0);
}
private void initComponents() {
mainFrame = new JFrame();
menuBar = new JMenuBar();
menuRoboControl = new JMenu();
menuItemStart = new JMenuItem();
menuItemShutdown = new JMenuItem();
cardPanel = new JPanel();
//======== mainFrame ========
{
Container mainFrameContentPane = mainFrame.getContentPane();
mainFrameContentPane.setLayout(new BoxLayout(mainFrameContentPane, BoxLayout.X_AXIS));
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//======== menuBar ========
{
//======== menuRoboControl ========
{
menuRoboControl.setText("RoboControl");
//---- menuItemStart ----
menuItemStart.setText("Start Robot");
menuItemStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
menuItemStartActionPerformed(e);
}
});
menuRoboControl.add(menuItemStart);
//---- menuItemShutdown ----
menuItemShutdown.setText("Shutdown Robot");
menuItemShutdown.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
menuItemShutdownActionPerformed(e);
}
});
menuRoboControl.add(menuItemShutdown);
}
menuBar.add(menuRoboControl);
}
mainFrame.setJMenuBar(menuBar);
//======== cardPanel ========
{
cardPanel.setLayout(new CardLayout());
cardPanel.add(comListCard, "selectPort");
}
mainFrameContentPane.add(cardPanel);
mainFrame.setSize(835, 635);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
}
ComListCard.java
package gui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.AbstractListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ComListCard extends JPanel {
private JTextArea portInfo;
private JScrollPane scrollPane1;
private JList<String> portList;
private JButton selectPort;
public ComListCard() {
initComponents();
}
public void initComponents() {
portInfo = new JTextArea();
scrollPane1 = new JScrollPane();
portList = new JList<>();
selectPort = new JButton();
//======== comListCard ========
{
this.setLayout(new GridBagLayout());
((GridBagLayout) this.getLayout()).columnWidths = new int[]{298, 214, 0, 0};
((GridBagLayout) this.getLayout()).rowHeights = new int[]{0, 0, 0, 0, 86, 220, 0, 0, 0};
((GridBagLayout) this.getLayout()).columnWeights = new double[]{0.0, 0.0, 1.0, 1.0E-4};
((GridBagLayout) this.getLayout()).rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0E-4};
//---- portInfo ----
portInfo.setText("Select the port connected to your XBee. If you do not know what port it is connected to, check your Device Manager.");
portInfo.setLineWrap(true);
portInfo.setWrapStyleWord(true);
portInfo.setOpaque(false);
portInfo.setEnabled(false);
portInfo.setEditable(false);
portInfo.setBorder(null);
this.add(portInfo, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 5, 5), 0, 0));
//======== scrollPane1 ========
{
//---- portList ----
portList.setModel(new AbstractListModel<String>() {
String[] values = {
"1",
"2",
"3",
"4"
};
#Override
public int getSize() {
return values.length;
}
#Override
public String getElementAt(int i) {
return values[i];
}
});
scrollPane1.setViewportView(portList);
}
this.add(scrollPane1, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 5, 5), 0, 0));
//---- selectPort ----
selectPort.setText("Select");
this.add(selectPort, new GridBagConstraints(1, 6, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 5, 5), 0, 0));
}
}
}
Now some information on the problem. GUI works fine, purely about the CardLayout. As you can see I created a main window with a JPanel inside acting as the holder of the card. I created a card and have added it too to CardLayout. But it already appears from the start of the program while it should only appear after pressing the button (referring to the actionlistener where I put .show(..).
Any help appreciated. Not in a hurry either.
A CardLayout is designed to "hold" multiple cards (panels), but only one card will ever be displayed at a time. The key is that "one" of the panels is always displayed. So the CardLayout is functioning properly.
If you has an application that needs to dynamically display an panel on a frame then you must add the panel at run time. In this case the basic logic would be:
panel.add(...);
panel.revalidate();
panel.repaint();
With the above approach, space is not reserved on the frame for the panel when the frame is initially displayed (so you may also need to pack() the frame to make sure the panel is visible).
If you really want to see an empty space for your card panel when the frame is displayed, then you could simply create a panel with no components added to it and then add this panel to your CardLayout. Then when you invoke the show() method, you will swap in your panel with the components.

Nested Layouts (GridBagLayout inside a FlowLayout)

How can I position my labels with this code? It seems that gridbaglayout is not working here, especially the gridbagconstraints. Even if I change the gridx and gridy values, the labels are not moving.
I need to make it in like 3 even columns, 1 column = 1 panel
package nest;
import javax.swing.*;
import java.awt.*;
public class nested extends JFrame{
public static void main(String[] args) {
JFrame f=new JFrame("Bio Data");
JPanel p1=new JPanel(new GridBagLayout());
JPanel p2=new JPanel(new GridBagLayout());
//JPanel p3=new JPanel(new GridBagLayout());
GridBagConstraints c1=new GridBagConstraints();
GridBagConstraints c2=new GridBagConstraints();
JLabel l1=new JLabel("aa");
JLabel l2=new JLabel("bb");
c1.gridx=1;
c1.gridy=1;
p1.add(l1, c1);
c2.gridx=4;
c2.gridy=4;
p2.add(l2, c2);
f.add(p1);
f.add(p2);
f.setVisible(true);
f.setSize(800,500);
f.setResizable(false);
f.setLayout(new FlowLayout());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Changing gridx and gridy does not change the actual position of the labels, but rather the order/format that the labels will be displayed in. If you have something in gridx 4 but nothing in gridx 1,2 or 3 then that object will be the first column.
Also, it woulld be very odd to put a new panel in each column since you can put things in different rows of the gridBagLayout. Here is a short example of a gridBagLayout inside a flowLayout with three different columns of labels:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import java.awt.Insets;
public class nest extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
nest frame = new nest();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public nest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new GridLayout(0, 1, 0, 0));
JPanel panel = new JPanel();
contentPane.add(panel);
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JPanel panel_1 = new JPanel();
panel.add(panel_1);
GridBagLayout gbl_panel_1 = new GridBagLayout();
gbl_panel_1.columnWidths = new int[]{0, 0, 27, 0};
gbl_panel_1.rowHeights = new int[]{0, 16, 0};
gbl_panel_1.columnWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE};
gbl_panel_1.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
panel_1.setLayout(gbl_panel_1);
JLabel lblNewLabel_1 = new JLabel("New label");
GridBagConstraints gbc_lblNewLabel_1 = new GridBagConstraints();
gbc_lblNewLabel_1.insets = new Insets(0, 0, 5, 5);
gbc_lblNewLabel_1.gridx = 0;
gbc_lblNewLabel_1.gridy = 0;
panel_1.add(lblNewLabel_1, gbc_lblNewLabel_1);
JLabel lblNewLabel = new JLabel("New label");
GridBagConstraints gbc_lblNewLabel = new GridBagConstraints();
gbc_lblNewLabel.insets = new Insets(0, 0, 5, 5);
gbc_lblNewLabel.gridx = 1;
gbc_lblNewLabel.gridy = 0;
panel_1.add(lblNewLabel, gbc_lblNewLabel);
JLabel lblNewLabel_2 = new JLabel("New label");
GridBagConstraints gbc_lblNewLabel_2 = new GridBagConstraints();
gbc_lblNewLabel_2.insets = new Insets(0, 0, 5, 0);
gbc_lblNewLabel_2.gridx = 2;
gbc_lblNewLabel_2.gridy = 0;
panel_1.add(lblNewLabel_2, gbc_lblNewLabel_2);
JLabel lblLabel = new JLabel("New label");
GridBagConstraints gbc_lblLabel = new GridBagConstraints();
gbc_lblLabel.gridx = 2;
gbc_lblLabel.gridy = 1;
panel_1.add(lblLabel, gbc_lblLabel);
}
}
I created this with the Google WindowBuilder. Note that you don't necessarily need to set the columnWidths, rowHeights, columnWeights, or rowWeights (and it is better not to sometimes when you have dynamic content). Hopefully this helps.

How do I apply an EtchedBorder to only a specific side of the border?

I have a JPanel where I want to add an EtchedBorder.Lowered to only the left border. I know this is possible with MatteBorders, but I was wondering if there was a way to do this with an EtchedBorder?
use JSeparator instead of EtchedBorder.Lowered,
but JSeparator is by default only line, but you are able to build funny Borders
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
public class NestedLayout {
private JFrame frame = new JFrame();
private JPanel leftPanel = new JPanel();
public NestedLayout() {
leftPanel.setLayout(new BorderLayout());
leftPanel.setBorder(BorderFactory.createEmptyBorder(
10, //top
10, //left
10, //bottom
10)); //right
leftPanel.add(new JSeparator(JSeparator.VERTICAL), BorderLayout.CENTER);
leftPanel.setPreferredSize(new Dimension(40, 40));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(leftPanel, BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new NestedLayout();
}
});
}
}
You can join two panels and add an 'opposite' matted border on each to recreate the etched effect :
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame {
public MainFrame() {
setLayout(new BorderLayout());
JPanel left = new JPanel();
left.setPreferredSize(new Dimension(200, 400));
left.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY));
add(left, BorderLayout.WEST);
JPanel center = new JPanel();
center.setPreferredSize(new Dimension(200, 400));
center.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.WHITE));
add(center, BorderLayout.CENTER);
setVisible(true);
pack();
}
public static void main(String[] args) {
new MainFrame();
}
}
You can easily create your own border class by sub-classing EtchedBorder or AbstractBorder.
This code will do exactly what you asked: an EtchedBorder drawn on one side only. But it doesn't look good. An EtchedBorder simply draws two lines (one dark, one light) on each side. It gets its 3-dimensional look from the way the lines meet at the corners. Without the full box drawn, it doesn't look 3-dimensional.
setBorder(new EtchedBorder() {
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
g.setColor(getShadowColor(c));
g.drawLine(x, y + height - 2, x, y);
g.setColor(getHighlightColor(c));
g.drawLine(x+1, y + height - 3, x+1, y + 1);
}
});
Extending on the answer given by Yanflea where you create an 'opposite' from two different panels to replicate the look of an etched border.
You can create it on one panel using a CompoundBorder like so:
CompoundBorder border = BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, Color.WHITE),
BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY)
); // This would create A line on the bottom
The advantage of doing this way is that you can also do two sides which then looks like this: (Note that this is just a grid of nine panels and only the middle has the border, which also a thicker than 1 See the code below, I used setBackground on panels to show where each panel was)
!
import javax.swing.*;
import java.awt.*;
public class Test
{
public static void main(String[] args)
{
JFrame f = new JFrame("A Demo");
f.setLayout(new GridLayout(3,3));
f.setSize(400,400);
JPanel j1 = new JPanel(); //j1.setBackground(new Color(255,0,0));
JPanel j2 = new JPanel(); //j2.setBackground(new Color(200,0,0));
JPanel j3 = new JPanel(); //j3.setBackground(new Color(150,0,0));
JPanel j4 = new JPanel(); //j4.setBackground(new Color(100,0,0));
JPanel j5 = new JPanel(); //j5.setBackground(new Color(0,255,0));
JPanel j6 = new JPanel(); //j6.setBackground(new Color(0,200,0));
JPanel j7 = new JPanel(); //j7.setBackground(new Color(50,0,0));
JPanel j8 = new JPanel(); //j8.setBackground(new Color(0,150,0));
JPanel j9 = new JPanel(); //j9.setBackground(new Color(0,100,0));
j5.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 2, 2, Color.WHITE),
BorderFactory.createMatteBorder(0, 0, 2, 2, Color.GRAY)
));
f.add(j1);
f.add(j2);
f.add(j3);
f.add(j4);
f.add(j5);
f.add(j6);
f.add(j7);
f.add(j8);
f.add(j9);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}

Categories

Resources