Why does part of my RichJLabel text look covered/hidden? - swing

I've been reading the Swing Hacks book and have used some of their code for the RichJLabel part. I understand what the code does, but not why some of the word is covered or looks hidden. It's not that it's not drawing all of the text because even half of the 'a' in horizontal is missing.
//imported libraries for the GUI
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.*;
import java.awt.Toolkit;
import java.awt.Dimension;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.*;
//Rich JLabel
import java.awt.GraphicsEnvironment;
import java.awt.Graphics2D;
import java.awt.FontMetrics;
import java.awt.RenderingHints;
import java.awt.font.*;
import javax.swing.ListSelectionModel;
import java.awt.Color;
import java.awt.Font;
public class nameInterfaceOne
{
//Declared components
static JFrame frame;
static JPanel TotalGUI, northP, southP, eastP, centerP, westP;
static JButton buttons;
//Frame method
public nameInterfaceOne()
{
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} //For a different look & feel, change the text in the speech marks
catch (ClassNotFoundException e) {}
catch (InstantiationException e) {}
catch (IllegalAccessException e) {}
catch (UnsupportedLookAndFeelException e) {}
frame = new JFrame("Interface");
frame.setExtendedState(frame.NORMAL);
frame.getContentPane().add(create_Content_Pane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500); //Size of main window
frame.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
// gets & sets frame size/location
int fw = frame.getSize().width;
int fh = frame.getSize().height;
int fx = (dim.width-fw)/2;
int fy = (dim.height-fh)/2;
//moves the frame
frame.setLocation(fx, fy);
}
public JPanel create_Content_Pane()
{
TotalGUI = new JPanel();
TotalGUI.setLayout(new BorderLayout(5,5)); //set layout for the Container Pane
northP = new JPanel();
northP.setBorder(new TitledBorder(new EtchedBorder(), "Label"));
TotalGUI.add(northP, BorderLayout.NORTH);
RichJLabel label = new RichJLabel("Horizontal", 1);
label.setLeftShadow(1,1,Color.white);
label.setRightShadow(1,1,Color.gray);
label.setForeground(Color.black);
label.setFont(label.getFont().deriveFont(20f));
Box top = Box.createHorizontalBox();
top.add(Box.createHorizontalStrut(10));
top.add(label);
top.add(Box.createHorizontalStrut(10));
northP.add(top);
//EAST Panel
eastP = new JPanel();
eastP.setBorder(new TitledBorder(new EtchedBorder(), "Boxes"));
TotalGUI.add(eastP, BorderLayout.EAST);
Box right = Box.createVerticalBox();
right.add(Box.createVerticalStrut(20));
right.add(new JLabel("EAST SIDE!"));
eastP.add(right);
//WEST Panel
westP = new JPanel();
westP.setBorder(new TitledBorder(new EtchedBorder(), "Buttons"));
TotalGUI.add(westP, BorderLayout.WEST);
Box left = Box.createVerticalBox();
left.add(Box.createVerticalStrut(10));
ButtonGroup JbuttonGroup = new ButtonGroup();
JButton buttons;
JbuttonGroup.add(buttons = new JButton("One"));
buttons.setToolTipText("This is Button One");
left.add(buttons);
left.add(Box.createVerticalStrut(10));
JbuttonGroup.add(buttons = new JButton("Two"));
buttons.setToolTipText("This is Button Two");
left.add(buttons);
left.add(Box.createVerticalStrut(10));
JbuttonGroup.add(buttons = new JButton("Three"));
buttons.setToolTipText("This is Button Three");
left.add(buttons);
left.add(Box.createVerticalStrut(10));
westP.add(left);
TotalGUI.setOpaque(true);
return(TotalGUI);
}
//Main method calling a new object of
public static void main(String[] args)
{
new nameInterfaceOne();
}
}
//RICH JLABEL CLASS
class RichJLabel extends JLabel
{
private int tracking;
public RichJLabel(String text, int tracking) {
super(text);
this.tracking = tracking;
}
private int left_x, left_y, right_x, right_y;
private Color left_color, right_color;
public void setLeftShadow(int x, int y, Color color) {
left_x = x;
left_y = y;
left_color = color;
}
public void setRightShadow(int x, int y, Color color) {
right_x = x;
right_y = y;
right_color = color;
}
public Dimension getPreferredSize()
{
String text = getText();
FontMetrics fm = this.getFontMetrics(getFont());
int w = fm.stringWidth(text);
w += (text.length())*tracking;
w += left_x + right_x;
int h = fm.getHeight();
h += left_y + right_y;
return new Dimension(w,h);
}
public void paintComponent(Graphics g) {
((Graphics2D)g).setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
char[] chars = getText().toCharArray();
FontMetrics fm = this.getFontMetrics(getFont());
int h = fm.getAscent();
int x = 0;
for(int i=0; i<chars.length; i++)
{
char ch = chars[i];
int w = fm.charWidth(ch) + tracking;
g.setColor(left_color);
g.drawString(""+chars[i],x-left_x,h-left_y);
g.setColor(right_color);
g.drawString(""+chars[i],x+right_x,h+right_y);
g.setColor(this.getForeground());
g.drawString(""+chars[i],x,h);
x+=w;
}
((Graphics2D)g).setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
} // end paintComponent()
}
Thank you in advance for any help :)

