KeyListener not working with JPanel - java

I am trying to make a menu class for a small game I'm making, and it all works fine, except now, the KeyListener does not work at all, I tried applying it to JFrame and JPanel, but nothing is working...
Here is my MainClass:
package bombermangame;
import javax.swing.JFrame;
public class MainClass {
public static int WIDTH = 870, HEIGHT = 800;
public static JFrame frame = new JFrame();
public static Menu menu = new Menu();
public static void main(String[] args) {
frame.setContentPane(menu);
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("BomberMan V0.3");
frame.setSize(WIDTH, HEIGHT);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
`
And here is my Menu class:
package bombermangame;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Menu extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private JButton startButton = new JButton("Play");
private int x = 0, y = 500;
private boolean down = false;
private boolean up = true;
private Timer timer = new Timer();
public Menu() {
setBackground(Color.blue);
startButton = new JButton("Start");
startButton.setBounds(0,0, 100, 40);
startButton.setPreferredSize(new Dimension(100, 40));
startButton.addActionListener(this);
startButton.setFocusPainted(true);
add(startButton);
}
public void actionPerformed(ActionEvent ae) {
Object a = ae.getSource();
Game game = new Game();
Listener keys = new Listener();
if (a == startButton) {
timer.cancel();
MainClass.frame.remove(MainClass.menu);
MainClass.frame.setContentPane(game);
MainClass.frame.addKeyListener(keys);
game.addKeyListener(keys);
game.setBackground(Color.BLACK);
game.setDoubleBuffered(true);
game.setBounds(0, 0, WIDTH, HEIGHT);
Game.running = true;
}
}
}

Related

how do i stop my jframe randomizer from just shaking

i created a program that makes a cube randomly move but how do i stop it from just shaking and actually make it move?
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.random.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class AIcivilication{
private static final JPanel island = new JPanel();
private static final JPanel character = new JPanel();
here`import java.awt.Color;
#SuppressWarnings("null")
public static void area(){
int y = 120;
int x = 100;
JFrame frame = new JFrame();
KeyEvent e = null;
movementthinking();
frame.setTitle("civilication");
frame.getContentPane().setLayout(null);
frame.setVisible(true);
frame.setSize(2000,700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.green);
character.setBackground(Color.BLACK);
character.setBounds(x, y, 50, 50);
frame.add(character);
}
public static void movementthinking() {
JFrame frame = new JFrame();
Timer timer = new Timer(5/120,new MyActionListener());
timer.start();
frame.setVisible(true);
}
public static class MyActionListener implements ActionListener{
public void actionPerformed(ActionEvent arg0) {
Random r = new Random();
int de = r.nextInt(3);
int y =350;
int x = 750;
if(de == 0) {
character.setLocation(x, y+=10);
}
if(de == 1) {
character.setLocation(x, y-=10);
}
if(de == 2) {
character.setLocation(x+=10, y);
}
if(de == 3) {
character.setLocation(x-=10, y);
}}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
area();
}
});
}
}
it picks number from 0 - 3 then go to a random direction but it looks like a shaking cube. how do i stop it from shaking like that and move to diffrent directions with the correct animations?

Problem with Java GridLayout and adding Buttons

