MigLayout: reference component width by id - java

I would like to layout my components as shown in this picture.
In short:
aTextField must have a fixed size of 250px;
bButton has a fixed size that dependes on the text label;
bTextField should grow so that it's width plus bButton width reach
250px.
This is my code:
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutIdReference extends JFrame {
private final MigLayout migLayout = new MigLayout("debug", "", "");
private final JLabel aLabel = new JLabel("Label A");
private final JTextField aTextField = new JTextField();
private final JLabel bLabel = new JLabel("Label B");
private final JTextField bTextField = new JTextField();
private final JButton bButton = new JButton("B Button");
public MigLayoutIdReference() {
Container container = getContentPane();
container.setLayout(migLayout);
add(aLabel, "");
add(aTextField, "id aTextField, w 250!, wrap");
add(bLabel, "");
add(bTextField, "width aTextField.w-bButton.w");
add(bButton, "id bButton, wrap");
setResizable(true);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new MigLayoutIdReference();
}
}
Unfortunately it seems that MigLayout does not allow to calculate width based on other components that you recall by id.
When running my code I get:
Caused by: java.lang.IllegalArgumentException: Size may not contain links
Am I missing something? Apart from referencing components by id, how could I achieve the desired result?

I changed the MigLayout constructor invocation and added row constraints and column constraints.
I made aTextField span two columns.
I gave bTextField the growx constraint.
Now the width of bTextField will adjust so that together with the width of bButton it will match the width of aTextField.
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutIdReference extends JFrame {
private final MigLayout migLayout = new MigLayout("debug", "[][grow][]", "[][]");
private final JLabel aLabel = new JLabel("Label A");
private final JTextField aTextField = new JTextField();
private final JLabel bLabel = new JLabel("Label B");
private final JTextField bTextField = new JTextField();
private final JButton bButton = new JButton("B Button");
public MigLayoutIdReference() {
Container container = getContentPane();
container.setLayout(migLayout);
add(aLabel, "");
add(aTextField, "id aTextField, w 250!, wrap, span 2");
add(bLabel, "");
add(bTextField, "growx");
add(bButton, "id bButton,wrap");
setResizable(true);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new MigLayoutIdReference();
}
}
Here is a screen capture:

Related

JAVA - How to access parent frame component in action listener?

