I am a noob in java and am trying to make a kind of text adventure game. I want to be able to have the program have some kind of fade ability as it transitions from one layout of the UI to another.
I really have no idea what the best approach to this problem would be or if its really even feasible, but I have so far been trying to have a Jpanel that covers the entire window and uses a timer to fade in to cover everything else in black, or fades out from black to transparency thereby revealing everything underneath.
I have been testing this idea by trying to fade in/out the program at the start just to get the logic for the fade system working before trying to have it as a transition effect. The fade-out kind of works, but I have the program output the alpha level and the screen is turning black at around alpha 50 out of 255 which is confusing me. The fade-in does not work at all.
Here is the code for the fade method:
static int opacityCounter = 0;
public void fadeOut(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 0;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter++;
gui.window.add(frame);
if(opacityCounter >= 255){
opacityCounter = 255;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
This is the code where the "fadePanel" that covers the window is created and deployed in the method.
fadeScreen = new JPanel();
fadeScreen.setBounds(0,0,800,600);
fadeScreen.setBackground(Color.black);
window.add(fadeScreen);
game.visibilityManager.fadeOut(this.fadeScreen);
To clarify I want something that goes from a UI layout like this:
fades to black, before fading back to a UI that looks like this
This is a minimal reproducible example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test {
JFrame window;
JPanel fadeScreen, screen1, screen2;
JLabel text1, text2;
Timer fadeTimer;
public Test(){
//Frame Window
window = new JFrame();
window.setSize(800,600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.blue);
//Screen 1
screen1 = new JPanel();
screen1.setBounds(100, 100, 600, 125);
screen1.setBackground(Color.white);
text1 = new JLabel("Text1");
screen1.add(text1);
window.add(screen1);
//Screen 2
screen2 = new JPanel();
screen2.setBounds(100, 400, 600, 125);
screen2.setBackground(Color.white);
text2 = new JLabel("Text2");
screen2.add(text2);
window.add(screen2);
//Cover Panel
fadeScreen = new JPanel();
fadeScreen.setBounds(0,0,800,600);
fadeScreen.setBackground(Color.black);
window.add(fadeScreen);
window.setVisible(true);
//Comment out which method you don't want to use
fadeOut(this.fadeScreen);
//fadeIn(this.fadeScreen);
}
//Fade methods
int opacityCounter = 0;
public void fadeOut(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 0;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter++;
window.add(frame);
if(opacityCounter >= 255){
opacityCounter = 255;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
public void fadeIn(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 255;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter--;
window.add(frame);
if(opacityCounter <= 0){
opacityCounter = 0;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
public static void main(String[] args){
new Test();
}
}
Thanks in advance!
I would try these things:
Use the GlassPane of the top-level window and make a section of it darker where you want to cover things up, using a Swing Timer.
Use a CardLayout to swap the underlying components, and make the swap when the covering JPanel is darkest.
Then undarken the covering panel after the swap.
For example (to write more code explanation later):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Test2 extends JPanel {
public static final String PANEL_1 = "panel 1";
public static final String PANEL_2 = "panel 2";
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel();
private Action fadeAction = new FadeAction(cardPanel);
public Test2() {
JLabel label = new JLabel("Panel 1");
label.setFont(label.getFont().deriveFont(Font.BOLD, 100f));
panel1.setLayout(new GridBagLayout());
int gap = 40;
panel1.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
panel1.add(label);
panel1.setBackground(Color.PINK);
label = new JLabel("Panel 2");
label.setFont(label.getFont().deriveFont(Font.BOLD, 100f));
panel2.setLayout(new GridBagLayout());
panel2.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
panel2.add(label);
panel2.setBackground(new Color(131, 238, 255));
cardPanel.add(panel1, PANEL_1);
cardPanel.add(panel2, PANEL_2);
JButton startFadeBtn = new JButton(fadeAction);
JPanel buttonPanel = new JPanel();
buttonPanel.add(startFadeBtn);
setLayout(new BorderLayout(5, 5));
add(cardPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
private static class FadeAction extends AbstractAction {
private static final int FADE_DELAY = 20;
private static final int UNFADE_VALUE = 255;
private JPanel cardPanel;
private JComponent glassPane;
private JPanel coverPanel = new JPanel();
private Timer fadeTimer;
private int counter = 0;
private boolean fade = true;
public FadeAction(JPanel cardPanel) {
super("Start Fade");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
this.cardPanel = cardPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
counter = 0;
fade = true;
setEnabled(false);
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, PANEL_1);
Window topLevelWindow = SwingUtilities.getWindowAncestor(cardPanel);
glassPane = (JComponent) ((RootPaneContainer) topLevelWindow).getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(null);
coverPanel.setSize(cardPanel.getSize());
int x = cardPanel.getLocationOnScreen().x - glassPane.getLocationOnScreen().x;
int y = cardPanel.getLocationOnScreen().y - glassPane.getLocationOnScreen().y;
Point coverPanelPoint = new Point(x, y);
coverPanel.setLocation(coverPanelPoint);
glassPane.add(coverPanel);
fadeTimer = new Timer(FADE_DELAY, e2 -> fadeTimerActionPerformed(e2));
fadeTimer.start();
}
private void fadeTimerActionPerformed(ActionEvent e) {
coverPanel.setBackground(new Color(0, 0, 0, counter));
glassPane.repaint();
if (fade) {
counter++;
} else if (counter > 0) {
counter--;
} else {
glassPane.remove(coverPanel);
glassPane.setVisible(false);
setEnabled(true);
((Timer) e.getSource()).stop();
}
if (counter >= UNFADE_VALUE) {
fade = false;
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, PANEL_2);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Test2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
This is Hovercraft Full Of Eels' answer. All I did was clean up the GUI creation and demonstrate how this would work with more than two JPanels.
I created five JPanels and displayed them in order with the fade-out/fade-in effect.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class FadeEffectsTesting {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Fade Effects Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FadeEffectsTesting().getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
public static final String[] PANEL_SEQUENCE = { "Panel 1", "Panel 2", "Panel 3", "Panel 4",
"Panel 5" };
private int sequence = 0;
private CardLayout cardLayout;
private FadeAction action;
private JPanel cardPanel, mainPanel;
public FadeEffectsTesting() {
this.mainPanel = new JPanel(new BorderLayout(5, 5));
this.cardPanel = createCardPanel();
this.action = new FadeAction(cardPanel);
mainPanel.add(cardPanel, BorderLayout.CENTER);
mainPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
}
private JPanel createCardPanel() {
cardLayout = new CardLayout();
JPanel panel = new JPanel(cardLayout);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[0]),
PANEL_SEQUENCE[0]);
panel.add(createTextPanel(new Color(131, 238, 255),
PANEL_SEQUENCE[1]), PANEL_SEQUENCE[1]);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[2]),
PANEL_SEQUENCE[2]);
panel.add(createTextPanel(new Color(131, 238, 255),
PANEL_SEQUENCE[3]), PANEL_SEQUENCE[3]);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[4]),
PANEL_SEQUENCE[4]);
return panel;
}
private JPanel createTextPanel(Color color, String text) {
JPanel panel = new JPanel(new FlowLayout());
panel.setBackground(color);
int gap = 40;
panel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
JLabel label = new JLabel(text);
label.setFont(label.getFont().deriveFont(Font.BOLD, 72f));
panel.add(label);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
setFadeAction();
JButton startFadeBtn = new JButton(action);
panel.add(startFadeBtn);
return panel;
}
public void setFadeAction() {
action.setFromPanel(PANEL_SEQUENCE[sequence]);
action.setToPanel(PANEL_SEQUENCE[sequence + 1]);
}
public JPanel getMainPanel() {
return mainPanel;
}
public class FadeAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private static final int FADE_DELAY = 20;
private static final int UNFADE_VALUE = 255;
private JPanel cardPanel;
private JComponent glassPane;
private JPanel coverPanel;
private Timer fadeTimer;
private int alphaValue;
private boolean fadeOut;
private String fromPanel, toPanel;
public FadeAction(JPanel cardPanel) {
super("Start Fade");
this.putValue(MNEMONIC_KEY, KeyEvent.VK_S);
this.cardPanel = cardPanel;
this.alphaValue = 0;
this.fadeOut = true;
}
public void setFromPanel(String fromPanel) {
this.fromPanel = fromPanel;
}
public void setToPanel(String toPanel) {
this.toPanel = toPanel;
}
#Override
public void actionPerformed(ActionEvent event) {
alphaValue = 0;
fadeOut = true;
setEnabled(false);
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, fromPanel);
Window topLevelWindow = SwingUtilities.getWindowAncestor(cardPanel);
glassPane = (JComponent) ((RootPaneContainer) topLevelWindow).getRootPane()
.getGlassPane();
glassPane.setLayout(null);
coverPanel = new JPanel();
coverPanel.setSize(cardPanel.getSize());
glassPane.add(coverPanel);
glassPane.setVisible(true);
fadeTimer = new Timer(FADE_DELAY, e2 -> fadeTimerActionPerformed(e2));
fadeTimer.start();
}
private void fadeTimerActionPerformed(ActionEvent event) {
coverPanel.setBackground(new Color(0, 0, 0, alphaValue));
glassPane.repaint();
if (fadeOut) {
alphaValue += 3;
} else if (alphaValue > 0) {
alphaValue -= 3;
} else {
glassPane.remove(coverPanel);
glassPane.setVisible(false);
((Timer) event.getSource()).stop();
if (++sequence < (PANEL_SEQUENCE.length - 1)) {
setFadeAction();
setEnabled(true);
}
}
if (alphaValue >= UNFADE_VALUE) {
fadeOut = false;
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, toPanel);
}
}
}
}
Related
I am trying to understand implemented ActionListener. I couldn't find a way out to add it to JButtons in an othor method. I simply trying to add show and hide action to buttons but I could't. Any help? My code is here. There are 3 colored JPanel and every button should hide or show related color JPanel.
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class ShowHidePanels implements ActionListener {
public static void main(String[] args) {
new ShowHidePanels();
}
public ShowHidePanels() {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(1, 2));
frame.add(bluePanel());
frame.add(greenPanel());
frame.add(redPanel());
frame.add(buttonPanel());
frame.setSize(950, 600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static JPanel greenPanel() {
String greenTitle = "Green Panel";
Border greenBorder = BorderFactory.createTitledBorder(greenTitle);
JPanel greenPanel = new JPanel();
greenPanel.setBorder(greenBorder);
greenPanel.setBackground(new Color(165, 195, 70));
return greenPanel;
}
public static JPanel bluePanel() {
String blueTitle = "Blue Panel";
Border blueBorder = BorderFactory.createTitledBorder(blueTitle);
JPanel bluePanel = new JPanel();
bluePanel.setBorder(blueBorder);
bluePanel.setBackground(new Color(80, 105, 212));
return bluePanel;
}
public static JPanel redPanel() {
String redTitle = "Kirmizi Panel";
Border redBorder = BorderFactory.createTitledBorder(redTitle);
JPanel redPanel = new JPanel();
redPanel.setBorder(redBorder);
redPanel.setBackground(new Color(255, 100, 90));
return redPanel;
}
public static JPanel buttonPanel() {
Border greyBorder = BorderFactory.createTitledBorder("Grey Panel");
JButton b_BlueHide = new JButton("Hide Blue");
JButton b_BlueShow = new JButton("Show Blue");
JButton b_RedHide = new JButton("Hide Red");
JButton b_RedShow = new JButton("Show Red");
JButton b_GreenHide = new JButton("Hide Green");
JButton b_GreenShow = new JButton("Show Green");
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(greyBorder);
buttonPanel.setBackground(new Color(200, 200, 200));
buttonPanel.add(b_BlueHide);
buttonPanel.add(b_BlueShow);
buttonPanel.add(b_GreenHide);
buttonPanel.add(b_GreenShow);
buttonPanel.add(b_RedHide);
buttonPanel.add(b_RedShow);
return buttonPanel;
}
#Override
public void actionPerformed(ActionEvent event) {
}
}
static is not your friend. It has its place and purpose, but this is not one of them. Learn to live without it.
Instead, your methods and components should be instance based (that is, obviously, not static and reliant on a instance of the parent class).
The following example is slightly modified and makes use of a CardLayout to switch the panels, which is a lot more fun then trying to handle z-order issues ;)
Take a look at How to Use CardLayout
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 implements ActionListener {
private CardLayout cardLayout;
private JPanel contentPane;
public TestPane() {
cardLayout = new CardLayout();
setLayout(new BorderLayout());
contentPane = new JPanel(cardLayout);
contentPane.add(bluePanel(), "blue");
contentPane.add(greenPanel(), "green");
contentPane.add(redPanel(), "red");
add(contentPane);
add(buttonPanel(), BorderLayout.SOUTH);
}
public JPanel greenPanel() {
String greenTitle = "Green Panel";
Border greenBorder = BorderFactory.createTitledBorder(greenTitle);
JPanel greenPanel = new JPanel();
// Demonstration purposes only -----//
greenPanel.setPreferredSize(new Dimension(200, 200));
// ----- Demonstration purposes only //
greenPanel.setBorder(greenBorder);
greenPanel.setBackground(new Color(165, 195, 70));
return greenPanel;
}
public JPanel bluePanel() {
String blueTitle = "Blue Panel";
Border blueBorder = BorderFactory.createTitledBorder(blueTitle);
JPanel bluePanel = new JPanel();
// Demonstration purposes only -----//
bluePanel.setPreferredSize(new Dimension(200, 200));
// ----- Demonstration purposes only //
bluePanel.setBorder(blueBorder);
bluePanel.setBackground(new Color(80, 105, 212));
return bluePanel;
}
public JPanel redPanel() {
String redTitle = "Kirmizi Panel";
Border redBorder = BorderFactory.createTitledBorder(redTitle);
JPanel redPanel = new JPanel();
// Demonstration purposes only -----//
redPanel.setPreferredSize(new Dimension(200, 200));
// ----- Demonstration purposes only //
redPanel.setBorder(redBorder);
redPanel.setBackground(new Color(255, 100, 90));
return redPanel;
}
public JPanel buttonPanel() {
Border greyBorder = BorderFactory.createTitledBorder("Grey Panel");
JButton blue = new JButton("Blue");
JButton red = new JButton("Red");
JButton green = new JButton("Green");
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(greyBorder);
buttonPanel.setBackground(new Color(200, 200, 200));
buttonPanel.add(blue);
buttonPanel.add(green);
buttonPanel.add(red);
blue.addActionListener(this);
green.addActionListener(this);
red.addActionListener(this);
return buttonPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if ("blue".equalsIgnoreCase(cmd)) {
cardLayout.show(contentPane, "blue");
} else if ("red".equalsIgnoreCase(cmd)) {
cardLayout.show(contentPane, "red");
} else if ("green".equalsIgnoreCase(cmd)) {
cardLayout.show(contentPane, "green");
}
}
}
}
There's a lot of room for simplification and reduction of duplicate workflows, but I'll leave that for you to figure out ;)
I am trying to add and actionListener to a JPanel it's self but keep getting the error"cannot find symbol". I was just wondering if it is possible to do this as I want to be able to click on the panel and make the colour change. Any help would be appreciated.
Here is what i have so far.
import java.awt.*;
import javax.swing.*;
import javax.swing.JPanel.*;
import java.awt.Color.*;
import java.awt.event.*;
/**
* Write a description of class SimpleFrame here.
*
* #author OFJ2
* #version
*/
public class Game extends JFrame
implements ActionListener
{
private final int ROWS = 5;
private final int COLUMS = 2;
private final int GAP = 2;
private final int SIZE = ROWS * COLUMS;
private int x;
private JPanel leftPanel = new JPanel(new GridLayout(ROWS,COLUMS, GAP,GAP));
private JPanel [] gridPanel = new JPanel[SIZE];
private JPanel middlePanel = new JPanel();
private JPanel rightPanel = new JPanel();
private Color col1 = Color.GREEN;
private Color col2 = Color.YELLOW;
private Color tempColor;
public Game()
{
super("Chasing Bombs OFJ2");
setSize(200,200);
setVisible(true);
makeFrame();
}
public void makeFrame()
{
Container contentPane = getContentPane();
contentPane.setLayout(new GridLayout());
leftPanel.setLayout(new GridLayout(ROWS, COLUMS));
//JLabel label2 = new JLabel("Pocahontas");
JButton playButton = new JButton("Play Game");
JButton exitButton = new JButton("Exit");
JButton easyButton = new JButton("Easy");
JButton mediumButton = new JButton("Medium");
JButton hardButton = new JButton("Hard");
add(leftPanel);
add(middlePanel, new FlowLayout());
add(rightPanel);
setGrid();
middlePanel.add(playButton);
middlePanel.add(exitButton);
rightPanel.add(easyButton);
rightPanel.add(mediumButton);
rightPanel.add(hardButton);
leftPanel.setBackground(Color.PINK);
middlePanel.setBackground(Color.RED);
easyButton.addActionListener(this);
mediumButton.addActionListener(this);
hardButton.addActionListener(this);
playButton.addActionListener(this);
exitButton.addActionListener(this);
}
public void setGrid()
{
for(int x = 0; x < SIZE; x++) {
gridPanel[x] = new JPanel();
gridPanel[x].setBorder(BorderFactory.createLineBorder(Color.BLACK));
leftPanel.add(gridPanel[x]);
gridPanel[x].setBackground(Color.GREEN);
gridPanel[x].addActionListener(this);
}
}
#Override
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == gridPanel[0]){
gridPanel[x].setBackground(Color.BLACK);
}
}
}
I have tried to find if there is any other method that is needed to do this but cant find anything. Is it possible that I will have to add a button to fill each of the panels to make this work?
Thanks!
It defaults to no addActionListener, and the code below is a reference suggestion.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
class GPanel extends JPanel {
private List<ActionListener> listenerList = new ArrayList<>();
public GPanel() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
var event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "GPanel");
for (var i : listenerList) {
i.actionPerformed(event);
}
}
});
}
public void addActionListener(ActionListener listener) {
listenerList.add(listener);
}
}
public class ActionListenerTest extends JFrame {
public static void main(String[] args) {
new ActionListenerTest();
}
public ActionListenerTest() {
GPanel test = new GPanel();
test.setBackground(Color.BLUE);
add(test);
test.addActionListener(e-> {
System.out.println("Click: " + e.getActionCommand());
});
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
I've intended to create a simple gui that would draw an oval in the top third of the window, display a name in the middle third, and draw a rectangle in the bottom third(to be done later)
So far, the only parts I've been able to create and make visible are four buttons that are eventually meant to toggle the visibility of the objects and label.
The problem I'm having is that I cannot get the label or the oval to appear, and I'm not sure what I'm missing preventing either to be visble
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
public class Gui extends JFrame
implements ActionListener
{
private JButton bottomLeftButton;
private JButton bottomMiddleLeftButton;
private JButton bottomRightButton;
private JButton bottomMiddleRightButton;
private OtherPanel mypanel;
private JLabel name;
private JPanel panelOne;
private boolean visible;
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == bottomLeftButton)
{
visible = name.isVisible();
name.setVisible(visible);
}
else if(e.getSource() == bottomMiddleLeftButton)
{
}
else if (e.getSource() == bottomMiddleRightButton)
{
}
else if (e.getSource() == bottomRightButton)
{
}
repaint();
}
public Gui()
{
setTitle("First GUI");
setSize(800,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = this.getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel BottomPanel = new JPanel(new GridLayout(1,4));
contentPane.add(BottomPanel, BorderLayout.SOUTH);
bottomLeftButton = new JButton("Name");
bottomLeftButton.addActionListener(this);
BottomPanel.add(bottomLeftButton);
bottomMiddleLeftButton = new JButton("Oval");
bottomMiddleLeftButton.addActionListener(this);
BottomPanel.add(bottomMiddleLeftButton);
bottomMiddleRightButton = new JButton("Square");
bottomMiddleRightButton.addActionListener(this);
BottomPanel.add(bottomMiddleRightButton);
bottomRightButton = new JButton("Special");
bottomRightButton.addActionListener(this);
BottomPanel.add(bottomRightButton);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(3,1));
panelOne = new OtherPanel();
name = new JLabel("Name");
name.setHorizontalAlignment(SwingConstants.CENTER);
JLabel label3 = new JLabel("Label3");
centerPanel.add(panelOne);
centerPanel.add(name);
centerPanel.add(label3);
}
public static void main(String[] args)
{
Gui gui = new Gui();
gui.setVisible(true);
}
}
(meant to draw the oval)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OtherPanel extends JPanel
{
public void paintComponent(Graphics g)
{
int x = 10;
int y = 10;
int width = getWidth(); //ten pixels of spaces
int height = getHeight();
g.fillOval(x, y, width, height);
}
}
was missing a line of code to add the objects to the contentPane
contentPane.add(centerPanel); goes at the end of the gui() method
I am trying to have a dialog showing a progress bar with a label. I have set my label to be center aligned with JLabel.Center and the use of a box.
Initially, the label is shown as centered, which is what I am looking for. However, when changing the label's text (by using the code "creatingQueriesLabel.setText(text)", the label is now displayed as left aligned.
Any help will be greatly appreciated! Here is my code.
JFrame frame = new JFrame("Creating queries ...");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Box box = Box.createVerticalBox();
JPanel panel = new JPanel();
panel.setLayout(null);
creatingQueriesLabel = new JLabel("Initializing ... ");
creatingQueriesLabel.setSize(480, 160);
creatingQueriesLabel.setLocation(10, 10);
creatingQueriesLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
box.setLocation(0, 10);
box.setSize(480, 160);
box.add(creatingQueriesLabel);
progressBar = new JProgressBar();
progressBar.setSize(480, 50);
progressBar.setValue(0);
progressBar.setStringPainted(true);
progressBar.setLocation(creatingQueriesLabel.getX(),
creatingQueriesLabel.getY() + creatingQueriesLabel.getHeight());
panel.add(progressBar);
frame.add(box);
frame.add(panel);
// Display the window.
frame.pack();
frame.setSize(520, 280);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
/**
* Invoked when task's progress property changes.
*/
public void propertyChange(PropertyChangeEvent evt)
{
if ("progress" == evt.getPropertyName())
{
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
}
if ("currentQueryText" == evt.getPropertyName())
{
String text = (String) evt.getNewValue();
creatingQueriesLabel.setText(text);
}
}
Problems:
You're setting sizes and positions using absolute positioning -- don't as that's not how Swing works and this will lead to GUI's that are very hard to maintain and enhance, as you're finding out.
Use the SwingConstants.CENTER int when constructing the JLabel so that its text is centered
Add it to a container that uses BorderLayout, probably in the BorderLayout.PAGE_START position.
Unrelated problem -- don't do this: if ("currentQueryText" == evt.getPropertyName()) {. This tests for reference equality which is not what you want to test for. Use the equals method instead.
This GUI looks like it should be a dialog window, a temporary window that is displaying information not shown in the main parent window (the JFrame window), and so it should be displayed in a JDialog, not a JFrame.
For example:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class CreatingSpeciesPanel extends JPanel {
public static final String INITIALIZING = "Initializing...";
public static final String DONE = "DONE!";
private static final int PREF_W = 480;
private static final int PREF_H = 150;
private static final int GAP = 20;
private static final float TITLE_SIZE = 24f;
private JLabel title = new JLabel(INITIALIZING, SwingConstants.CENTER);
private JProgressBar progressBar = new JProgressBar();
public CreatingSpeciesPanel() {
title.setFont(title.getFont().deriveFont(Font.BOLD, TITLE_SIZE));
progressBar.setValue(0);
progressBar.setStringPainted(true);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(progressBar, BorderLayout.PAGE_END);
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
add(title, BorderLayout.PAGE_START);
add(centerPanel, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public void setValue(int value) {
progressBar.setValue(value);
}
public void setTitleLabelText(String text) {
title.setText(text);
}
private static void createAndShowGui() {
final CreatingSpeciesPanel creatingSpeciesPanel = new CreatingSpeciesPanel();
final JFrame mainFrame = new JFrame("Main Frame");
JButton createSpeciesBtn = new JButton(new AbstractAction("Create Species") {
#Override
public void actionPerformed(ActionEvent e) {
creatingSpeciesPanel.setTitleLabelText(CreatingSpeciesPanel.INITIALIZING);
final JDialog dialog = new JDialog(mainFrame, "Creating Species", ModalityType.APPLICATION_MODAL);
dialog.add(creatingSpeciesPanel);
dialog.pack();
dialog.setLocationRelativeTo(mainFrame);
new Timer(200, new ActionListener() {
private int doneCount = 0;
private int value = 0;
private static final int MAX_DONE_COUNT = 10;
#Override
public void actionPerformed(ActionEvent e) {
if (value < 100) {
value += (int) Math.random() * 5 + 5;
value = Math.min(100, value);
creatingSpeciesPanel.setValue(value);
if (value == 100) {
creatingSpeciesPanel.setTitleLabelText(CreatingSpeciesPanel.DONE);
}
} else {
// let's display the dialog for 2 more seconds
doneCount++;
if (doneCount >= MAX_DONE_COUNT) {
((Timer) e.getSource()).stop();
dialog.setVisible(false);
}
}
}
}).start();
dialog.setVisible(true);
}
});
JPanel panel = new JPanel();
panel.add(createSpeciesBtn);
panel.setPreferredSize(new Dimension(500, 400));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().add(panel);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have checked everwhere for a fix but nothing can work to make my checkbox appear. I added it to the panel and added the panel to the window. The button is appearing so it must be a problem with the checkbox. Here is my code:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainApplication {
public static Toolkit tk = Toolkit.getDefaultToolkit();
public static void main(String[] args) {
MainApplication instance = new MainApplication();
instance.start();
}
private JFrame window;
private JPanel mainPanel;
private JPanel contingencyPanel;
private JButton applyButton = new JButton("Apply Changes");
private JCheckBox autoRedLightBox = new JCheckBox("Red Light");
private JCheckBox autoYellowLightBox = new JCheckBox("Yellow Light");
private JCheckBox autoGreenLightBox = new JCheckBox("Green Light");
private JCheckBox autoBlueLightBox = new JCheckBox("Blue Light");
public void start() {
window = new JFrame("Main Control Window");
mainPanel = new JPanel();
contingencyPanel = new JPanel();
window.setSize(1280, 720);
window.setResizable(false);
window.setFocusable(true);
window.setFocusTraversalKeysEnabled(true);
int screenWidth = (int)tk.getScreenSize().getWidth();
int screenHeight = (int)tk.getScreenSize().getHeight();
window.setLocation((screenWidth/2)-(window.getWidth()/2), (screenHeight/2)-(window.getHeight()/2));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel.setLayout(null);
contingencyPanel.setLayout(null);
applyButton.setToolTipText("Changes will be applied to the arduino.");
applyButton.setSize(new Dimension(120, 30));
applyButton.setLocation(new Point((1280-120)-10, (720-56)-10));
autoRedLightBox.setSelected(true);
autoRedLightBox.setLocation(new Point(30, 30));
autoRedLightBox.setMnemonic(KeyEvent.VK_R);
mainPanel.add(applyButton);
mainPanel.add(autoRedLightBox, BorderLayout.CENTER);
window.add(mainPanel);
window.setVisible(true);
}
}
Desired Outcome:
That's well suited to a GridLayout.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ButtonsAndChecks {
private JComponent ui = null;
ButtonsAndChecks() {
initUI();
}
public void initUI() {
if (ui!=null) return;
// adjust last two numbers to need..
ui = new JPanel(new GridLayout(0,5,20,20));
ui.setBorder(new EmptyBorder(4,4,4,4));
// adjust numbers to need..
for (int i=1; i<26; i++) {
ui.add(new JButton("Button " + i));
}
// adjust numbers to need..
for (int i=1; i<26; i++) {
ui.add(new JCheckBox("Check " + i, i%2==0));
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ButtonsAndChecks o = new ButtonsAndChecks();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Read a bit about LayoutManagers in Swing. Every panel needs a layout to hold components, if you don't specify layout for JPanel it uses default one (FlowLayout).
The problem was in this line, when you set null for layout
mainPanel.setLayout(null);
just comment it and you will see buttons on form.
Also, for putting your form in center of screen you can call this method
window.setLocationRelativeTo(null);