Empirically, the problem disappears when adding the label directly to the (default) FlowLayout of northP.
northP.add(label);
Addendum: An alternative is to override getMaximumSize(), as suggested in How to Use BoxLayout: Specifying Component Sizes.
#Override
public Dimension getMaximumSize() {
return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
}

Related

Getting null / empty JtextArea

I crated a Frame which have a panel inside it and the panel have a textarea inside it. Now i created a constructor which makes the frame visible for some time and after that it is set as invisible. Time for which it is visible it shows some massage.
When i run the constructor code inside the main method of outputDisplay class it shows the text massage
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.Timer;
public class OutputDisplay {
static JFrame frame;
JPanel panel;
JTextArea area;
Font font;
public void timer(int time){
Timer timer = new Timer(time, new ActionListener(){
public void actionPerformed(ActionEvent e){
frame.setVisible(false);
}
});
timer.start();
timer.setRepeats(false);
}
OutputDisplay(String ip,int time) throws InterruptedException{
frame = new JFrame("Warning");
frame.setLocation(400, 220);
panel = new JPanel();
area = new JTextArea();
font = new Font("Aharoni", Font.BOLD, 16);
area.setFont(font);
area.setForeground(Color.RED);
area.setSize(200, 200);
int j=0;
String[] t = {ip};
for(int i=0;i<t.length;i++){
area.append(t[i]+"\n");
}//for
panel.add(area);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.pack();
frame.setSize(600, 200);
frame.setVisible(true);
Thread.sleep(time);
j++;
if(j==1){
frame.setVisible(false);
}//if
frame.setResizable(false);
}//constructor
OutputDisplay(String dialogue,String path,int time) throws InterruptedException{
frame = new JFrame("Warning");
frame.setLocation(400, 220);
panel = new JPanel();
area = new JTextArea();
font = new Font("Aharoni", Font.BOLD, 16);
area.setFont(font);
area.setForeground(Color.MAGENTA);
area.setSize(200, 200);
int j=0;
String[] t = {dialogue};
for(int i=0;i<t.length;i++){
area.append(t[i]+"\n");
}//for
panel.add(area);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.pack();
frame.setSize(500, 200);
frame.setVisible(true);
Thread.sleep(time);
j++;
if(j==1){
frame.setVisible(false);
}//if
frame.setResizable(false);
}//constructor
OutputDisplay(String dialogue) throws InterruptedException{
frame = new JFrame("Report");
frame.setLocation(400, 220);
panel = new JPanel();
area = new JTextArea();
font = new Font("Aharoni", Font.BOLD, 16);
area.setFont(font);
area.setForeground(Color.BLUE);
area.setSize(200, 200);
String[] t = {dialogue};
for(int i=0;i<t.length;i++){
area.append(t[i]+"\n");
}//for
panel.add(area);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.pack();
frame.setSize(600, 600);
frame.setVisible(true);
frame.setResizable(false);
}//constructor
public OutputDisplay() {
}//no arg
public void dialogue (String massage) throws InterruptedException{
frame = new JFrame("Massage");
frame.setLocation(400, 220);
JPanel panel = new JPanel();
JTextArea area = new JTextArea();
Font font = new Font("Aharoni", Font.BOLD, 16);
area.setFont(font);
area.setForeground(Color.GREEN);
area.setSize(200, 200);
int j=0;
String[] t = {massage};
for(int i=0;i<t.length;i++){
area.append(t[i]+"\n");
}//for
panel.add(area);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.pack();
frame.setSize(400, 100);
frame.setVisible(true);
Thread.sleep(8*1000);
j++;
if(j==1){
frame.setVisible(false);
}//if
frame.setResizable(false);
}//dialogue
static void warningPopUp (String massage){
JOptionPane.showMessageDialog(null, massage);
}//dialogue
public static void main(String[] args){
new OutputDisplay("We are checking for account validation"+"\n"
+ "If user id and password matches then we will goto websites for updation. " +"\n"
+ "You will get a complete report once we are done", 4*1000);
}//main
}//OutputDisplay
Don't call Thread.sleep(...) on the Swing EDT as that just puts your whole GUI to sleep.
Do use a Swing Timer instead.
Do Google and search this site for similar questions.
Please check out Lesson: Concurrency in Swing
Also check out the Swing Tutorials
Edit
You're still using Thread.sleep, again you shouldn't use it, but instead should use a Timer. Also, never set a JTextArea's size or preferred size ever. Do this and the scrollbars of your JScrollPane won't work. Instead, set its rows and columns.
import java.awt.Color;
import java.awt.Font;
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class TimeLimitedDialogTester {
private static final int EB_GAP = 25;
private JPanel mainPanel = new JPanel();
public TimeLimitedDialogTester() {
mainPanel.add(new JButton(new ShowDialogAction("Show Dialog")));
mainPanel.setBorder(BorderFactory.createEmptyBorder(EB_GAP, 2 * EB_GAP, 2 * EB_GAP, 2 * EB_GAP));
}
public JPanel getMainPanel() {
return mainPanel;
}
#SuppressWarnings("serial")
private class ShowDialogAction extends AbstractAction {
public ShowDialogAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Window mainWin = SwingUtilities.getWindowAncestor(mainPanel);
int seconds = 5;
String dialogTitle = "WARNING";
String text = "We are checking for account validation. If user id and password matches then we"
+ " will go to websites for updating. You will get a complete report once we are done.";
TimeLimitedDialog timeLimitedDialog = new TimeLimitedDialog(mainWin, seconds, dialogTitle, text);
timeLimitedDialog.dialogShow();
}
}
private static void createAndShowGui() {
TimeLimitedDialogTester timeLimitedDialog = new TimeLimitedDialogTester();
JFrame frame = new JFrame("TimeLimitedDialog");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(timeLimitedDialog.getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class TimeLimitedDialog {
private static final int ROWS = 6;
private static final int COLS = 30;
private static final Color FG = Color.green.darker().darker();
private JDialog dialog;
private JTextArea displayArea = new JTextArea(ROWS, COLS);
private int seconds;
public TimeLimitedDialog(Window mainWin, int seconds, String dialogTitle, String text) {
displayArea.setWrapStyleWord(true);
displayArea.setLineWrap(true);
displayArea.setFocusable(false);
displayArea.setText(text);
displayArea.setForeground(FG);
displayArea.setFont(displayArea.getFont().deriveFont(Font.BOLD));
this.seconds = seconds;
dialog = new JDialog(mainWin, dialogTitle, ModalityType.APPLICATION_MODAL);
dialog.add(new JScrollPane(displayArea));
dialog.pack();
dialog.setLocationRelativeTo(mainWin);
}
public void dialogShow() {
new Timer(seconds * 1000, new TimerListener()).start();
dialog.setVisible(true);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (dialog != null && dialog.isVisible()) {
dialog.dispose();
}
((Timer) e.getSource()).stop();
}
}
}

Hangman Game Background Image Not Efficient?

I'm making a Hangman game and it seems that my code doesn't provide me much freedom with using layouts. I added an image to my JFrame then I added a JPanel to my image which I'm using for all the JLabels and JTextFields but it seems to me that its inefficient because in order to change the layout of my JTextFields or JLabels I have to change the layout of my image which messes up the entire looks of the game. How can I make this code more efficient and give myself more freedom to change the layouts of my JLabels and JTextFields without messing everything up? Thanks for the help in advanced.
/*PACKAGE DECLARATION*/
package Game;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
/************************
* GAME MECHANICS CLASS *
* **********************/
public class GameStructure {
/* INSTANCE DECLARATIONS */
private String []wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday"};
private int []length = new int [64];
private JTextField tf;//text field instance variable (used)
private JLabel jl2;//label instance variable (used)
private JLabel jl3;//label instance (working on)
private String letter;
/*****************
* LENGTH METHOD *
* ***************/
public void length(){
jl3 = new JLabel();
int j = 0;
for(j = 0; j<64; j++) {
length[j] = wordList[j].length();//gets length of words in wordList
}//end for
int l = 0;
String line = "";
//create line first then put into .setText
for(int m = 0; m<length[l]; m++) {
line += "__ ";
l++;
}//end for
jl3.setText(line);
}//end length method
/*****************
* WINDOW METHOD *
* ***************/
public void window() {
LoadImageApp i = new LoadImageApp();//calling image class
JFrame gameFrame = new JFrame();//declaration
JPanel jp = new JPanel();
//JPanel jp2 = new JPanel();//jpanel for blanks
JLabel jl = new JLabel("Enter a Letter:");//prompt with label
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
tf = new JTextField(1);//length of text field by character
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jp.add(jl);//add label to panel
jp.add(tf);//add text field to panel
jp.add(jl2);//add letters used
gameFrame.add(i); //adds background image to window
i.add(jp); // adds panel containing label to background image panel
gameFrame.setTitle("Hangman");//title of frame window
gameFrame.setSize(850, 600);//sets size of frame
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when 'x' button pressed
gameFrame.setIconImage(new ImageIcon("Hangman-Game-grey.png").getImage());//set the frame icon to an image loaded from a file
gameFrame.setLocationRelativeTo(null);//window centered
gameFrame.setResizable(false);//user can not resize window
gameFrame.setVisible(true);//display frame
}//end window method
/*********************
* USER INPUT METHOD *
* *******************/
public void userInput() {
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//when enter key pressed
JTextField tf = (JTextField)e.getSource();
letter = tf.getText();
jl2.setText(jl2.getText() + letter + " ");//sets jlabel text to users entered letter
}//end actionPerformed method
});
}//end userInput method
}//end GameMechanics class
/*PACKAGE DECLARATION*/
package Game;
/***********************
* IMPORT DECLARATIONS *
* *********************/
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
/***************
* IMAGE CLASS *
* *************/
public class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon image;
/***********************
* PAINT IMAGE METHOD *
* *********************/
public void paintComponent (Graphics g) {
//setLayout(new BorderLayout());
super.paintComponent(g);
image = new ImageIcon("hangman.png");//image name & type
image.paintIcon(this, g, 270, 20);
}//end paintComponent method
}//end LoadImageApp class
/*PACKAGE DECLARATION*/
package Game;
/*******************
* GAME MAIN CLASS *
* *****************/
public class GameMain {
/***************
* MAIN METHOD *
* *************/
public static void main (String []args) {
GameStructure game = new GameStructure();//declaration
game.length();
game.window();
game.userInput();
}//end main method
}//end GameMain class
Some suggestions:
Don't override a JPanel's paint(...) method, but rather its paintComponent(Graphics g) method, not unless you need to change how it renders its child components or its borders (you don't). Also by doing this you gain some Swing graphics advantages including automatic double buffering.
Never read in an image into the paint or paintComponent method. These methods are one of the main determinants of how responsive your GUI appears to the user, and so you never want to do file I/O in the method. And also, why have code that inefficiently re-reads the same image in whenever paint or paintComponent is called? Why not simply store the image or ImageIcon in a variable once, and be done with it?
Learn and use the layout managers
JPanels that go over drawing or image rendering JPanels often should be non-opaque - so be sure to call setOpaque(false) on them, and also on some other overlying Swing components.
_________________________
Edit
For example, here is my SSCCE that shows an example of getting an image (here off of the internet) in a class constructor. Also note that my SSCCE will work on any computer connected to the internet since it does not require image files, unlike yours. Also code not related to displaying the GUI has been cut out making the remaining code more pertinent to the problem. Consider doing this next time you post an SSCCE.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
class GameStructure {
private JTextField tf;
private JLabel jl2;
public void window() {
LoadImageApp loadImageApp = new LoadImageApp();
JFrame gameFrame = new JFrame();
JPanel jp = new JPanel();
jp.setOpaque(false); //!!
jp.setBorder(BorderFactory.createTitledBorder("jp"));
JLabel jl = new JLabel("Enter a Letter:");
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));
tf = new JTextField(1);
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));
jp.add(jl);
jp.add(tf);
jp.add(jl2);
gameFrame.add(loadImageApp);
loadImageApp.add(jp);
gameFrame.setTitle("Hangman");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// gameFrame.setIconImage(
// new ImageIcon("Hangman-Game-grey.png").getImage());
gameFrame.setResizable(false);
gameFrame.pack();
gameFrame.setLocationRelativeTo(null);
gameFrame.setVisible(true);
}
}
class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 850;
private static final int PREF_H = 600;
private BufferedImage img;
public LoadImageApp() {
// just used as an example public image
String spec = "https://duke.kenai.com/"
+ "SunRIP/.Midsize/SunRIP.png.png";
URL url;
try {
url = new URL(spec);
img = ImageIO.read(url);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
}
public class GameMain {
public static void main(String[] args) {
GameStructure game = new GameStructure();
game.window();
}
}

placing components in GridBagLayout

I am trying to place the JLabel and JTextfield like this,
First Name Textbox -> First Name is a label named as lblFirstname
Last Name Textbox TextBox is JTextField
tried using GridBagLayout,
the constraints applied are,
lblFirstNameCons.gridx = 0;
lblLastNameCons.gridy = 0;
txtFirstName.gridx = 0;
txtLastNameCons.gridy = 3;
I am getting the output like this,
First NameTextbox -> There is no space and also, the JTextField is almost invisible.
The layout should be something like this. The values in parenthesis are the gridx and gridy (grix, gridy):
First Name (0, 0) Textbox (1, 0)
Last Name (0, 1) Textbox (1, 1)
You should make sure that the fill property of the GridBagConstraint is set to HORIZONTAL for the textfield and make sure that the weightx is set to something greater than 0
Or you can indicate to the textfield the desired number of columns to display (this will eventually influence the preferred size of the textfield).
Here is an example showing that:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.net.MalformedURLException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestGridBagLayout {
protected void initUI() throws MalformedURLException {
final JFrame frame = new JFrame();
frame.setTitle(TestGridBagLayout.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel(new GridBagLayout());
JLabel firstName = new JLabel("First name:");
JLabel lastName = new JLabel("Last name:");
JTextField firstNameTF = new JTextField();
JTextField lastNameTF = new JTextField();
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(3, 3, 3, 3);
gbc.weightx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
panel.add(firstName, gbc);
gbc.weightx = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(firstNameTF, gbc);
gbc.gridwidth = 1;
gbc.weightx = 0;
panel.add(lastName, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
panel.add(lastNameTF, gbc);
frame.add(panel);
frame.setSize(300, 200);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new TestGridBagLayout().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}

Margins with LineBorders

I want to have a JTextArea with a LineBorder and leave a little padding between the text and the LineBorder.
Is this possible with the standard classes or do I need a custom "DoubleLine" border (one with the color and one with the margin)?
Some sample code is below...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
public class TextAreaLineBorder extends JFrame
{
private static final long serialVersionUID = 1L;
private class MyPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public MyPanel()
{
setLayout(new FlowLayout());
JTextArea ta = new JTextArea("Some text");
ta.setSize(200, 50);
boolean useDefaultBorder = false;
if (useDefaultBorder)
{
// Setting the margin works fine, with the default border
ta.setMargin(new Insets(12, 12, 12, 12));
Border b = ta.getBorder();
Insets defaultInsets = b.getBorderInsets(ta);
System.out.println("Default Insets: "
+ defaultInsets);
}
else
{
// Try using a non-default LineBorder
LineBorder lb = (LineBorder) BorderFactory.createLineBorder(Color.YELLOW, 2);
ta.setBorder(lb);
// TODO: What should be done so that the LineBorder has Insets?
ta.setMargin(new Insets(12, 12, 12, 12));
Insets lineBorderInsets = lb.getBorderInsets(ta);
System.out.println("LineBorder Insets: " + lineBorderInsets);
}
add(ta);
}
}
public TextAreaLineBorder()
{
setResizable(true);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP);
// Add the panel
tabbedPane.addTab("Button panel", new MyPanel());
add(tabbedPane, BorderLayout.CENTER);
getContentPane().add(tabbedPane);
}
private static void createAndShowGUI()
{
// Create and set up the window.
TextAreaLineBorder frame = new TextAreaLineBorder();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}
You can add the JTextArea to a JScrollPane and put the border around that.
JTextArea JTA = new JTextArea();
JScrollPane JSP = new JScrollPane(JTA);
JSP.setBorder(BorderFactory.createLineBorder(Color.blue));
I created a class that helped me solve this problem. The same solution can likely be used for all JTextComponents.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class JTextAreaWithPaddedBorder extends JTextArea
{
// **********************************************************************
// To modify the sample program using GWT Designer, uncomment this code
// **********************************************************************
// public JTextAreaWithPaddedBorder()
// {
// }
//
// /**
// * Bogus Constructor
// *
// * #wbp.parser.constructor (Use this method in the GWT Designer)
// */
//
// public JTextAreaWithPaddedBorder(int ignore)
// {
// createAndShowGUI();
// }
// **********************************************************************
// To modify the sample program using GWT Designer, uncomment this code
// **********************************************************************
public static void createAndShowGUI()
{
// Create and set up the frame
JFrame frmTextareawithpaddedborder = new JFrame();
frmTextareawithpaddedborder.setTitle("TextAreaWithPaddedBorder");
frmTextareawithpaddedborder.setName("frmTextareawithpaddedborder");
frmTextareawithpaddedborder.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmTextareawithpaddedborder.setBounds(100, 100, 514, 495);
frmTextareawithpaddedborder.setResizable(false);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
frmTextareawithpaddedborder.setContentPane(contentPane);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(5, 5, 490, 395);
scrollPane.setName("scrollPane");
contentPane.add(scrollPane);
final JTextAreaWithPaddedBorder textArea = new JTextAreaWithPaddedBorder();
textArea.setBorder(new LineBorder(new Color(0, 0, 0), 2));
textArea.setName("textArea");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
String text = "The iPhone is a line of smartphones designed and marketed by Apple Inc. The first iPhone was unveiled by Steve Jobs, then CEO of Apple, on January 9, 2007,[1] and released on June 29, 2007. The 5th generation iPhone, the iPhone 4S, was announced on October 4, 2011, and released 10 days later. An iPhone can function as a video camera (video recording was not a standard feature until the iPhone 3GS was released), a camera phone, a portable media player, and an Internet client with email and web browsing capabilities, can send texts and receive visual voicemail, and has both Wi-Fi and cellular data (2G and 3G) connectivity. The user interface is built around the device's multi-touch screen, including a virtual keyboard rather than a physical one.";
textArea.setText(text);
textArea.append("\n\nThis is the text within the TextArea. As the border of the TextArea is changed, the text should display properly.");
contentPane.setLayout(null);
textArea.setBackground(Color.WHITE);
scrollPane.setViewportView(textArea);
btnChangeMargins = new JButton("Change Margins");
btnChangeMargins.setBounds(13, 430, 152, 23);
btnChangeMargins.setName("btnChangeMargins");
btnChangeMargins.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
long t = (new Date()).getTime() % 100;
int top = (int) (t * 18) % 15;
int bottom = (int) (t * 34) % 15;
int left = (int) (t * 52) % 15;
int right = (int) (t * 52) % 15;
Insets insets = new Insets(top, left, bottom, right);
textArea.setMargin(insets);
}
});
contentPane.add(btnChangeMargins);
btnChangeBGColor = new JButton("Change BG Color");
btnChangeBGColor.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
long t = (new Date()).getTime() % 100;
int r = 100 + (int) (t * 18) % 100;
int g = 100 + (int) (t * 34) % 100;
int b = 100 + (int) (t * 52) % 100;
Color c = new Color(r, g, b);
textArea.setBackground(c);
}
});
btnChangeBGColor.setBounds(178, 430, 152, 23);
btnChangeBGColor.setName("btnChangeBGColor");
contentPane.add(btnChangeBGColor);
btnChangeBorder = new JButton("Change Border");
btnChangeBorder.setBounds(343, 430, 152, 23);
btnChangeBorder.setName("btnChangeBorder");
btnChangeBorder.addActionListener(new ActionListener()
{
int last = 0;
#Override
public void actionPerformed(ActionEvent e)
{
Border nextBorder;
switch (last++ % 8)
{
case 0:
nextBorder = BorderFactory.createLoweredBevelBorder();
break;
case 1:
nextBorder = BorderFactory.createEmptyBorder();
break;
case 2:
nextBorder = BorderFactory.createEtchedBorder();
break;
case 3:
nextBorder = BorderFactory.createLineBorder(Color.black, 2);
break;
case 4:
nextBorder = BorderFactory.createRaisedBevelBorder();
break;
case 5:
nextBorder = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.red, 3), BorderFactory
.createLoweredBevelBorder());
break;
case 6:
nextBorder = BorderFactory.createMatteBorder(2, 15, 1, 15, new Color(255, 0, 0));
break;
case 7:
nextBorder = BorderFactory.createTitledBorder("Titled Border");
break;
default:
nextBorder = BorderFactory.createTitledBorder("Titled Border");
}
textArea.setBorder(nextBorder);
}
});
contentPane.add(btnChangeBorder);
frmTextareawithpaddedborder.setVisible(true);
}
private static final long serialVersionUID = 1L;
private static JButton btnChangeMargins;
private static JButton btnChangeBGColor;
private static JButton btnChangeBorder;
#Override
public void setBorder(Border border)
{
int paddingWidth = 0;
Border currentBorder = getBorder();
if (currentBorder != null)
{
// The padding width will be the minimum width specified in the insets
Insets insets = getMargin();
paddingWidth = Math.min(insets.bottom, insets.top);
paddingWidth = Math.min(paddingWidth, insets.left);
paddingWidth = Math.min(paddingWidth, insets.right);
}
/*
* Use a LineBorder for the padding.
*
* The color must be the same as the background color of the TextComponent
*/
super.setBorder(new CompoundBorder(border, BorderFactory.createLineBorder(getBackground(), paddingWidth)));
}
#Override
public void setBackground(Color c)
{
super.setBackground(c);
Border b = getBorder();
if (b != null)
{
setBorder(((CompoundBorder) b).getOutsideBorder());
}
}
#Override
public void setMargin(Insets m)
{
super.setMargin(m);
Border b = getBorder();
if (b != null)
{
setBorder(((CompoundBorder) b).getOutsideBorder());
}
}
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}