this is my code
This code gives me a frame with text displayed inside it.
I may need to modify the text as necessary, and then there are two buttons. One pushes the code further, the other one closes the application.
What I want to do is add listener to okButt, within the createOverviewButtonsPanel method, that would retrieve the value of txtMenuOverview in order to pass it further is this even possible?
MenuOverviewFrame class:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class MenuOverviewFrame extends JFrame{
private static final long serialVersionUID = -5908534022988507381L;
private static final Font FONT = new Font("Courier", Font.BOLD, 16);
private static final Font MENU_FONT = new Font(Font.MONOSPACED,Font.BOLD,14);
private static final Color BLUE_STEEL = new Color(70, 107, 176);
private static final Dimension INITIAL_SIZE = new Dimension(500, 300);
private static final Dimension MINIMUM_SIZE = new Dimension(275, 150);
public static void main(String[] args) {
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
SwingUtilities.invokeLater(() -> {
MenuOverviewFrame frame = new MenuOverviewFrame("Test test\ntest\ntest");
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
public MenuOverviewFrame(String menuOutput) {
super("Daily Menu");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
getContentPane().setBackground(Color.WHITE);
setSize(INITIAL_SIZE); // The initial frame size
setMinimumSize(MINIMUM_SIZE);
JTextArea txtMenuOverview = new JTextArea(menuOutput);
txtMenuOverview.setFont(MENU_FONT);
JScrollPane taScroll = new JScrollPane(txtMenuOverview);
add(taScroll);
JPanel overviewButtonsPanel = createOverviewButtonsPanel();
overviewButtonsPanel.setPreferredSize(new Dimension(overviewButtonsPanel.getPreferredSize().width, overviewButtonsPanel.getPreferredSize().height + 30));
getContentPane().add(overviewButtonsPanel, BorderLayout.SOUTH); // at the center
}
private JPanel createOverviewButtonsPanel() {
JPanel panel = new JPanel();
//panel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 1));
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(0,0,0,20);
panel.setBackground(BLUE_STEEL);
JButton okButt = new JButton("Send menu");
JButton koButt = new JButton("Abort mission");
panel.add(okButt,gbc);
panel.add(koButt);
okButt.setVerticalAlignment(SwingConstants.CENTER);
return panel;
}
}
Thank you

MiG Layout bad behavior

I'm sorry if this is stupid question, but I couldn't find the answer to this. I am trying to make simple login page to my java program. It contains JLayeredPane settings and login. Also there is one JSplitPane which contains two JSrollpane consolepanel and changelogpanel. So the problem is that I have added JSplitPane and Settings layeredpane but when I am adding login layeredpane it goes same line as settingspanel as it belongs to, but it also goes next to splitpane so it looks like this:
[----]
[-]...[-]
and it's supposed to be:
[----]
[-][-]
Here is screenshot
Main.java
package Main;
import javax.swing.JFrame;
import Development.Version;
import GameEngine.GameEngine;
public class Main {
private static String title = "2D SquareWorld 0.";
private static JFrame window;
public static void main(String[] args) {
GameEngine game = new GameEngine();
window = new JFrame();
window.setTitle("2D SquareWorld 0." + Version.newVersion());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.add(game);
window.add(new GUI());
window.pack();
window.setSize(1000, 720);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
GUI.java
package Main;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import net.miginfocom.swing.MigLayout;
public class GUI extends JPanel {
private static final long serialVersionUID = 1L;
private JSplitPane Splitpanel;
private JScrollPane consolepanel, changelogpanel;
private JPasswordField password;
private JLabel usernametext, passwordtext;
private JButton update, register, login;
private JCheckBox keepLogged;
private JTextField username, server;
private JTextPane console, changelog;
private JLayeredPane loginlayer, settingslayer;
public GUI() {
setLayout(new MigLayout());
settingslayer = new JLayeredPane();
settingslayer.setBorder(BorderFactory.createTitledBorder(""));
loginlayer = new JLayeredPane();
loginlayer.setBorder(BorderFactory.createTitledBorder(""));
username = new JTextField();
password = new JPasswordField();
usernametext = new JLabel("Username:");
passwordtext = new JLabel("Password:");
update = new JButton("Update");
register = new JButton("Register");
login = new JButton("Login");
keepLogged = new JCheckBox("Keep me logged in");
server = new JTextField();
server.setEditable(false);
server.setText("jdbc:mysql://sql4.freemysqlhosting.net");
loginlayer.add(server);
loginlayer.add(keepLogged);
loginlayer.add(login);
loginlayer.add(update);
loginlayer.add(register);
loginlayer.add(usernametext);
loginlayer.add(passwordtext);
loginlayer.add(username);
loginlayer.add(password);
console = new JTextPane();
console.setContentType("text/html");
console.setEditable(false);
console.setText("<center><h1><u>Console:</u></h1></center>");
changelog = new JTextPane();
changelog.setContentType("text/html");
changelog.setEditable(false);
changelog.setText("<center><h1><u>Changelog:</u></h1></center>");
consolepanel = new JScrollPane(console);
consolepanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
consolepanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
changelogpanel = new JScrollPane(changelog);
changelogpanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
changelogpanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Splitpanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, consolepanel, changelogpanel);
Splitpanel.setOneTouchExpandable(true);
Splitpanel.setDividerLocation(480);
add(Splitpanel, "w 100%, h 80%, wrap");
add(settingslayer, "w 50%, h 20%");
add(loginlayer, "w 50%, h 20%");
}
}
I'm sorry for my bad english. This is my first question in stackoverflow so just tell me if I did something wrong. Thanks for help!
add(Splitpanel, "w 100%, h 80%, wrap");
should be
add(Splitpanel, "w 100%, h 80%, spanx, wrap");

setAlignmentX(CENTER_ALIGNMENT) does not center boxLayout in JFrame

I want to keep my two JLabel text have Left alignment and at the same time place my boxLayout in the center of the JFrame.
I tried setAlignmentX(CENTER_ALIGNMENT) on my boxlayout panel but it's not placing my boxlayout in the center.
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GuiTest extends JFrame {
private static final long serialVersionUID = 1L;
private JLabel jLabelOne = new JLabel();
private JLabel jLabelTwo = new JLabel();
private JPanel panel = new JPanel();
private BoxLayout boxLayout = new BoxLayout(panel,BoxLayout.Y_AXIS);
public GuiTest() {
jLabelOne.setAlignmentX(LEFT_ALIGNMENT);
jLabelTwo.setAlignmentX(LEFT_ALIGNMENT);
jLabelOne.setText("This is text one");
jLabelTwo.setText("This is text two");
panel.setLayout(boxLayout);
panel.add(jLabelOne);
panel.add(jLabelTwo);
panel.setAlignmentX(CENTER_ALIGNMENT);
add(panel);
pack();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(1024,768);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String args[]) {
new GuiTest();
}
}
This won't achieve anything I believe:
panel.setAlignmentX(CENTER_ALIGNMENT);
because you're adding the panel to the JFrame's contentPane, a Container that uses BorderLayout, and are in fact adding it in a default way, meaning BorderLayout.CENTER.
Consider giving the contentPane a GridBagLayout, and adding the panel JPanel in a default way, which should center it. This will only be seen if its preferred size is smaller than that JFrame's contentPane.
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GuiTest extends JFrame {
private static final long serialVersionUID = 1L;
private JLabel jLabelOne = new JLabel();
private JLabel jLabelTwo = new JLabel();
private JPanel panel = new JPanel();
private BoxLayout boxLayout = new BoxLayout(panel,BoxLayout.Y_AXIS);
public GuiTest() {
panel.setLayout(boxLayout);
jLabelOne.setAlignmentX(CENTER_ALIGNMENT);
jLabelTwo.setAlignmentX(CENTER_ALIGNMENT);
jLabelOne.setText("This is text one");
jLabelTwo.setText("This is text two");
panel.add(jLabelOne);
panel.add(jLabelTwo);
panel.setAlignmentX(CENTER_ALIGNMENT);
add(panel);
setSize(1024,768);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String args[]) {
new GuiTest();
}
}
This should get you what you want. You had some things out of order.

centering JLabel in a panel

For some reason, the "Java Text" JLabel does not center. I've looked up how to do it and seen various examples, the most promising being http://www.java2s.com/Code/Java/Swing-JFC/AsimpledemonstrationoftextalignmentinJLabels.htm but it's not working. Here's the whole code if you wish to run it yourself with a few in-code comments so you don't have to bother searching through its entirety:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingConstants;
public class FontViewer
{
static JCheckBox checkBoxBold;
static JCheckBox checkBoxItalic;
static JCheckBox checkBoxCenter;
static JPanel textPanel;
static JLabel textLabel;
static JComboBox fontName;
static JComboBox fontSize;
static JRadioButton redButton;
static JRadioButton whiteButton;
static JRadioButton blueButton;
static ActionListener listener;
public static void main(String[] args)
{
final int FRAME_SIZE_X = 250;
final int FRAME_SIZE_Y = 400;
JFrame frame = new JFrame();
frame.setSize(FRAME_SIZE_X, FRAME_SIZE_Y);
JPanel face = new JPanel();
face.setLayout(new GridLayout(2, 1));
// listener inner class
class FontListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
int fontStyle = 0;
if (checkBoxBold.isSelected())
fontStyle = fontStyle + Font.BOLD;
if (checkBoxItalic.isSelected())
fontStyle = fontStyle + Font.ITALIC;
// this if statement does not work
if (checkBoxCenter.isSelected())
textLabel.setHorizontalAlignment(SwingConstants.CENTER);
String textFont = (String) fontName.getSelectedItem();
int textSize = Integer.parseInt((String) fontSize.getSelectedItem());
textLabel.setFont(new Font(textFont, fontStyle, textSize));
if (redButton.isSelected())
textLabel.setForeground(Color.RED);
else if (whiteButton.isSelected())
textLabel.setForeground(Color.WHITE);
else if (blueButton.isSelected())
textLabel.setForeground(Color.BLUE);
textLabel.repaint();
}
}
listener = new FontListener();
JPanel bottomFace = new JPanel();
bottomFace.setLayout(new GridLayout(3, 1));
textPanel = createTextPanel();
JPanel checkBoxPanel = createCheckBoxPanel();
JPanel comboPanel = createComboPanel();
JPanel radioButtonsPanel = createButtonsPanel();
face.add(textPanel);
bottomFace.add(checkBoxPanel);
bottomFace.add(comboPanel);
bottomFace.add(radioButtonsPanel);
face.add(bottomFace);
frame.add(face);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static JPanel createTextPanel()
{
final int DEFAULT_FONT_SIZE = 12;
textPanel = new JPanel();
textPanel.setLayout(new BorderLayout());
textLabel = new JLabel("Java Text");
textLabel.setFont(new Font("Times", 0, DEFAULT_FONT_SIZE));
textPanel.add(textLabel, BorderLayout.WEST);
return textPanel;
}
// check boxes created and programmed here
private static JPanel createCheckBoxPanel()
{
JPanel checkBoxPanel = new JPanel();
checkBoxBold = new JCheckBox("Bold");
checkBoxItalic = new JCheckBox("Italic");
checkBoxCenter = new JCheckBox("Center");
checkBoxBold.addActionListener(listener);
checkBoxItalic.addActionListener(listener);
checkBoxCenter.addActionListener(listener);
checkBoxPanel.add(checkBoxBold);
checkBoxPanel.add(checkBoxItalic);
checkBoxPanel.add(checkBoxCenter);
return checkBoxPanel;
}
private static JPanel createComboPanel()
{
JPanel comboPanel = new JPanel();
fontName = new JComboBox();
fontName.addItem("Times");
fontName.addItem("Serif");
fontName.addItem("Courier");
fontSize = new JComboBox();
fontSize.addItem("12");
fontSize.addItem("24");
fontSize.addItem("36");
comboPanel.add(fontName);
comboPanel.add(fontSize);
fontName.addActionListener(listener);
fontSize.addActionListener(listener);
return comboPanel;
}
private static JPanel createButtonsPanel()
{
JPanel radioButtonsPanel = new JPanel();
redButton = new JRadioButton("Red");
whiteButton = new JRadioButton("White");
blueButton = new JRadioButton("Blue");
redButton.addActionListener(listener);
whiteButton.addActionListener(listener);
blueButton.addActionListener(listener);
ButtonGroup colors = new ButtonGroup();
colors.add(redButton);
colors.add(whiteButton);
colors.add(blueButton);
radioButtonsPanel.add(redButton);
radioButtonsPanel.add(whiteButton);
radioButtonsPanel.add(blueButton);
return radioButtonsPanel;
}
}
I'm completely puzzled by this anomaly and any help or advice is greatly appreciated! Thank you so much in advance.
The textLabel is anchored to the BorderLayout.WEST position of your textPanel. Move it to the center:
textPanel.add(textLabel, BorderLayout.CENTER);

My text does not change. I don't understand why

I don't understand why this Java code isn't working. It's a GUI project I'm working on and I'm trying to get the JLabel to change to bold, italic, etc. via some check boxes:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class FontViewer {
static JCheckBox checkBoxBold;
static JCheckBox checkBoxItalic;
static JCheckBox checkBoxCenter;
static JPanel textPanel;
static JLabel textLabel;
static JComboBox fontName;
static JComboBox fontSize;
static ActionListener listener;
public static void main(String[] args) {
final int FRAME_SIZE_X = 250;
final int FRAME_SIZE_Y = 400;
JFrame frame = new JFrame();
frame.setSize(FRAME_SIZE_X, FRAME_SIZE_Y);
JPanel face = new JPanel();
face.setLayout(new GridLayout(2, 1));
JPanel bottomFace = new JPanel();
bottomFace.setLayout(new GridLayout(3, 1));
textPanel = createTextPanel();
JPanel checkBoxPanel = createCheckBoxPanel();
JPanel comboPanel = createComboPanel();
JPanel radioButtonsPanel = createButtonsPanel();
face.add(textPanel);
bottomFace.add(checkBoxPanel);
bottomFace.add(comboPanel);
bottomFace.add(radioButtonsPanel);
face.add(bottomFace);
frame.add(face);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
class FontListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
int fontStyle = 0;
if (checkBoxBold.isSelected())
fontStyle = fontStyle + Font.BOLD;
if (checkBoxItalic.isSelected())
fontStyle = fontStyle + Font.ITALIC;
if (checkBoxCenter.isSelected())
textPanel.add(textLabel, BorderLayout.CENTER);
String textFont = (String) fontName.getSelectedItem();
int textSize = Integer.parseInt((String) fontSize
.getSelectedItem());
textLabel.setFont(new Font(textFont, fontStyle, textSize));
textLabel.repaint();
}
}
listener = new FontListener();
}
private static JPanel createTextPanel() {
textPanel = new JPanel();
textPanel.setLayout(new BorderLayout());
textLabel = new JLabel("Java Text");
textPanel.add(textLabel, BorderLayout.WEST);
return textPanel;
}
private static JPanel createCheckBoxPanel() {
JPanel checkBoxPanel = new JPanel();
checkBoxBold = new JCheckBox("Bold");
checkBoxItalic = new JCheckBox("Italic");
checkBoxCenter = new JCheckBox("Center");
checkBoxBold.addActionListener(listener);
checkBoxItalic.addActionListener(listener);
checkBoxCenter.addActionListener(listener);
checkBoxPanel.add(checkBoxBold);
checkBoxPanel.add(checkBoxItalic);
checkBoxPanel.add(checkBoxCenter);
return checkBoxPanel;
}
private static JPanel createComboPanel() {
JPanel comboPanel = new JPanel();
fontName = new JComboBox();
fontName.addItem("Serif");
fontName.addItem("Courier");
fontSize = new JComboBox();
fontSize.addItem("12");
fontSize.addItem("24");
fontSize.addItem("36");
comboPanel.add(fontName);
comboPanel.add(fontSize);
return comboPanel;
}
private static JPanel createButtonsPanel() {
JPanel radioButtonsPanel = new JPanel();
JRadioButton redButton = new JRadioButton("Red");
JRadioButton whiteButton = new JRadioButton("White");
JRadioButton blueButton = new JRadioButton("Blue");
ButtonGroup colors = new ButtonGroup();
colors.add(redButton);
colors.add(whiteButton);
colors.add(blueButton);
radioButtonsPanel.add(redButton);
radioButtonsPanel.add(whiteButton);
radioButtonsPanel.add(blueButton);
return radioButtonsPanel;
}
}
When I press any of the check boxes, the JLabel object does not change. Any help is greatly appreciated and thank you so much in advance.
Note: As of now, I only wish to know why the check boxes are not working. This code is incomplete, I'm aware of this. Thank you once again.
At the time you added the listener to the check boxes, the value of listener was null. listener is not initialized until the very end of the main method.
Try to initialize the listeners before creating JFrame. It worked for me. Of course the definition of the FontListener class has to be put before listener declaration accordingly.
//...
listener = new FontListener();
JFrame frame = new JFrame();
//...

Categories

Resources