I am trying to create a grid of text fields which I envision would look like this:
I am trying to use Swing in order to do this but am having trouble creating the grid. I have tried both GridBagLayout and GridLayout in order to accomplish this but have had the same issue with both - I am unable to remove spaces between the text fields.
The above image is using grid bag layout. I have tried to change the insets as well as the weights of each text field but have not been able to get rid of the spaces between the fields.
The grid layout is slightly better:
But it has the same problem. I tried adding each text field to a JPanel and then created an empty border for each panel but this also did not work.
I have attached the code for both implementations. I am not committed to using a JTextField so if there is some other element that a user can type into I would be willing to try that out as well. Any help getting rid of the spaces between each text field would be greatly appreciated!
GridBagLayoutDemo
class GridBagLayoutDemo {
public static void addComponentsToPane(Container pane) {
GridBagLayout gbl = new GridBagLayout();
pane.setLayout(gbl);
GridBagConstraints c = new GridBagConstraints();
int rows = 2;
int cols = 2;
for(int i = 0; i < (rows + 1) * 3; i++){
JTextField textField = new JTextField(1);
textField.setFont( new Font("Serif", Font.PLAIN, 30) );
JPanel tempPanel = new JPanel();
tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
tempPanel.add(textField);
c.gridx = i % (rows + 1);
c.gridy = i / (cols + 1);
c.gridheight = 1;
c.gridwidth = 1;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
pane.add(tempPanel, c);
}
gbl.setConstraints(pane, c);
c.insets = new Insets(0,0,0,0);
}
public void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("GridBagLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridBagLayoutDemo demo = new GridBagLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
GridLayoutDemo
class GridLayoutDemo {
public void createAndShowGUI() {
JFrame frame = new JFrame("GridLayout");
//frame.setOpacity(0L);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel parentPanel = new JPanel();
GridLayout layout = new GridLayout(3, 3, 0, 0);
layout.setHgap(0);
layout.setVgap(0);
parentPanel.setLayout(layout);
for(int i = 0 ; i < 9; i++){
JTextField textField = new JTextField();
textField.setHorizontalAlignment(JTextField.CENTER);
// JPanel tempPanel = new JPanel();
//textField.setBounds(0, 0, 10 , 10);
//textField.setFont( new Font("Serif", Font.PLAIN, 18));
//tempPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
//tempPanel.add(textField);
// tempPanel.add(textField);
parentPanel.add(textField);
}
frame.add(parentPanel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
GridLayoutDemo demo = new GridLayoutDemo();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
demo.createAndShowGUI();
}
});
}
}
I think you will find that this is a issue with the MacOS look and feel, as it adds a empty border around the text fields to allow for the focus highlight
You can see it highlighted below
The simplest way to remove it, is to remove or replace the border, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
int rows = 3;
int cols = 3;
for (int index = 0; index < (rows * cols); index++) {
int row = index % rows;
int col = index / cols;
gbc.gridy = row;
gbc.gridx = col;
JTextField textField = new JTextField(4);
textField.setText(col + "x" + row);
textField.setBorder(new LineBorder(Color.DARK_GRAY));
add(textField, gbc);
}
}
}
}
Related
I have a super basic JTable, which I'm adding to a JFrame, but for some reason frame.pack() doesn't work. I'm setting the row height to the column width so that the cells of the table are squares, but this doesn't seem to work when the window is resized. So, how can I make it so that the cells of the table are always squares, even when resized, and the frame is properly packed? Here's the code for the window:
package me.an.ar.window;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
public class DayPlanner
{
private JFrame frame;
private void createAndShowGUI()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = frame.getContentPane();
Object[][] data = new Object[5][7];
String[] columnNames = { "Day1", "Day2", "Day3", "Day4", "Day5", "Day6", "Day7" };
JTable table = new JTable(data, columnNames);
for (int col = 0; col < table.getColumnCount(); col++)
{
for (int row = 0; row < table.getRowCount(); row++)
{
int colWidth = table.getColumnModel().getColumn(col).getWidth();
table.setRowHeight(row, colWidth);
}
}
container.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void show()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
public DayPlanner()
{
show();
}
public static void main(String[] args)
{
new DayPlanner();
}
}
You did not set any LayoutManager. The default is not a FlowLayout but at least not null:
The default content pane will have a BorderLayout manager set on it.
(Java 17 API)
This would mean by resizing the window you would more have to fight with the scrollpane's resizing. What happens if you use
container.add(new JScrollPane(table), BorderLayout.CENTER);
That should let the scrollpane grow and shrink with the frame, and the amount of rows/columns inside the table might vary. This might also get impacted by JTable.setAutoResizeMode().
Option 1
You haven't really mentioned how you are about to use this table (what data will be held and how the user is expected to interact with); however, it sounds like a use case for GridLayout (regarding data cells), as well as GridBagLayout (regarding header cells). Example below:
public class DayPlanner {
private JFrame frame;
Dimension cellSize = new Dimension(75, 75);
private void createAndShowGUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create header cells
JPanel p1 = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
String[] columnNames = { "Day 1", "Day 2", "Day 3", "Day 4", "Day 5", "Day 6", "Day 7" };
int count = 0;
for (int i = 0; i < columnNames.length; i++) {
JLabel l = new JLabel(columnNames[i], SwingConstants.CENTER);
l.setFont(new Font("Times New Roman", Font.BOLD, 14));
l.setBackground(new Color(238, 238, 238));
l.setOpaque(true);
l.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, new Color(122, 138, 153)));
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 5; // adjusts cell's height
c.weightx = 0.5;
c.gridx = count++;
c.gridy = 0;
p1.add(l, c);
}
// Create data cells
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(5, 7));
for (int i = 0; i < 35; i++) {
JLabel l = new JLabel("<html> This is some sample text " + i + "</html>"); // html tags allow text-wrapping
l.setFont(new Font("Times New Roman", Font.PLAIN, 14));
l.setVerticalAlignment(SwingConstants.TOP);
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setPreferredSize(cellSize);
l.setBackground(Color.WHITE);
l.setOpaque(true);
l.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, new Color(122, 138, 153)));
p2.add(l);
}
JScrollPane sp = new JScrollPane(p2);
sp.getVerticalScrollBar().setUnitIncrement((int) cellSize.getHeight() / 2); // adjusts scrolling speed
sp.getViewport().setBackground(Color.WHITE);
Container container = frame.getContentPane();
container.add(p1, BorderLayout.NORTH);
container.add(sp, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DayPlanner().createAndShowGUI();
}
});
}
}
Option 2
If you still want to use the JTable given in your question, you could add a ComponentListener to your JFrame, so that you can listen to "resize events", allowing you to readjust the cells' size and retain their square shape.
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent evt) {
for (int row = 0; row < table.getRowCount(); row++) {
int colWidth = table.getColumnModel().getColumn(0).getWidth();
table.setRowHeight(row, colWidth);
}
}
});
As for the pack() issue, you could set the initial size of the JFrame according to the columns and rows in your table (remember to comment out frame.pack();). The below, although it would remove the empty space at the bottom of the frame, it wouldn't, however, stop the user from resizing the window and bringing that back.
int colWidth = table.getColumnModel().getColumn(0).getWidth();
frame.setSize(7 * colWidth, 5 * table.getRowHeight(0) + 25);
//frame.pack();
I have simple GUI that is supposed to show some informations. I created menu of multiple JTabbedPanes and the tabs are stacking on each other as intended. I am trying to remove borders on left, right and bottom sides of each tab so it doesn't look stacked. I haven't found anything that would solve my problem, is there actually a way to do it?
Thank you for answer in advance.
Here is screen shot:
Here is my code:
import java.awt.*;
import java.awt.event.*;
import java.io.FileNotFoundException;
import javax.swing.*;
public class Convertor implements ItemListener {
public void addComponentToPane(Container pane) throws FileNotFoundException {
//main panel containing all below
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
//Menu panel
JPanel menuPanel = new JPanel();
menuPanel.setMinimumSize(new Dimension(1200, 30));
menuPanel.setMaximumSize(new Dimension(1200, 30));
menuPanel.setPreferredSize(new Dimension(1200, 30));
menuPanel.setBackground(Color.BLUE);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.insets = new Insets(0, 0, 0, 0);
gbc.gridx = 0;
gbc.gridy = 0;
mainPanel.add(menuPanel, gbc);
//Menu panel buttons
JButton importButton = new JButton("Import");
importButton.setPreferredSize(new Dimension(75, 20));
menuPanel.add(importButton, BorderLayout.EAST);
JButton button2 = new JButton("XXX");
button2.setPreferredSize(new Dimension(75, 20));
menuPanel.add(button2, BorderLayout.EAST);
//PAYER PANEL CONTAINER - containing payer panel
JPanel payerPanelContainer = new JPanel(new BorderLayout());
//payerPanelContainer.setBackground(Color.RED);
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 0;
gbc.weighty = 1;
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.insets = new Insets(0, 0, 0, 0);
gbc.gridx = 0;
gbc.gridy = 1;
mainPanel.add(payerPanelContainer, gbc);
//PAYER PANEL
JPanel payerPanel = new JPanel(new GridBagLayout());
payerPanel.setBackground(Color.YELLOW);
payerPanelContainer.add(payerPanel);
//PAYER PANEL TABBED PANE
JTabbedPane payerTabbedPane = new JTabbedPane();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.insets = new Insets(0, 0, 0, 0);
gbc.gridx = 0;
gbc.gridy = 0;
payerPanel.add(payerTabbedPane, gbc);
//Create payer tabs
JPanel payerTab1 = new JPanel(new BorderLayout());
payerTabbedPane.addTab("Payer 1", payerTab1);
JPanel payerTab2 = new JPanel(new BorderLayout());
payerTabbedPane.addTab("Payer 2", payerTab2);
//create MSISDN tabbed pane in each payer tab
JTabbedPane msisdnTabbedPane1 = new JTabbedPane();
payerTab1.add(msisdnTabbedPane1);
//create MSISDN tabs
JPanel generalTabPayer1 = new JPanel(new BorderLayout());
msisdnTabbedPane1.addTab("GENERAL", generalTabPayer1);
JPanel msisdnTab1 = new JPanel(new BorderLayout());
msisdnTabbedPane1.addTab("MSISDN 1", msisdnTab1);
JPanel msisdnTab2 = new JPanel(new BorderLayout());
msisdnTabbedPane1.addTab("MSISDN 2", msisdnTab2);
JPanel msisdnTab3 = new JPanel(new BorderLayout());
msisdnTabbedPane1.addTab("MSISDN 2", msisdnTab3);
//create MSISDN options tabbed pane
JTabbedPane msisdnOptionsTabbedPane1 = new JTabbedPane();
msisdnTab1.add(msisdnOptionsTabbedPane1);
//create MSISDN options tabs
JPanel msisdnOptionsTab1 = new JPanel(new BorderLayout());
msisdnOptionsTabbedPane1.addTab("Option 1", msisdnOptionsTab1);
JPanel msisdnOptionsTab2 = new JPanel(new BorderLayout());
msisdnOptionsTabbedPane1.addTab("Option 2", msisdnOptionsTab2);
//add main panel to window
pane.add(mainPanel);
}
private static void createAndShowGUI() throws FileNotFoundException {
//Create and set up the window.
JFrame frame = new JFrame("CSV Reader");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
Convertor demo = new Convertor();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setSize(1206, 800);
frame.setMinimumSize(new Dimension(1206, 800));
frame.setMaximumSize(new Dimension(1206, 800));
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGUI();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
#Override
public void itemStateChanged(ItemEvent arg0) {
// TODO Auto-generated method stub
}
}
It's possible, but it's hard. The only way to do it is to provide your own UI for the tabbed pane. Here is the example, which is not completly satisfied your requirements, but it can show the way, which you must go (sorry, but I cann't provide a complete solution, because it could be time expansive).
import java.awt.Graphics;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
public class BorderlessTabsExample implements Runnable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(MetalLookAndFeel.class.getName());
} catch (Exception e) {
// Nothing
}
SwingUtilities.invokeLater(new BorderlessTabsExample());
}
#Override
public void run() {
JTabbedPane tabber = new JTabbedPane();
tabber.addTab("First", new JLabel("First"));
tabber.addTab("Second", new JLabel("Second"));
tabber.addTab("Third", new JLabel("Third"));
// set the UI which will paint your tabs
tabber.setUI(new MetalBorderlessTabbedPaneUI());
JFrame frm = new JFrame("Tabber test");
frm.add(tabber);
frm.setSize(500, 400);
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
private static class MetalBorderlessTabbedPaneUI extends MetalTabbedPaneUI {
#Override
protected void installDefaults() {
super.installDefaults();
if (contentBorderInsets != null) {
contentBorderInsets = new Insets(contentBorderInsets.top, 0, 0, 0);
}
}
#Override
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
// Do nothing
}
#Override
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
// Do nothing
}
#Override
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h) {
// Do nothing
}
}
}
I'm trying to get the CardLayout working correctly. - I have the first "card" in my deck", which i've called firstPanel (Gridbaglayout). Inside that panel i want some other panels with the same layout (Gridbaglayout) which ofc has some components.
as example under here - I'm showing one of the JPanels with Gridbaglayout that i want inside my firstPanel (Jpanel) called textFieldForPlayers.
I hope you understand what i mean. if not i'll try to explain it more detailed. :)
public void run() {
deck.setLayout(cl);
c = new GridBagConstraints();
firstPanel.setLayout(new GridBagLayout());
secondPanel.setLayout(new GridBagLayout());
thirdPanel.setLayout(new GridBagLayout());
GamePanel gamePanel = new GamePanel();
c.gridx = 0;
c.gridy = 0;
firstPanel.add(textFieldForPlayers(humanPLayers), c);
c.gridx = 0;
c.gridy = 1;
firstPanel.add(botPreferences(), c);
c.gridx = 0;
c.gridy = 2;
firstPanel.add(next = new JButton("Next"), c);
c.gridx = 0;
c.gridy = 0;
secondPanel.add(new JLabel("Bot preferences"), c);
c.gridx = 0;
c.gridy = 0;
thirdPanel.add(gamePanel, c);
deck.add(firstPanel, "1");
deck.add(secondPanel, "2");
deck.add(thirdPanel, "3");
cl.show(deck, "1");
events();
}
private JPanel textFieldForPlayers(int hplayers) {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
c = new GridBagConstraints();
JLabel text = new JLabel("Name of the human players");
c.gridx = 0;
c.gridy = 0;
panel.add(text, c);
boxes = new ArrayList<>();
boxes.add(new JTextField());
boxes.add(new JTextField());
boxes.add(new JTextField());
boxes.add(new JTextField());
boxes.add(new JTextField());
boxes.add(new JTextField());
for (int i = 1; i <= hplayers; i++) {
boxes.get(i).setPreferredSize(new Dimension(165, 18));
c.gridx = 1;
c.gridy = i;
panel.add(boxes.get(i), c);
c.gridx = 0;
c.gridy = i;
panel.add(new JLabel("Player " + i + ": "), c);
}
return panel;
}
Picture 3 - This is what it looks like now
Picture 4 - Should be - 1 in the top, 2 in the middle and 3 in the bottom. All of them centeret.
Your CardLayout, cl, is not behaving as a true CardLayout, suggesting something is wrong with code not shown. Myself, I try to modularize my gui creation, including using a separate utility method to help create gridbagconstraints if any complex constraints are needed.
For example:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class GridBagEg extends JPanel {
public static final int PLAYER_COUNT = 5;
private CardLayout cardLayout = new CardLayout();
private JPanel deckPanel = new JPanel(cardLayout);
private NextAction nextAction = new NextAction("Next");
private PlayerPanel playerPanel = new PlayerPanel(PLAYER_COUNT);
private BotDifficultyPanel botDifficultyPanel = new BotDifficultyPanel();
public GridBagEg() {
deckPanel.add(playerPanel, PlayerPanel.NAME);
deckPanel.add(botDifficultyPanel, BotDifficultyPanel.NAME);
JPanel nextBtnPanel = new JPanel();
nextBtnPanel.add(new JButton(nextAction));
setLayout(new BorderLayout());
add(deckPanel, BorderLayout.CENTER);
add(nextBtnPanel, BorderLayout.PAGE_END);
}
private class NextAction extends AbstractAction {
public NextAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(deckPanel);
}
}
private static void createAndShowGui() {
GridBagEg mainPanel = new GridBagEg();
JFrame frame = new JFrame("GridBagEg");
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(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class BotDifficultyPanel extends JPanel {
public static final String NAME = "bot difficulty panel";
public static final String[] LEVELS = {"Easy", "Mid-level", "Difficult", "Holy Mother of God Difficulty"};
private JComboBox<String> difficultyCombo = new JComboBox<>(LEVELS);
public BotDifficultyPanel() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(new JLabel("Bot Difficulty:"), gbc);
gbc.gridx = 1;
gbc.insets = new Insets(0, 10, 0, 0);
add(difficultyCombo, gbc);
}
public String getSelectedDifficulty() {
String selection = (String) difficultyCombo.getSelectedItem();
return selection;
}
}
#SuppressWarnings("serial")
class PlayerPanel extends JPanel {
public static final String NAME = "player panel";
private static final String TITLE = "Name of Human Players";
private static final int EB_GAP = 10;
private static final int FIELD_COLUMNS = 15;
private static final int INS_GAP = 5;
private int playerMaxCount = 0;
private List<JTextField> playerFields = new ArrayList<>();
public PlayerPanel(int playerMaxCount) {
this.playerMaxCount = playerMaxCount;
Border outsideBorder = BorderFactory.createTitledBorder(TITLE);
Border insideBorder = BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP);
setBorder(BorderFactory.createCompoundBorder(outsideBorder, insideBorder));
setLayout(new GridBagLayout());
for (int i = 0; i < playerMaxCount; i++) {
JTextField playerField = new JTextField(FIELD_COLUMNS);
playerFields.add(playerField);
add(new JLabel("Player " + i + ":"), createGbc(0, i));
add(playerField, createGbc(1, i));
}
}
public String getFieldName(int index) {
if (index < 0 || index >= playerFields.size()) {
String text = "for playerFields index of " + index;
throw new IllegalArgumentException(text);
} else {
return playerFields.get(index).getText();
}
}
public int getPlayerMaxCount() {
return playerMaxCount;
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
// if x is 0, anchor to the left otherwise to the right
gbc.anchor = x == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(INS_GAP, INS_GAP, INS_GAP, INS_GAP);
if (x == 0) {
gbc.insets.right = 4 * INS_GAP; // increase gap in between
}
return gbc;
}
}
Like:
CardLayout cl = new CardLayout();
JPanel contentPane = new JPanel();
JPanel firstPanel = new JPanel();
JPanel secondPanel = new JPanel();
contentPane.setlayout(cl);
firstPanel.add(new JButton("1"));
secondPanel.add(new JButton("2"));
contentPane.add(firstPanel, "1");
contentPane.add(secondPanel, "2");
cl.show(contentPane, "1");
So now the contentPane contains 2 JPanels inside it. and now we would be seeing everything on firstPanel right? :)
Can somebody tell me why after calling method getContentPane().add(grid[i][j]) I am not able to display the matrix of JLabels. There's only one "e" label displayed.
public class SudokuFrame extends JFrame implements ActionListener {
JButton generateButton;
JLabel[][] grid;
public SudokuFrame(){
setSize(300, 300);
setTitle("Sudoku");
setLayout(null);
generateButton = new JButton("Generate");
generateButton.setBounds(90, 220, 100, 30);
add(generateButton);
generateButton.addActionListener(this);
grid = new JLabel[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
grid[i][j] = new JLabel("e");
grid[i][j].setBounds(100, 100, 30, 30);
getContentPane().add(grid[i][j]);
}
}
}
public static void main(String[] args){
SudokuFrame frame = new SudokuFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
You're giving every JLabel the exact same bounds -- same size and same position and so every new label is placed right smack dab on top of the previously added ones.
Solution: don't use null layout. Why use this when the problem is perfectly suited for a GridLayout? In general you want to avoid using null layouts and setBounds as the layout managers will make your coding and your GUI much easier to manage. Let the layouts do the heavy lifting for you.
e.g.,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.*;
public class SimpleSudoku extends JPanel {
private static final int GAP = 1;
private static final Font LABEL_FONT = new Font(Font.DIALOG, Font.PLAIN, 24);
private JLabel[][] grid = new JLabel[9][9];
public SimpleSudoku() {
JPanel sudokuPanel = new JPanel(new GridLayout(9, 9, GAP, GAP));
sudokuPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
sudokuPanel.setBackground(Color.BLACK);
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
grid[row][col] = new JLabel(" ", SwingConstants.CENTER);
grid[row][col].setFont(LABEL_FONT); // make it big
grid[row][col].setOpaque(true);
grid[row][col].setBackground(Color.WHITE);
sudokuPanel.add(grid[row][col]);
}
}
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton("Regenerate"));
setLayout(new BorderLayout());
add(sudokuPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
private static void createAndShowGui() {
SimpleSudoku mainPanel = new SimpleSudoku();
JFrame frame = new JFrame("SimpleSudoku");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
Another problem with swing. How can I stop GridBagLayout from respacing components if one of them changes size? For example, I have few columns, in one of which there is a JLabel with text "text". When I change it to "texttext" layout manager resizes the whole column. I don't want it to do that. Is there any way to prevent it?
Example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class ResizeIssue {
static int value = 99;
public static void main(String[] args) {
JFrame frame = new JFrame();
final JLabel valueLabel = new JLabel(String.valueOf(value));
JButton decButton = new JButton("-");
decButton.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
valueLabel.setText(String.valueOf(--value));
}
});
JButton incButton = new JButton("+");
incButton.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
valueLabel.setText(String.valueOf(++value));
}
});
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
panel.add(decButton, c);
c.gridx = 1;
panel.add(valueLabel, c);
c.gridx = 2;
panel.add(incButton, c);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
It is visible while 9 -> 10 or anytime text changes width.
GridBagLayout ignores maximumWidth/Height. There's not an easy way to set the maximum size of the JLabel.
But, what I think you really want is the layout to not shift when the text in the JLabel changes.
That can be done by making the JLabel wide enough to hold the largest value it needs to display. For example:
jLabel1.setFont(new Font("monospace", Font.PLAIN, 12));
FontMetrics fm = jLabel1.getFontMetrics(jLabel1.getFont());
int w = fm.stringWidth("0000");
int h = fm.getHeight();
Dimension size = new Dimension(w, h);
jLabel1.setMinimumSize(size);
jLabel1.setPreferredSize(size);
Update:
To center the label text, just add:
jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
This might work:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ResizeIssue2 {
static int value = 99;
public static void main(String[] args) {
JFrame frame = new JFrame();
final JLabel valueLabel = new JLabel(String.valueOf(value));
JButton decButton = new JButton("-");
decButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
valueLabel.setText(String.valueOf(--value));
}
});
JButton incButton = new JButton("+");
incButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
valueLabel.setText(String.valueOf(++value));
}
});
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
panel.add(decButton, c);
c.gridx = 1;
panel.add(valueLabel, c);
c.gridx = 2;
panel.add(incButton, c);
//*
c.gridy = 1;
int w = 32; //incButton.getPreferredSize().width;
for(c.gridx=0;c.gridx<3;c.gridx++) {
panel.add(Box.createHorizontalStrut(w), c);
}
// */
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}