I want to add 100 buttons into an GridLayout and my code works but sometimes it only adds one button and if I click where the other buttons belong the button where I clicked appears.
it happens totally randomly and I don't get it.
Here is my code:
public class GamePanel extends JPanel {
GameUI controler;
GridLayout gameLayout = new GridLayout(10,10);
JButton gameButtons[] = new JButton[100];
ImageIcon ice;
JButton startButton;
JButton exitButton;
ImageIcon startIcon;
ImageIcon exitIcon;
URL urlIcon;
private int i;
public GamePanel(GameUI controler) {
this.setLayout(gameLayout);
this.controler = controler;
urlIcon = this.getClass().getResource("/icons/Overlay.png");
ice = new ImageIcon(urlIcon);
makeButtons();
}
#Override
public void paint(Graphics g) {
super.paint(g);
}
public void makeButtons() {
for(i = 0; i< 100; i++) {
gameButtons[i] = new JButton(ice);
this.add(gameButtons[i]);
revalidate();
}
repaint();
}
}
update:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.net.URL;
public class GameUI extends JFrame {
ImageIcon i;
Image jFrameBackground;
JButton startButton;
JButton exitButton;
ImageIcon startIcon;
ImageIcon exitIcon;
public GameUI() {
setResizable(false);
this.setSize(1200, 800);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
BackGroundPanel backGroundPanel = new BackGroundPanel();
GamePanel panel = new GamePanel(this);
ButtonPanel buttonPanel = new ButtonPanel();
panel.setSize(500,500);
panel.setLocation(100, 150);
backGroundPanel.setSize(this.getWidth(),this.getHeight());
backGroundPanel.setLocation(0,0);
buttonPanel.setSize(390,50);
buttonPanel.setLocation(100,100);
this.add(backGroundPanel);
this.add(panel);
this.add(buttonPanel);
backGroundPanel.setBackground(Color.BLACK);
}
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
javax.swing.SwingUtilities.invokeAndWait(
new Runnable(){
#Override
public void run() {
GameUI ui = new GameUI();
ui.setVisible(true);
}
}
);
}
}
As I mentioned in comments, you're using a null layout, and this is the source of your problems.
You're using the null layout to try to layer JPanels, one on top of the other, and that is not how it should be used or what it is for, nor how you should create backgrounds. This is having the effect of the background covering your buttons until your mouse hovers over them.
Instead if you wish to create a background image, I would recommend that you:
create a JPanel, say called BackgroundPanel,
override its paintComponent method,
call its super.paintComponent(g); on your method's first line
then draw the image it should display
then give it a decent layout manager
and add your GUI components to it
Make sure that any JPanels added to it are made transparent via .setOpaque(false)
Other options include using a JLayeredPane, but you really don't need this just to have a background.
For example, the following code produces:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class GameUI2 {
private static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/3/3f/"
+ "Butterfly_Nebula_in_narrow_band_Sulfur%2C_Hydrogen_and_Oxygen_Stephan_Hamel.jpg";
private static final String BTN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/5/54/Crystal_Project_Games_kids.png";
private static void createAndShowGui() {
BufferedImage bgImg = null;
BufferedImage btnImg = null;
try {
URL bgImgUrl = new URL(IMG_PATH);
URL btnImgUrl = new URL(BTN_IMG_PATH);
bgImg = ImageIO.read(bgImgUrl);
btnImg = ImageIO.read(btnImgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
BackgroundPanel2 mainPanel = new BackgroundPanel2(bgImg);
mainPanel.setLayout(new GridBagLayout());
GamePanel2 gamePanel = new GamePanel2(btnImg);
mainPanel.add(gamePanel);
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class BackgroundPanel2 extends JPanel {
private Image backgroundImg;
public BackgroundPanel2(Image backgroundImg) {
this.backgroundImg = backgroundImg;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || backgroundImg == null) {
return super.getPreferredSize();
} else {
int w = backgroundImg.getWidth(this);
int h = backgroundImg.getHeight(this);
return new Dimension(w, h);
}
}
}
#SuppressWarnings("serial")
class GamePanel2 extends JPanel {
public static final int MAX_BUTTONS = 100;
private static final int IMG_WIDTH = 40;
JButton[] gameButtons = new JButton[MAX_BUTTONS];
public GamePanel2(Image buttonImg) {
setOpaque(false);
if (buttonImg.getWidth(this) > IMG_WIDTH) {
buttonImg = buttonImg.getScaledInstance(IMG_WIDTH, IMG_WIDTH, Image.SCALE_SMOOTH);
}
Icon icon = new ImageIcon(buttonImg);
setLayout(new GridLayout(10, 10, 4, 4));
for (int i = 0; i < gameButtons.length; i++) {
int finalIndex = i;
JButton btn = new JButton(icon);
btn.addActionListener(e -> {
String text = String.format("Button: %02d", finalIndex);
System.out.println(text);
});
add(btn);
gameButtons[i] = btn;
}
}
}

Timer is trying to convert to String

Can someone please tell me why the Timer is trying to Convert an int into a String. Here is the error that keeps coming up.
CurrentTimePrinter.java:48: error: incompatible types: int cannot be
converted to String
time = new Timer(1000,listener);
CurrentTimePrinter.java:49: error: cannot find symbol
time.start();
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.Date;
import java.util.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.BorderLayout;
public class CurrentTimePrinter extends JFrame
{
private JButton Exitbutton;
private JTextField textField;
private static final int FIELD_WIDTH = 10;
private static final int FRAME_WIDTH = 600;
private static final int FRAME_HEIGHT = 400;
private ActionListener listener;
public Timer time;
public CurrentTimePrinter()
{
//listener = new CtpListener();
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public void createComponents()
{
Color orange = new Color(255,165,0);
Font font = new Font("Times New Roman", Font.BOLD, 14);
textField = new JTextField(FIELD_WIDTH);
Exitbutton = new JButton("EXIT");
class CtpListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
textField.setText("" + new Date());
Date now = new Date();
System.out.println(now);
}
}
ActionListener listener = new CtpListener();
time = new Timer(1000,listener);
time.start();
Exitbutton.setFont(font);
Exitbutton.setForeground(Color.BLACK);
ExitButtonListener exitListener = new ExitButtonListener();
Exitbutton.addActionListener(exitListener);
JPanel panel1 = new JPanel();
time = new Timer(1000, listener);
time.start();
JPanel panel2 = new JPanel();
panel1.setBackground(orange);
panel1.add(Exitbutton);
panel2.add(textField);
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.add(panel1, BorderLayout.SOUTH);
contentPane.add(panel2, BorderLayout.CENTER);
setContentPane(contentPane);
}
class ExitButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.exit(0);
}
}
public static void main(String[] args)
{
JFrame frame = new CurrentTimePrinter();
frame.setTitle("Current Time");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
You are using java.util.Timer. You want javax.swing.Timer here.
Replace that in the imports, it should be:
import javax.swing.Timer;

How to implement JScrollPane child behavior?

It is said in manual, that if child does not implement Scrollable, then JScrollPane rely on preferredSize properties of it's content.
Apparently this is not true for me. I am increasing preferred height, but JScrollPane does not feel or react on it.
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Try01_JScrollPane extends JFrame {
private static final long serialVersionUID = 4123186105171813186L;
private static final Logger log = LoggerFactory.getLogger(Try01_JScrollPane.class);
JPanel yellowPanel = new JPanel();
{
yellowPanel.setPreferredSize(new Dimension(200,50));
yellowPanel.setSize(new Dimension(200,50));
yellowPanel.setBackground(Color.yellow);
}
JScrollPane scrollPane = new JScrollPane(yellowPanel);
{
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
}
AbstractAction increaseAction = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
yellowPanel.setPreferredSize(new Dimension(yellowPanel.getPreferredSize().width, yellowPanel.getPreferredSize().height+100));
log.debug("preferred height is now {}", yellowPanel.getPreferredSize().height);
}
};
Timer increaseTimer = new Timer(1000, increaseAction);
{
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200, 400);
setTitle("Try01_JScrollPane");
increaseTimer.start();
setVisible(true);
}
public static void main(String[] args) {
new Try01_JScrollPane();
}
}
JPanel is container and JComponent too, for any changes to JViewport you have to notify the JScrollPane:-)
.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Try01_JScrollPane extends JFrame {
private static final long serialVersionUID = 4123186105171813186L;
private JFrame frame = new JFrame("Try01_JScrollPane");
private JPanel yellowPanel = new JPanel();
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
{
yellowPanel.setBackground(Color.yellow);
}
private JScrollPane scrollPane = new JScrollPane(yellowPanel);
{
scrollPane.setPreferredSize(new Dimension(400, 300));
}
private AbstractAction increaseAction = new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
yellowPanel.setPreferredSize(
new Dimension(yellowPanel.getPreferredSize().width + 100,
yellowPanel.getPreferredSize().height + 100));
yellowPanel.revalidate();
yellowPanel.repaint();
}
};
private Timer increaseTimer = new Timer(1000, increaseAction);
public Try01_JScrollPane() {
frame.add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
increaseTimer.start();
increaseTimer.setRepeats(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Try01_JScrollPane();
}
});
}
}
The JScrollPane cuts a view port out of a backing content have a scroll pane layout. The part on getPreferredSize refers to this layout. It simply says that the JScrollPane / view port rectangle is not influenced by the backing content and vice versa: content is layed out with respect to their preferred size.
So a change of preferred size need a new layouting. More sence would be to:
initialize with a setPreferredSize.
afterwards call setSize to resize.

