Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I want to clean up my code and I was wondering if I could put these JLabels into an ArrayList.
This is going to be used for a do-while loop in which the collisions of my player will be checked.
Below is the GamePane class. This code has the moving player in it and has the code for the collisions. This is where I create the ArrayList:
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This class Holds the game pane that has the moving player. It also contains
* the GamePane
*
* #author 602052004
*
*/
public class GamePane extends JPanel implements ActionListener, KeyListener {// *change GamePane to GamePane
// This is were the game screen is made and the player is created.
private static final long serialVersionUID = 1L;
JLabel player = new JLabel();
JLabel finish = new JLabel();
// This is were the JLabels for the walls are created
//JLabel wall1 = new JLabel();
//ArrayList<JLabel> array = new ArrayList<>();
ArrayList<JLabel> array = new ArrayList<>();
array.add(wall1);
JLabel wall1 = new JLabel();
JLabel wall2 = new JLabel();
JLabel wall3 = new JLabel();
JLabel wall4 = new JLabel();
JLabel wall5 = new JLabel();
JLabel wall6 = new JLabel();
JLabel wall7 = new JLabel();
JLabel wall8 = new JLabel();
JLabel wall9 = new JLabel();
JLabel wall10 = new JLabel();
JLabel wall11 = new JLabel();
JLabel wall12 = new JLabel();
JLabel wall13 = new JLabel();
JLabel wall14 = new JLabel();
JLabel wall15 = new JLabel();
JLabel wall16 = new JLabel();
JLabel wall17 = new JLabel();
JLabel wall18 = new JLabel();
JLabel wall19 = new JLabel();
JLabel wall20 = new JLabel();
JLabel wall21 = new JLabel();
JLabel wall22 = new JLabel();
JLabel wall23 = new JLabel();
JLabel wall24 = new JLabel();
int playerSpeed = 5;
int FPS = 40;
private final Set<Integer> keys = new HashSet<>();
// The keys set holds the keys being pressed
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Create a new object and
// run its go() method
new GamePane().go();
}
});
}
GamePane() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
}
/**
* The frame that shows my game. It contains the game frame which holds my
* JPanel GameStage and ButtonPane.
*/
protected void go() {
setLayout(new CardLayout());
// Setup the window
JFrame GameFrame = new JFrame();
// Add this panel to the window
GameFrame.setLayout(new CardLayout());
GameFrame.add(this, "main");
GameFrame.setContentPane(this);
// Set's the window properties
GameFrame.setTitle("main");
GameFrame.setSize(800, 600);
GameFrame.setLocationRelativeTo(null);
GameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameFrame.setVisible(true);
GameFrame.add(new ButtonPane(GameFrame), "buttons");
// Creates the new JPanel that will hold the game.
JPanel gamestage = new JPanel();
gamestage.setBackground(Color.darkGray);
GameFrame.add(gamestage, "game");
gamestage.setLayout(null);
// *Move the setup of the player and the timer under the walls
// Get a sample of collisions going so that i can do it over the weekend
// Setup the movable box
player.setBounds(25, 25, 20, 20);
player.setVisible(true);
player.setBackground(Color.cyan);
// Opaque makes the background visible
player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
gamestage.add(player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
wall1.setBounds(10, 15, 10, 480);
wall1.setVisible(true);
wall1.setBackground(Color.white);
wall1.setOpaque(true);
gamestage.add(wall1);
wall2.setBounds(10, 10, 755, 10);
wall2.setVisible(true);
wall2.setBackground(Color.white);
wall2.setOpaque(true);
gamestage.add(wall2);
// wall3.setBounds(x, y, width, height);
wall3.setBounds(10, 100, 100, 10);
wall3.setVisible(true);
wall3.setBackground(Color.white);
wall3.setOpaque(true);
gamestage.add(wall3);
wall4.setBounds(100, 60, 10, 40);
wall4.setVisible(true);
wall4.setBackground(Color.white);
wall4.setOpaque(true);
gamestage.add(wall4);
wall5.setBounds(70, 60, 35, 10);
wall5.setVisible(true);
wall5.setBackground(Color.white);
wall5.setOpaque(true);
gamestage.add(wall5);
wall6.setBounds(60, 100, 10, 90);
wall6.setVisible(true);
wall6.setBackground(Color.white);
wall6.setOpaque(true);
gamestage.add(wall6);
wall7.setBounds(10, 230, 60, 10);
wall7.setVisible(true);
wall7.setBackground(Color.white);
wall7.setOpaque(true);
gamestage.add(wall7);
wall8.setBounds(60, 230, 10, 65);
wall8.setVisible(true);
wall8.setBackground(Color.white);
wall8.setOpaque(true);
gamestage.add(wall8);
wall9.setBounds(60, 290, 125, 10);
wall9.setVisible(true);
wall9.setBackground(Color.white);
wall9.setOpaque(true);
gamestage.add(wall9);
wall10.setBounds(175, 300, 10, 45);
wall10.setVisible(true);
wall10.setBackground(Color.white);
wall10.setOpaque(true);
gamestage.add(wall10);
wall11.setBounds(130, 335, 45, 10);
wall11.setVisible(true);
wall11.setBackground(Color.white);
wall11.setOpaque(true);
gamestage.add(wall11);
wall12.setBounds(10, 335, 70, 10);
wall12.setVisible(true);
wall12.setBackground(Color.white);
wall12.setOpaque(true);
gamestage.add(wall12);
wall13.setBounds(10, 435, 60, 10);
wall13.setVisible(true);
wall13.setBackground(Color.white);
wall13.setOpaque(true);
gamestage.add(wall13);
wall14.setBounds(10, 385, 230, 10);
wall14.setVisible(true);
wall14.setBackground(Color.white);
wall14.setOpaque(true);
gamestage.add(wall14);
wall15.setBounds(60, 390, 10, 50);
wall15.setVisible(true);
wall15.setBackground(Color.white);
wall15.setOpaque(true);
gamestage.add(wall15);
wall16.setBounds(230, 290, 10, 155);
wall16.setVisible(true);
wall16.setBackground(Color.white);
wall16.setOpaque(true);
gamestage.add(wall16);
wall17.setBounds(10, 485, 750, 10);
wall17.setVisible(true);
wall17.setBackground(Color.white);
wall17.setOpaque(true);
gamestage.add(wall17);
wall18.setBounds(70, 180, 60, 10);
wall18.setVisible(true);
wall18.setBackground(Color.white);
wall18.setOpaque(true);
gamestage.add(wall18);
wall19.setBounds(120, 180, 10, 55);
wall19.setVisible(true);
wall19.setBackground(Color.white);
wall19.setOpaque(true);
gamestage.add(wall19);
}
public boolean areColliding(JLabel a, JLabel b) {
return a.getBounds().intersects(b.getBounds());
}
/**
* this method makes the player move. It takes the players speed and subtracts
* or adds the player speed to the current position of the player. It also
* figures out were the player is at currently aswell.
*
* #param arg0
*/
#Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
player.setLocation(player.getX(), player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
player.setLocation(player.getX() + playerSpeed, player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
player.setLocation(player.getX(), player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
player.setLocation(player.getX() - playerSpeed, player.getY());
}
// Check for collisions
if (areColliding(wall1, player)) {
// Reposition the target
int newX = (int) (25);
int newY = (int) (25);
player.setLocation(newX, newY);
}else
// Check for collisions
if (areColliding(wall2, player)) {
// Reposition the target
int newX = (int) (25);
int newY = (int) (25);
player.setLocation(newX, newY);
}else
// Check for collisions
if (areColliding(wall3, player)) {
// Reposition the target
int newX = (int) (25);
int newY = (int) (25);
player.setLocation(newX, newY);
}
}
#Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
#Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
#Override
public void keyTyped(KeyEvent e) {
}
}
Below is the ButtonPane class. It controls the screen switching. The two screens that switch are the GamePane and the ButtonPane. The GamePane contains the walls and all the code to run the game. The ButtonPane class is as follows:
/**
* This pane contains the button and sets up the button pane
*/
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonPane extends JPanel {
private JButton startBTN;// Calls the JButton
JFrame game;
public ButtonPane(JFrame g) {
game = g;
setLayout(new GridBagLayout());
setBackground(Color.gray);// Sets the menu stages color blue
startBTN = new JButton("Start");// Creates a new button
add(startBTN);// Adds the button on the startStage
startBTN.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (game.getContentPane().getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getParent().getLayout();
layout.show(game.getContentPane(), "game");
}
}
});
}
}
You could initialize an ArrayList with JLabels in a for-loop like this:
ArrayList<JLabel> array = new ArrayList<>();
for (int i = 0, i < numberOfLabels, i++)
{
array.add(new JLabel());
}
To retrieve an element from the ArrayList, just use:
array.get(elementIndex);
If you want to put already created JLabels into an ArrayList, you can do:
array.add(labelObject);
for each JLabel object you want in the ArrayList.
You can use ArrayList to store your JLabel
But you will have struggle when add an already-exist JLabel to your arraylist (because, when you got it back you don't know which index to access).
The better way to keep track of your JLabel is to create a map, you often need to specify text for your JLabel so you can use it to identify your JLabel:
Map<String, JLabel> map = new HashMap<>();
map.put(your-label-name, new JLabel(your-label-name));
If you know your label is going to duplicated, then add prefix to your JLabel key.
Related
I only learn Java Swing 1 week so I tried complete some exercises. This is my code. I set 9 icon to 9 button but it doesn't show on button.
package mypack;
import java.awt.Color;
import javax.swing.*;
public class PuzzleGame extends JFrame{
static JButton bt1,bt2,bt3,bt4,bt5,bt6,bt7,bt8,bt9,btNew,btExit;
static JLabel move, moveNum, time, timeNum;
public PuzzleGame(){
createMyGUI();
}
public static void createMyGUI(){
JFrame jf = new JFrame("Game Puzzle Java");
JPanel jpl = new JPanel();
Icon icSpace = new ImageIcon("images/0.png");
Icon ic1 = new ImageIcon("images/1.png");
Icon ic2 = new ImageIcon("images/2.png");
Icon ic3 = new ImageIcon("images/3.png");
Icon ic4 = new ImageIcon("images/4.png");
Icon ic5 = new ImageIcon("images/5.png");
Icon ic6 = new ImageIcon("images/6.png");
Icon ic7 = new ImageIcon("images/7.png");
Icon ic8 = new ImageIcon("images/8.png");
jpl.setSize(100,100);
jpl.setBounds(480, 50, 200, 200);
jpl.setBackground(Color.BLUE);
move = new JLabel("Move:");
move.setBounds(480,10,50,20);
moveNum = new JLabel("0");
moveNum.setBounds(530, 10, 50, 20);
time = new JLabel("Time:");
time.setBounds(580, 10, 50, 20);
timeNum = new JLabel("0");
timeNum.setBounds(630,10,50,20);
btNew = new JButton("New Game");
btNew.setBounds(480, 270, 200, 80);
btExit = new JButton("Exit");
btExit.setBounds(480, 370, 200, 80);
jf.add(move);
jf.add(moveNum);
jf.add(time);
jf.add(timeNum);
jf.add(btNew);
jf.add(btExit);
jf.add(jpl);
jf.setSize(700, 500);
jf.setLocation(300,20);
jf.setLayout(null);
jf.setResizable(false);
jf.setVisible(true);
bt1 = new JButton();
bt1.setBounds(10, 10, 150, 150);
bt1.setIcon(ic1);
bt2 = new JButton();
bt2.setBounds(160, 10, 150, 150);
bt2.setIcon(ic2);
bt3 = new JButton();
bt3.setBounds(310, 10, 150, 150);
bt3.setIcon(ic3);
bt4 = new JButton();
bt4.setBounds(10, 160, 150, 150);
bt4.setIcon(ic4);
bt5 = new JButton();
bt5.setBounds(160, 160, 150, 150);
bt5.setIcon(ic5);
bt6 = new JButton();
bt6.setBounds(310, 160, 150, 150);
bt6.setIcon(ic6);
bt7 = new JButton();
bt7.setBounds(10, 310, 150, 150);
bt7.setIcon(ic7);
bt8 = new JButton();
bt8.setBounds(160, 310, 150, 150);
bt8.setIcon(ic8);
bt9 = new JButton();
bt9.setBounds(310, 310, 150, 150);
bt9.setIcon(icSpace);
jf.add(bt1);
jf.add(bt2);
jf.add(bt3);
jf.add(bt4);
jf.add(bt5);
jf.add(bt6);
jf.add(bt7);
jf.add(bt8);
jf.add(bt9);
}
public static void main(String[] args){
PuzzleGame.createMyGUI();
}
}
I think method setIcon is not apply for Button. Besides, someone show me how to set a action to arrange mess picture into a complete picture in Puzzle Game with my code.
I see some issues in your code:
You're extending JFrame and creating a new JFrame object inside your class. You're never using the JFrame of your class (the extended one). So it's wise to just remove it.
You should avoid extending JFrame because that means that your class is a JFrame, JFrame is a rigid container, instead make your programs based on JPanels and add them to other Containers. For reference see: Using extends JFrame vs calling it inside of class.
You're over using the static keyword. static is not a cross method passing word, it will harm you a lot, stop using it. Instead create instances of your class and call your methods that way.
You have multiple objects that do the same:
Icon ic1 = new ImageIcon("images/1.png");
Icon ic2 = new ImageIcon("images/2.png");
...
Why not have an Icon[] icons and iterate over it?
You're using the evil null layout and setBounds(...), stop using it and instead make use of the layout managers along with EmptyBorders for extra spacing between components.
While pixel perfect positioning might be like the easiest way to Swing newbies to create complex GUIs, the more you use it, the more problems you'll find regarding this. Swing has to deal with different platforms, screen sizes, resolutions, PLAFs, etc. That's why pixel perfect GUIs are just an illusion. For reference see Null layout is evil and the answers in this question for a further explanation on why you should avoid null layout.
You're making your JFrame visible before you have added all your components, this could cause your GUI to not be painted fully before it's shown and could cause a "bug" that the components don't display until you hover where they should be. JFrame#setVisible(...) should be one of the last lines to be called.
You're calling JFrame#setSize(...), you should instead override the getPreferredSize of your inner JPanels and then call JFrame#pack(), so your JFrame reduces its size to the minimum size where all your components are visible on their preferred sizes. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Java Swing? (The general consensus says "yes").
You're not placing your program on the Event Dispatch Thread (EDT), Swing is not Thread safe and this could make your program to freeze sometimes, you can solve this by changing your main(...) method like this one:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Your constructor here
}
});
}
Your images probably aren't located, but they'll become embedded resources once you package your program as a JAR file, and thus, it's wise to start treating the files (or images) as if they already were.
You can change for example:
Icon ic1 = new ImageIcon("images/1.png");
To this:
Icon ic1 = null;
try {
ic1 = new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/1.png")));
} catch (IOException e) {
e.printStackTrace();
}
That will make your image to be loaded. See this question and the accepted answer for reference.
That should solve your question, and your GUI (I did it with 2 icons) shoudl look like this one:
But if you want to follow my above recommendations you could try this code, which uses layout managers, empty borders, overrides getPreferredSize() methods and uses pack(), etc and generates a really similar GUI like the one you already have:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImagesInResourcesExample {
private JFrame frame;
private JPanel buttonsPane;
private JPanel rightPane;
private JPanel scorePanel;
private JPanel colorPanel;
private BufferedImage img;
private JButton[][] buttons;
private JLabel moveLabel;
private JLabel timeLabel;
private JButton newGameButton;
private JButton exitButton;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ImagesInResourcesExample().createAndShowGui();
}
});
}
#SuppressWarnings("serial")
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
buttons = new JButton[3][3];
moveLabel = new JLabel("Move: 0");
timeLabel = new JLabel("Time: 0");
colorPanel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
colorPanel.setBackground(Color.BLUE);
colorPanel.setOpaque(true);
newGameButton = new JButton("New Game");
exitButton = new JButton("Exit");
try {
img = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/arrow.png"));
} catch (IOException e) {
e.printStackTrace();
}
buttonsPane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
buttonsPane.setLayout(new GridLayout(3, 3));
buttonsPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons.length; j++) {
buttons[i][j] = new JButton(new ImageIcon(img));
buttonsPane.add(buttons[i][j]);
}
}
rightPane = new JPanel();
rightPane.setLayout(new GridBagLayout());
scorePanel = new JPanel();
scorePanel.setLayout(new GridLayout(1, 2, 10, 10));
scorePanel.add(moveLabel);
scorePanel.add(timeLabel);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(10, 10, 10, 10);
rightPane.add(scorePanel, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
rightPane.add(colorPanel, gbc);
gbc.gridy = 2;
gbc.ipadx = 30;
gbc.ipady = 80;
rightPane.add(newGameButton, gbc);
gbc.gridy = 3;
rightPane.add(exitButton, gbc);
rightPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.add(buttonsPane, BorderLayout.CENTER);
frame.add(rightPane, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
As you can see, the code is at most 20 lines longer than the one you already have, but if you keep adding elements to both programs, the one I did will, in a future, be shorter than the one you'll end up by using null layout.
I hope you follow the above recommendations and take this example and try to understand it and improve it.
The idea behind the code is a simple multiplying game where it generates 2 numbers and I have to input the corret answer.
Basically, my question(s) is(are):
When I do operacao.setOpaque(false); it does nothing, or at least not what I'd expect it to do (http://puu.sh/pyVcE/813aa1843a.png - shouldn't the grey area be pink, since the background is pink?). Same happens with JLabels, the setOpaque(false) leaves a grey background behind the (in this case) numbers.
I have that last commented section because I saw someone around here saying to alter the paint method, and it did work, but caused some weird issues (painted over everything when I started the console, only the JTextField would be clear), and then I "fixed" it with the setOpacity(1); setBackground(pink); - is this a proper way of doing it?
public class Frame extends JFrame {
private JPanel panel, mensagem, operacao;
private JTextArea sucesso;
private JLabel numero1, numero2;
private JTextField resposta;
private Color pink = new Color(255, 213, 224);
//more vars
public Frame() {
super("Jogo de Multiplicar!");
setOpacity(1);
setBackground(pink);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(300, 200);
panel = new JPanel();
mensagem = new JPanel();
operacao = new JPanel();
mensagem.setLayout(new FlowLayout(FlowLayout.CENTER));
operacao.setLayout(new FlowLayout(FlowLayout.CENTER));
sucesso = new JTextArea();
sucesso.setEditable(false);
sucesso.setOpaque(false);
sucesso.setFont(minhaFont2);
Random randomGen = new Random();
while (random1 == 0)
random1 = randomGen.nextInt(10);
while (random2 == 0)
random2 = randomGen.nextInt(10);
res = random1 * random2;
numero1 = new JLabel();
numero2 = new JLabel();
numero1.setText(random1 + " *");
numero2.setText(random2 + " =");
numero1.setOpaque(false);
numero1.setFont(minhaFont);
numero2.setFont(minhaFont);
resposta = new JTextField(2);
resposta.addActionListener(new MinhaAcao());
resposta.setFont(minhaFont);
operacao.add(numero1);
operacao.add(numero2);
operacao.add(resposta);
mensagem.add(sucesso);
operacao.setOpaque(true);
operacao.setBackground(pink);
mensagem.setOpaque(true);
mensagem.setBackground(pink);
//add(panel, BorderLayout.NORTH);
add(operacao);
add(mensagem, BorderLayout.SOUTH);
}/*
public void paint(Graphics g) {
g.setColor(pink);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}*/
You need to textfield to be pink. You may have to do this.
resposta.setOpaque(false);
I have refactored your code like below.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Frame extends JFrame {
private JPanel panel, mensagem, operacao;
private JTextArea sucesso;
private JLabel numero1, numero2;
private JTextField resposta;
private Color pink = new Color(255, 213, 224);
//more vars
public Frame() {
super("Jogo de Multiplicar!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setSize(300, 200);
getContentPane().setBackground(pink);
panel = new TransperantPanel();
mensagem = new TransperantPanel();
operacao = new TransperantPanel();
mensagem.setLayout(new FlowLayout(FlowLayout.CENTER));
operacao.setLayout(new FlowLayout(FlowLayout.CENTER));
sucesso = new JTextArea();
sucesso.setEditable(false);
Random randomGen = new Random();
int random1 =0 , random2 = 0;
while (random1 == 0)
random1 = randomGen.nextInt(10);
while (random2 == 0)
random2 = randomGen.nextInt(10);
int res = random1 * random2;
numero1 = new JLabel();
numero2 = new JLabel();
numero1.setText(random1 + " *");
numero2.setText(random2 + " =");
resposta = new JTextField(2);
resposta.setOpaque(false);
resposta.addActionListener(new MinhaAcao());
numero1.setFont(minhaFont);
numero2.setFont(minhaFont);
resposta.setFont(minhaFont);
operacao.add(numero1);
operacao.add(numero2);
operacao.add(resposta);
mensagem.add(sucesso);
add(operacao);
add(mensagem, BorderLayout.SOUTH);
}
public static void main(String[] args){
Frame f = new Frame();
f.setVisible(true);
}
class TransperantPanel extends JPanel {
public TransperantPanel() {
setOpaque(false);
}
}
}
What i have done is
Setting background to contentPane of the frame.
Created a transparent panel(setting Opaque of the panel to false).
Setting JTextfield's Opaque to false.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a java swing project that looks like this:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.Box;
import javax.swing.BoxLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class DiceGameReplaceDice extends JFrame
{
private JFrame gameFrame;
private JPanel mainPanel;
private JPanel centerPanel = new JPanel();
private JButton diceArray[];
private DiceListener diceListener = new DiceListener();
private ButtonListener buttonListener = new ButtonListener();
private Random rand = new Random();
private int NUM_DICE = 2;
private String diceImages[] = {"./src/1.png", "./src/2.png", "./src/3.png",
"./src/4.png", "./src/5.png", "./src/6.png"};
public static void main(String[] args)
{
new DiceGameReplaceDice();
}
public DiceGameReplaceDice()
{
// Initialize the frame that holds the game
gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setLocation(300, 100);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add Panel
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
// Instantiate a ButtonListener
buttonListener = new ButtonListener();
// Add 1 Button and 1 Label to a newly created panel
// Add new panel to West
JButton buttonW1 = new JButton("Add Die");
buttonW1.setName("W1");
buttonW1.addActionListener(buttonListener);
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest,BoxLayout.Y_AXIS ));
panelWest.setBackground(new Color(0, 0, 122)); // set to blue
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
mainPanel.add(panelWest, BorderLayout.WEST);
// Create and display center panel with dice
displayCenterPanel();
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void displayCenterPanel()
{
centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel,BoxLayout.X_AXIS ));
centerPanel.setBackground(new Color(0, 122, 0)); // set to green
centerPanel.add(Box.createHorizontalGlue());
diceArray = new JButton[NUM_DICE];
// Add 2 Buttons to center panel with images of 2 random dice
for (int i=0; i<NUM_DICE; i++)
{
// Create dice button
int dieNum = rand.nextInt(6)+1;
diceArray[i] = new JButton(new ImageIcon(diceImages[dieNum-1]));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(diceListener);
// Add to center panel
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
mainPanel.add(centerPanel, BorderLayout.CENTER);
// Add mainPanel to frame and display the frame
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
// Implement an (inner) class that implements ActionListener
class DiceListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
NUM_DICE -= 1;
displayCenterPanel();
}
}
// Implement an (inner) class that implements ActionListener
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String button = ((JButton)e.getSource()).getName();
System.out.println("Button Pressed: " + button);
if (button.equals("W1"))
NUM_DICE ++;
System.out.println(NUM_DICE);
displayCenterPanel();
}
}
}
When Clicking the "Add Die" button, a die is added to the screen and is correctly formatted. However, when a die is pressed, and the NUM_DICE is decreased, clicking on the die button results in weird overlaps and "ghost buttons". How do you fix this?
The quick fix would be to remove the centerPanel prior to adding the new one. Add the line
mainPanel.remove(centerPanel);
as the first thing you do inside displayCenterPanel.
However, your way of manipulating the layout dynamically leaves a lot to be desired. Instead of creating a new panel each time, just modify the existing one:
public class DiceGame {
private JPanel centerPanel = new JPanel();
private Random rand = new Random();
private int numDice = 2;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new DiceGame());
}
public DiceGame() {
JFrame gameFrame = new JFrame();
gameFrame.setSize(800, 600);
gameFrame.setTitle("Dice Game");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JButton buttonW1 = new JButton("Add Die");
buttonW1.addActionListener(e -> {
numDice++;
updateCenterPanel();
});
JPanel panelWest = new JPanel();
panelWest.setLayout(new BoxLayout(panelWest, BoxLayout.Y_AXIS));
panelWest.setBackground(new Color(0, 0, 122));
panelWest.add(Box.createVerticalGlue());
panelWest.add(buttonW1);
panelWest.add(Box.createVerticalGlue());
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
centerPanel.setBackground(new Color(0, 122, 0));
mainPanel.add(panelWest, BorderLayout.WEST);
mainPanel.add(centerPanel);
gameFrame.add(mainPanel);
gameFrame.setVisible(true);
}
private void updateCenterPanel() {
centerPanel.removeAll();
centerPanel.add(Box.createHorizontalGlue());
JButton[] diceArray = new JButton[numDice];
for (int i = 0; i < numDice; i++) {
diceArray[i] = new JButton(Integer.toString(rand.nextInt(6) + 1));
diceArray[i].setName("Dice" + i);
diceArray[i].addActionListener(e -> {
numDice--;
updateCenterPanel();
});
centerPanel.add(diceArray[i]);
centerPanel.add(Box.createHorizontalGlue());
}
centerPanel.revalidate();
centerPanel.repaint();
}
}
Revalidating and repainting is necessary after invalidating the component hierarchy.
Notes:
Don't create fields when local variables will do.
NUM_DICE is not final, so it should be named numDice.
Calling gameFrame.setVisible(true); when it is already visible does nothing.
When you have a working version of whatever it is you are doing, replace setSize(...) on the JFrame with pack and be sure to calculate the size of its children properly.
I'm completely new to Layout Managers, but i want to create a table. I have a window that is set.Resizable(false) and doesn't have a layout manager, with 1 image and two text items placed using coordinates. I would like to keep these items using absolute layout, while creating my table underneath (using GridLayout I assume)
If it helps, here is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Canvas;
import javax.swing.JFrame;
import java.awt.Dimension;
class DisplayItems extends JFrame implements ActionListener
{
//text
private static JLabel TechforTeachingTitle;
private static JLabel TechforTeachingSubTitle;
//images
private static JLabel Logo;
//buttons
private static final int BUTTON_WIDTH = 100;
private static final int BUTTON_HEIGHT = 30;
public static void main(String[] args)
{
DisplayItems ProjectFrame = new DisplayItems();
ProjectFrame.setVisible(true); // Display the frame
}
public DisplayItems( )
{
//font properties
Font TitleFont = new Font("Serif", Font.BOLD, 80);
Font subFont = new Font("Serif", Font.BOLD, 40);
// set the frame properties
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Inventory system");
setSize(900, 700);
setLocationRelativeTo(null);
setResizable(false);
// set the content pane properties
Container contentPane = getContentPane();
contentPane.setLayout(null);
contentPane.setBackground(Color.decode("#FDF3E7"));
//set text properties
TechforTeachingTitle = new JLabel();
TechforTeachingTitle.setText("Tech For Teaching");
TechforTeachingTitle.setBounds(200, 30, 900, 95);
TechforTeachingTitle.setForeground(Color.decode("#8f8f8f"));
TechforTeachingTitle.setFont(TitleFont);
contentPane.add(TechforTeachingTitle);
TechforTeachingSubTitle = new JLabel();
TechforTeachingSubTitle.setText("View items");
TechforTeachingSubTitle.setBounds(400, 90, 900, 95); //left, top, length, height
TechforTeachingSubTitle.setForeground(Color.decode("#799177")); //7E8F7C (slightly less green)
TechforTeachingSubTitle.setFont(subFont);
contentPane.add(TechforTeachingSubTitle);
//set image properties
Logo = new JLabel(new ImageIcon("SmallLogo.png"));
Logo.setBounds(10,20,179,178); // //left, top, width, height
contentPane.add(Logo);
Logo.setVisible(true);
// Logo.addMouseListener(new MouseAdapter()
// {
// public void mouseClicked(MouseEvent e) {
// setVisible(false);
//
// FinalProject FP = new FinalProject();
// FP.setVisible(true);
// }
// });
//set button properties
}
public void actionPerformed(ActionEvent event) // Actions
{
}
}
I am trying to access JTextField text namely 'searchBox' from outer action listener created in outer class.
GUI:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MyFrame extends JFrame
{
public int stat1_var;
public int stat2_var;
public int stat3_var;
public String stat4_var;
private int statX_bound = 50;
private int statY_bound = 280;
public String url;
/*
* #param width The width of the frame.
* #param height The height of the frame.
* #param title The title of the frame.
*/
public MyFrame(int width, int height, String title, int stat1_var, int stat2_var, int stat3_var, String stat4_var)
{
this.stat1_var = stat1_var; //threading var
this.stat2_var = stat2_var; //spiders var
this.stat3_var = stat3_var; //results var
this.stat4_var = stat4_var; //other var
initUI(width, height, stat1_var, stat2_var, stat3_var, stat4_var);
this.setSize(width,height); //set frame size
this.setTitle(title); //set frame title
this.setVisible(true); //set visible
this.setResizable(false); //disable resizable frame
}
private void initUI(int width, int height, int stat1_var, int stat2_var, int stat3_var, String stat4_var)
{
ImageIcon ic = new ImageIcon("background.jpg");//background image source
JDesktopPane dp = new JDesktopPane(); //create desktop pane
JLabel lbl = new JLabel(ic); //create label
JPanel transparentPanel = new JPanel(); //create a JPanel
lbl.setBounds(0, 0, width, height); //bounds for the background
transparentPanel.setOpaque(false);
transparentPanel.setBounds(0, 0, width, height);//bounds for the panel
transparentPanel.setLayout(null);//default layout
setLayeredPane(dp);
JTextField searchBox = new JTextField("http://", 40); //keyword search box
searchBox.setEditable(true);
searchBox.setBounds(250, 130, 300, 25);
searchBox.setToolTipText("Enter domain to be crawled");
transparentPanel.add(searchBox);
searchBox.setActionCommand("url");
searchBox.addActionListener(new listeners(this));
JButton crawlBtn = new JButton("Crawl"); // search button
crawlBtn.addActionListener(new listeners(this));
crawlBtn.setBounds(555, 130, 80, 25);
crawlBtn.setActionCommand("crawl");
crawlBtn.setToolTipText("crawl domain");
transparentPanel.add(crawlBtn);//end
JTextField searchBox2 = new JTextField("", 40); //crawl url search box
searchBox2.setEditable(true);
searchBox2.setBounds(250, 160, 300, 25);
searchBox2.setToolTipText("enter your keywords");
transparentPanel.add(searchBox2); //end
JButton jumpBtn = new JButton("Jump!"); // search button
jumpBtn.addActionListener(new listeners(this));
jumpBtn.setBounds(555, 160, 80, 25);
jumpBtn.setActionCommand("crawl");
jumpBtn.setToolTipText("crawl domain");
transparentPanel.add(jumpBtn);//end
JLabel stat1 = new JLabel("Threads: " + stat1_var); //stat labels
stat1.setToolTipText("Threads");
stat1.setBounds(statX_bound, statY_bound, 300, 25);
statY_bound += 25; //place the label one place below
transparentPanel.add(stat1);
JLabel stat2 = new JLabel("Spiders: " + stat2_var); //stat labels
stat2.setToolTipText("Spiders");
stat2.setBounds(statX_bound, statY_bound, 300, 25);
statY_bound += 25; //place the label one place below
transparentPanel.add(stat2);
JLabel stat3 = new JLabel("Results found: " + stat3_var);
stat3.setToolTipText("Results found");
stat3.setBounds(statX_bound, statY_bound, 300, 25);
statY_bound += 25; //place the label one place below
transparentPanel.add(stat3);
JLabel stat4 = new JLabel("Status: " + stat4_var);
stat4.setToolTipText("Status");
stat4.setBounds(statX_bound, statY_bound, 300, 25);
statY_bound += 25; //place the label one place below
transparentPanel.add(stat4);
dp.add(lbl,new Integer(50));
dp.add(transparentPanel,new Integer(350));
setDefaultCloseOperation(EXIT_ON_CLOSE); //close the app if close button clicked
} //end constructor
public void paint(Graphics g)
{
super.paint(g); //call superclass' paint method
g.setColor(Color.BLACK);
} //end method paint
} //end class MyFrame
And this is the outer class listener:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.File;
public class listeners implements ActionListener
{
private MyFrame myframe;
public listeners(MyFrame myframe){
this.myframe = myframe;
//String source = e.getSource();
}
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
if (action == "url")
{
myframe.url = searchBox.getText(); //<----- I am trying to obtain this from the gui
}
}
}
I am trying to obtain the searchBox text value(arrows above) to the url variable from GUI class. Can anyone please help me with this? I have been looking for the solution for 3 hours now...
Use getSource to obtain a reference to the JTextField
JTextField searchBox = (JTextField) e.getSource();
Declare your JTextField variable as instance var. (outside of initUI method) and create getter method. Then call it in your listeners class:
myframe.url = myframe.getSearchBox().getText();;
Other sidenotes:
Name your classes properly. Names of classes begin with upper cases.
Do not extend your class with JFrame if you are not going to override some methods or to define new methods.
DON'T use absolute positioning for swing components! Use proper layout manager.