Gui - JPanel adding JComponent into GridLayout cell

I'm trying to display a frame using GridLayout, but one of my panels isn't displaying.
The JPanel that I'm having trouble with (gridPanel) is supposed to have a 50 by 50 GridLayout and each cell in that grid is supposed to have a Square object added to it. Then that panel is supposed to be added to the frame, but it doesn't display.
import java.awt.*;
import javax.swing.*;
public class Gui extends JFrame{
JPanel buttonPanel, populationPanel, velocityPanel, gridPanel;
JButton setupButton, stepButton, goButton;
JLabel populationLabel, velocityLabel;
JSlider populationSlider, velocitySlider;
Square [] [] square;
public Gui() {
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//Set up JButtons
buttonPanel = new JPanel();
setupButton = new JButton("Setup");
stepButton = new JButton("Step");
goButton = new JButton("Go");
buttonPanel.add(setupButton);
buttonPanel.add(stepButton);
buttonPanel.add(goButton);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 2; //2 columns wide
add(buttonPanel, c);
//Set up populationPanel
populationPanel = new JPanel();
populationLabel = new JLabel("Population");
populationSlider = new JSlider(JSlider.HORIZONTAL,0, 200, 1);
populationPanel.add(populationLabel);
populationPanel.add(populationSlider);
c.fill = GridBagConstraints.LAST_LINE_END;
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 2; //2 columns wide
add(populationPanel, c);
//Set up velocityPanel
velocityPanel = new JPanel();
velocityLabel = new JLabel(" Velocity");
velocitySlider = new JSlider(JSlider.HORIZONTAL,0, 200, 1);
velocityPanel.add(velocityLabel);
velocityPanel.add(velocitySlider);
c.fill = GridBagConstraints.LAST_LINE_END;
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 2; //2 columns wide
add(velocityPanel, c);
//Set up gridPanel
JPanel gridPanel = new JPanel(new GridLayout(50, 50));
square = new Square[50][50];
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
square[i][j] = new Square();
gridPanel.add(square[i][j]);
}
}
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2; //2 columns wide
add(gridPanel, c);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
Gui frame = new Gui();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Square class
import java.awt.*;
import javax.swing.*;
public class Square extends JComponent{
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(10, 10, 10, 10);
}
}
The reason you are not seeing anything are two-fold (though not entirely sure if the second is intentional, guessing on that part :)
JComponent is a bare-bone container, it has no ui delegate and no inherent size - it's up to your code to return something reasonable for min/max/pref
the painting rect is hard-coded to "somewhere" inside, which might or might be inside the actual component area
Following is showing (border just to see the boundaries)
public static class Square extends JComponent {
public Square() {
setBorder(BorderFactory.createLineBorder(Color.RED));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(10, 10);
}
#Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
}