need assistance with GUIs and java swing

This is my program below and I am trying to figure out where my main method should be. I have seen a few examples of it being implemented at the very end of the program but there main is different from mine.
Main method (to be implemented):
public class JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Components File");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
My Program
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Lab_10 extends JFrame
{
private final double EARTHQUAKE_RATE= 8.0;
private final int FRAME_WIDTH= 300;
private final int FRAME_HEIGHT= 200;
private JLabel rLabel;
private JTextField eField;
private JButton button;
private JLabel earthLabel;
public Lab_10()
{
JLabel earthLabel = new JLabel("Most structures fall");
makeTextField();
makeButton();
makePanel();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void makeTextField()
{
JLabel rLabel = new JLabel("Richter");
final int FIELD_WIDTH = 10;
eField = new JTextField(FIELD_WIDTH);
eField.setText("" + EARTHQUAKE_RATE);
}
class AddLabelListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
earthLabel.setText("Most structures fall");
}
}
private void makeButton()
{
JButton button = new JButton("Enter");
ActionListener listener = new AddLabelListener();
button.addActionListener(listener);
}
private void makePanel()
{
JPanel panel = new JPanel();
panel.add(rLabel);
panel.add(eField);
panel.add(button);
panel.add(earthLabel);
add(panel);
}
}
Updated Code (which is compiling but and running but with logic errors because it implements an empty frame [guess as much from the main method I have]):
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Lab_10 extends JFrame
{
private final double EARTHQUAKE_RATE= 8.0;
private final int FRAME_WIDTH= 300;
private final int FRAME_HEIGHT= 200;
private JLabel rLabel;
private JTextField eField;
private JButton button;
private JLabel earthLabel;
public Lab_10()
{
JLabel earthLabel = new JLabel("Most structures fall");
makeTextField();
makeButton();
makePanel();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void makeTextField()
{
JLabel rLabel = new JLabel("Richter");
final int FIELD_WIDTH = 10;
eField = new JTextField(FIELD_WIDTH);
eField.setText("" + EARTHQUAKE_RATE);
}
class AddLabelListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
earthLabel.setText("Most structures fall");
}
}
private void makeButton()
{
JButton button = new JButton("Enter");
ActionListener listener = new AddLabelListener();
button.addActionListener(listener);
}
private void makePanel()
{
JPanel panel = new JPanel();
panel.add(rLabel);
panel.add(eField);
panel.add(button);
panel.add(earthLabel);
add(panel);
}
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
#Override
public void run()
{ JFrame frame = new JFrame();
frame.setTitle("Components File");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
Your 'main' probably looks different because you are not using SwingUtilities.invokeLater(Runnable doRun) ?
Well, to put it simply, you must use it always. So, modify your code and use this:
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
// copy-paste your main() code
}
});
Also, why is your class named JFrame ? Refrain from using names that are already used by Java classes already.

Categories

Resources