Java JLabel background color not working? - java

I'm learning how to create application in Java.
I'm having trouble getting the JLabel to have a background color whilst the JPanel is white, behind it. Also, is there a way to resize the JPanel to half of what the JFrame is?
Any help would be very much appreciated. Thank you.
package PracticeOne;
import java.awt.BorderLayout;
public class PracticeOne {
public static void main(String[] args) {
Frame container = new Frame();
Panel box = new Panel();
Label txt = new Label();
box.add(txt);
container.add(box, BorderLayout.CENTER);
}
}
package PracticeOne;
import javax.swing.JFrame;
public class Frame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
Frame(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setTitle("Testing this out");
}
}
package PracticeOne;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JPanel;
public class Panel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public Dimension d = new Dimension(100,100);
Panel(){
this.setSize(d);
this.setAlignmentX(CENTER_ALIGNMENT);
this.setBackground(Color.WHITE);
}
}
package PracticeOne;
import java.awt.Color;
import javax.swing.JLabel;
public class Label extends JLabel {
/**
*
*/
private static final long serialVersionUID = 1L;
Label(){
this.setSize(50, 50);
this.setText("ya boy is working here");
this.setForeground(Color.BLACK);
this.setBackground(Color.ORANGE);
}
}

I'm having trouble getting the JLabel to have a background color whilst the JPanel is white
You need to call setOpaque(true); in your JLabel
Also, is there a way to resize the JPanel to half of what the JFrame is?
You could use a GridLayout, and place 2 JPanels in it, that way, you're going to have 2 JPanels using half the size of your JFrame each.
Also, rename your classes, Panel belongs to the name of a class in AWT, same for Frame and Label, this might confuse your (and whoever reads your code).
Never extend JFrame, instead build your GUI based on JPanels. See extends JFrame vs creating it inside of class and The use of multiple JFrames, Good / Bad practice? The general consensus says it's bad.
Also you should also check Should I avoid the use of setPreferred|Maximum|MinimumSize() in Swing? Again, yes, you should and instead override the getPreferredSize() method.
Don't forget to place your program on the Event Dispatch Thread (EDT) by changing your main() method as follows:
public static void main(String[] args) {
//Java 8 with lambda expressions
SwingUtilities.invokeLater(() ->
//Your code here
);
//Java 7 and below (Or 8 without lambda expressions)
SwingUtilities.invokeLater(new Runnable() {
//Your code here
});
}
Now, with all the above recommendations, your code should now look like this:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class HalfSizePanelWithLabelInDifferentColor {
private JFrame frame;
private Container contentPane;
private JPanel pane;
private JPanel pane2;
private JLabel label;
private static final Dimension dim = new Dimension(100, 100);
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new HalfSizePanelWithLabelInDifferentColor().createAndShowGui());
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
contentPane = frame.getContentPane();
pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return dim;
}
};
pane2 = new JPanel();
pane.setOpaque(false);
pane2.setOpaque(false);
pane.setBorder(BorderFactory.createLineBorder(Color.RED));
pane2.setBorder(BorderFactory.createLineBorder(Color.BLUE));
label = new JLabel("Hello World!");
label.setBackground(Color.GREEN);
label.setOpaque(true);
contentPane.setLayout(new GridLayout(2, 1));
pane.add(label);
contentPane.add(pane);
contentPane.add(pane2);
contentPane.setBackground(Color.WHITE);
frame.setContentPane(contentPane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
And your output would be like this:
Note that I added some colored borders to show where a pane starts and ends and where the other one starts and ends

Related

How to achieve the desired layout?

I am trying to create this layout
for a project using Swing in Java 8, but since Swing is something I have never learned I am really struggling with trying to get the layout set up. I've tried my best but I just do not understand this. I don't think I will have any trouble with the backend functionality of the window I just can't get it to look the way I need it.
A common strategy to solve complex computing tasks, is to break them into small, well defined manageable tasks. Divide and conquer.
This also applies to gui: break the design into small, easy to layout containers.
In this case, consider dividing the design into 4 areas (JPanels) nested in a main JPanel:
This basic layout, that can get you started, can be achieved like so:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Gui {
private final String text ="Growing ";
private JPanel grid;
private JFrame f;
Gui() {
creategui();
}
void creategui(){
f = new JFrame("Hexagon Cross For Less");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setLayout(new BoxLayout(f.getContentPane(),BoxLayout.Y_AXIS));
JPanel primes = new JPanel();
primes.setPreferredSize(new Dimension(1000,120));
primes.setBackground(Color.CYAN);
f.add(primes);
JPanel xFiles = new JPanel();
xFiles.setPreferredSize(new Dimension(1000,120));
xFiles.setBackground(Color.YELLOW);
f.add(xFiles);
JPanel actions = new JPanel();
actions.setPreferredSize(new Dimension(1000,120));
actions.setBackground(Color.GREEN);
f.add(actions);
JPanel status = new JPanel();
status.setPreferredSize(new Dimension(1000,40));
status.setBackground(Color.LIGHT_GRAY);
f.add(status);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new Gui();
}
}
it produces the following layout:
It can be better structured by representing each such distinct area (JPanel) in a separate class.
The following code produces exactly the same layout (it is a single-file mre. Copy past it to Gui.java and run):
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Gui {
private final String text ="Growing ";
private JPanel grid;
private JFrame f;
Gui() {
creategui();
}
void creategui(){
f = new JFrame("Hexagon Cross For Less");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.add(new MainPane());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
new Gui();
}
}
class MainPane extends JPanel{
MainPane() {
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
add(new Primes());
add(new CrossFiles());
add(new Actions());
add(new Status());
}
}
class Primes extends JPanel{
Primes() {
setPreferredSize(new Dimension(1000,120));
setBackground(Color.CYAN);
}
}
class CrossFiles extends JPanel{
CrossFiles() {
setPreferredSize(new Dimension(1000,120));
setBackground(Color.YELLOW);
}
}
class Actions extends JPanel{
Actions() {
setPreferredSize(new Dimension(1000,120));
setBackground(Color.GREEN);
}
}
class Status extends JPanel{
Status() {
setPreferredSize(new Dimension(1000,40));
setBackground(Color.LIGHT_GRAY);
}
}
To continue, apply the same technique and define the layout of each of the 4 sub panels.
The design of Actions could be :
Hint: Primes and CrossFiles have exactly the same layout.

Java FlowLayout

I am writing some Java code that allows the user to see a frame with JLabel, JTextField and JButton.
I want the JLabel to be called "Count" and I have a problem with FlowLayout.
I want the interface to look like this:
Instead, I have this:
This is my code:
package modul1_Interfate_Grafice;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Exercitiu04 implements ActionListener {
private JFrame frame;
private JLabel labelCount;
private JTextField tfCount;
private JButton buttonCount;
private int count = 0;
public void go() {
frame = new JFrame("Java Counter");
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
frame.getContentPane().add(BorderLayout.CENTER, labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
labelCount.add(tfCount);
buttonCount = new JButton("Count");
labelCount.add(buttonCount);
buttonCount.addActionListener(this);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(350, 150);
frame.setLocation(400, 200);
}
#Override
public void actionPerformed(ActionEvent event) {
count++;
tfCount.setText(count + "");
}
public static void main(String[] args) {
Exercitiu04 a = new Exercitiu04();
a.go();
}
}
Solve it.
Instead of labelCount.setLayout(new FlowLayout());` i should have had
frame.setLayout(new FlowLayout());
From description of JLabel class,
JLabel is:
A display area for a short text string or an image, or both.
But here: labelCount.add(tfCount) and here labelCount.add(buttonCount) you're trying to put a textfield and a button into a label. In this case, positions of button and textfield are controlled by FlowLayout but position of the text in the label is not.
Instead of this, you should put all of your elements in common JPanel, like this:
...
frame = new JFrame("Java Counter");
frame.setLayout(new BorderLayout());
JPanel wrapper = new JPanel(); // JPanel has FlowLayout by default
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
wrapper.add(labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
wrapper.add(tfCount);
buttonCount = new JButton("Count");
buttonCount.addActionListener(this);
wrapper.add(buttonCount);
frame.add(BorderLayout.CENTER, wrapper);
...
And, like MasterBlaster said, you should put swing methods in EDT.
There are only two things you should know about FlowLayout:
a) It is a default layout manager of the JPanel component
b) It is good for nothing.
This trivial layout cannot be achieved with FlowLayout.
When doing layouts in Swing, you should familiarize yourself
with some powerful layout managers. I recommend MigLayout and
GroupLayout.
package com.zetcode;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
/*
Simple UI with a MigLayout manager.
Author Jan Bodnar
Website zetcode.com
*/
public class MigLayoutCounterEx extends JFrame {
public MigLayoutCounterEx() {
initUI();
}
private void initUI() {
JLabel lbl = new JLabel("Counter");
JTextField field = new JTextField(10);
JButton btn = new JButton("Count");
createLayout(lbl, field, btn);
setTitle("Java Counter");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
setLayout(new MigLayout());
add(arg[0]);
add(arg[1]);
add(arg[2]);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MigLayoutCounterEx ex = new MigLayoutCounterEx();
ex.setVisible(true);
});
}
}
The example is trivial. You just put the three components into the
cells.
Screenshot:
You shouldn't use setSize when dealing with FlowLayout. Instead use pack(). It makes the window just about big enough to fit all your components in. That should tidy things up for you

How to edit JTextField?

I want to write a simple Swing application with a button and a text field at the bottom. I'm using a JTextField but it is not clickable. I searched on the web and SO, but I could not find a solution. In question How to Set Focus on JTextField?, I found the following :
addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
entry.requestFocus();
}
});
but this does not help. In this other question (How do you set a focus on Textfield in Swing?) I found Component.requestFocus() but this does not work either. I also tried
entry.setFocusable(true);
entry.setEditable(true);
entry.setEnabled(true);
without effects. My code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class StackSample extends JFrame {
public StackSample() {
initUI();
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void initUI() {
JPanel panel = new JPanel(new BorderLayout());
add(panel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new FlowLayout());
panel.add(bottomPanel, BorderLayout.SOUTH);
JButton buttonDraw = new JButton("Draw");
bottomPanel.add(buttonDraw);
JTextField entry = new JTextField();
bottomPanel.add(entry);
setPreferredSize(new Dimension(250, 150));
setLocationRelativeTo(null);
}
private static final long serialVersionUID = 8359448221778584189L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyApp app = new MyApp();
app.setVisible(true);
}
});
}
}
Your JTextField is clickable. The only problem is that it's too small.
This is because you're using FlowLayout, which will make components as small as possible.
One solution is to simply switch to a layout that allows components to fill as much space as possible, such as BoxLayout:
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel,BoxLayout.X_AXIS));
You haven't specified a size for your JTextField, so it defaults to zero characters wide. Try using the constructor that specifies the number of columns.
Also, what is MyApp? I can't see any evidence that your StackSample is ever created or used.

frame.getContentPane().add(); not working properly?

I've been having some (very annoying) trouble with these scripts that I've created.
Sburb.java
import java.awt.Color;
import javax.swing.*;
public class Sburb
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Welcome to Sburb");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
spirograph page = new spirograph();
progressbar bar = new progressbar();
frame.getContentPane().add(page);
frame.getContentPane().add(bar);
frame.pack();
frame.setVisible(true);
frame.setResizable(true);
}
}
progressbar.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class progressbar extends JPanel
{
JProgressBar current;
JTextArea out;
JButton find;
Thread runner;
int num = 1;
progressbar()
{
super();
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pane = new JPanel();
pane.setLayout(new FlowLayout());
current = new JProgressBar(0, 2000);
current.setStringPainted(false);
pane.add(current);
//setContentPane(pane);
}
public void iterate() {
while (num < 2000) {
current.setValue(num);
try {
Thread.sleep(300);
} catch (InterruptedException e) { }
num += 5;
}
}
// public static void main(String[] arguments) {
// progressbar frame = new progressbar();
// frame.pack();
// frame.setVisible(true);
// frame.iterate();
// }
}
spirograph.java
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class spirograph extends JPanel
{
private ImageIcon image;
private JLabel label;
private JLabel frame = new JLabel();
private JPanel panel = new JPanel();
spirograph()
{
this.setOpaque(true);
this.setBackground(Color.BLACK);
setLayout(new FlowLayout());
image = new ImageIcon(getClass().getResource("Gate.gif"));
label = new JLabel(image);
add(label);
progressbar bar = new progressbar();
}
}
I'm trying to call the file "progressbar" to the Sburb file but when I do, it gives me just the simple JFrame of this (not fixed):
http://imgur.com/1aAmPwJ
And when I get rid of the "frame.getContentPane().add(bar);" in Sburb.java, it gives me this (fixed, kind-of):
http://imgur.com/15aGtT2
How do I fix this? I've looked everywhere and yet I still can't figure it out! I also can't seem to figure out how to align the bar directly below the gif.
frame.getContentPane().add(page);
frame.getContentPane().add(bar);
The content pane of a JFrame is a set to a BorderLayout which can only accept one component in any one of the border layout constraints. Given no constraints were supplied here, the JRE will try to put them both in the CENTER.
For this, and a variety of other reasons, I would advise to ignore the existing content pane, arrange the entire GUI (as many panels as it consists of) into another panel (let's call it ui) then call
frame.setContentPane(ui);

How to reference JFrame

I have a problem which is most likely "simple" however I can't figure it out. I am trying to reference my current JFrame so that I can dispose of it, and create a new one, thus "resetting" the program, however I and having trouble figuring out how to reference the JFrame, I have tried, super, this and getParent(), but none of the seem to work. Thanks for any / all help. ^^
Here is my code:
Main Class, just sets up the Jframe and calls the class that creates everything:
public static void main(String args[]) {
JFrame window = new JFrame();
Director director = new Director(window, args);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.pack();
window.setVisible(true);
}
}
Class the creates everything:
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class Director extends JFrame implements CollisionListener {
private BrickWall wall;
private JLabel gameTitle, gameScore, gameLives;
private JPanel controlPanel;
private JButton reset, quit;
private JRadioButton hard, normal, easy;
private int score = 6, lives = 5;
private ButtonGroup difficulty;
public Director(JFrame window, String[] args) {
window.getContentPane().add(makeGamePanel(), BorderLayout.CENTER);
window.getContentPane().add(gameControlPanel(), BorderLayout.NORTH);
}
public void collisionDetected(CollisionEvent e) {
wall.setBrick(e.getRow(), e.getColumn(), null);
}
private JComponent makeGamePanel() {
wall = new BrickWall();
wall.addCollisionListener(this);
wall.buildWall(3, 6, 1, wall.getColumns(), Color.GRAY);
return wall;
}
// Reset method I'm trying to dispose of the JFrame in.
private void reset() {
JFrame frame = new JFrame();
frame.getContentPane().add(makeGamePanel(), BorderLayout.CENTER);
frame.getContentPane().add(gameControlPanel(), BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private JComponent gameControlPanel() {
// CONTROL PANEL PANEL!
controlPanel = new JPanel();
gameTitle = new JLabel("Brickles");
gameScore = new JLabel("Score:" + " " + score);
gameLives = new JLabel("Lives:" + " " + lives);
reset = new JButton("Reset");
quit = new JButton("Quit");
hard = new JRadioButton("Hard", false);
normal = new JRadioButton("Normal", true);
easy = new JRadioButton("Easy", false);
difficulty = new ButtonGroup();
difficulty.add(hard);
difficulty.add(normal);
difficulty.add(easy);
controlPanel.setLayout(new GridLayout(4, 2));
controlPanel.add(gameTitle);
controlPanel.add(gameScore);
controlPanel.add(hard);
controlPanel.add(gameLives);
controlPanel.add(normal);
controlPanel.add(reset);
controlPanel.add(easy);
controlPanel.add(quit);
// Action Listener, where I'm caling the reset method.
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
reset();
}
});
return controlPanel;
}
}
You can refer to the "outer this" from a nested class with the following syntax:
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Director.this.reset();
}
});
Yes, you can refer to the outer class by specifying it with the class name as noted in DSquare's good answer (1+ to it), but I urge you not to fling JFrame's at the user as you're program is trying to do. I recommend:
Instead of opening and closing multiple JFrames, use only one JFrame as the main application's window.
If you need helper windows, such as modal windows to get critical information that is absolutely needed, before the program can progress, use modal dialogs such as JDialogs or JOptionPanes.
If you need to swap GUI's, instead of swapping JFrames, swap "views" inside the JFrame via a CardLayout.
Gear your code towards creating these JPanel views and not JFrames as it will make your Swing GUI's much more flexible and portable.

Categories

Resources