Component won't display unless window is resized - Java - java

I have problem with image visibility after click the button. I have the main class with frame:
package superworld;
import java.awt.*;
import javax.swing.*;
public class SuperWorld {
public static void main(String[] args) {
JFrame frame= new JFrame();
frame.setSize(1050,650);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SuperPanel());
frame.setVisible(true);
// frame.setResizable(false);
}
}
Then I have class with Panel with all components:
package superworld;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.Timer;
public class SuperPanel extends JPanel implements ActionListener{
Timer mainTimer;
public static final int HEIGHT = 550;
public static final int WIDTH = 1050;
int i;
int w=-100;
int h=-50;
ArrayList<SuperMiasto> miasta = new ArrayList<SuperMiasto>();
private JButton heroButton;
private JButton cywilButton;
public SuperPanel() {
mainTimer = new Timer(10,this);
heroButton = new HeroButton(this);
cywilButton = new CywilButton(this);
setLayout(null);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setBackground(Color.GREEN);
for(i=0;i<10;i++)
{
miasta.add( new SuperMiasto() );
miasta.get(i).x=w;
miasta.get(i).y=h;
miasta.get(i).imagelabel = new JLabel(miasta.get(i).image);
miasta.get(i).imagelabel.setBounds(miasta.get(i).x,miasta.get(i).y,miasta.get(i).image.getIconWidth(),miasta.get(i).image.getIconHeight());
add(miasta.get(i).imagelabel);
w=w+200;
if (w > WIDTH-200)
{
h=h+200;
w=-100;
}
}
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
add(heroButton);
add(cywilButton);
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
And Class with button with add new object with image:
package superworld;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class HeroButton extends JButton implements ActionListener {
private JPanel buttonPanel;
HeroButton(JPanel buttonPanel) {
super("Dodaj hero");
this.buttonPanel = buttonPanel;
setBounds(0,500,150,50);
addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
SuperLudzie batman = new SuperLudzie();
batman.imagelabel = new JLabel(batman.image);
batman.imagelabel.setBounds(50,50,batman.image.getIconWidth(),batman.image.getIconHeight());
buttonPanel.add(batman.imagelabel);
}
}
And class of this SuperLudzie:
package superworld;
import java.awt.*;
import javax.swing.*;
public class SuperLudzie {
private String imie;
private int zycie;
private int inteligencja;
private int wytrzymalosc;
private int sila;
private int umiejetnosci_walki;
private int x,y;
ImageIcon image = new ImageIcon("C:/Users/Zuzanna Sawala/Moje dokumenty/NetBeansProjects/SuperWorld/mysz.jpg");
JLabel imagelabel;
}
Everything work great. I have only problem with this object and image created by button it's not visible just after clicking but after i resize a window. I know that it have something to do with setVisibility(true); but i'm not sure where to use it.

Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Use overridden paintComponent() method instead of paint()
class SuperPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
}
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
}
Read more points...
Try to avoid null layout and use proper layout that suits as per our need.
Please have a look at How to Use Various Layout Managers that has sole responsibilities for positioning and sizing of the components.

Related

How to make the JFrame contentPane transparent but the JFrame visible?

I wanted to know how to make the JFrame's contentPane transparent but the JFrame visible. I saw many pages but all showed on how to make the JFrame border visible but the contentPane visible.
I tried using setOpacity() but that requires the JFrame to be undecorated.
Are there any methods that I can achieve this?
Swing was not designed to paint with transparent backgrounds. You cannot create a transparent contentPane. However, you can fake a transparent background.
Here's a screenshot showing a fake transparent background. I cropped and reduced the image by 50% to get it to display in this answer.
So, how did I do this?
I took a snapshot of the background and painted the background on the JPanel.
This only works if you do not change the background while you're displaying your JFrame. If you change the background by opening or closing any other applications, this fake will not work.
You can move the JFrame around. Do not move the JFrame close to the edge of the screen, or you'll ruin the illusion.
Iconifying and deiconifying the JFrame works, but the illusion becomes obvious.
You can resize, maximize, and restore the JFrame.
It requires a lot of code to make this fake work properly.
Here's the complete runnable code. I made all the additional classes inner classes so I could post this code as one block.
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TransparentJPanelView implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TransparentJPanelView());
}
private DrawingPanel drawingPanel;
private JFrame frame;
private TransparentJPanelModel model;
public TransparentJPanelView() {
this.model = new TransparentJPanelModel();
this.drawingPanel = new DrawingPanel(model);
}
#Override
public void run() {
this.frame = new JFrame("Fake Transparent JPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addComponentListener(new FrameComponentListener(this, model));
FrameListener listener = new FrameListener(this, model);
frame.addWindowListener(listener);
frame.addWindowFocusListener(listener);
frame.addWindowStateListener(listener);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void repaint() {
drawingPanel.repaint();
}
public JFrame getFrame() {
return frame;
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private TransparentJPanelModel model;
public DrawingPanel(TransparentJPanelModel model) {
this.model = model;
this.setLayout(new FlowLayout());
this.setPreferredSize(new Dimension(600, 300));
JButton button = new JButton("Click me");
this.add(button);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Point point = new Point(this.getLocation());
SwingUtilities.convertPointToScreen(point, this);
Image image = model.getSubImage(point.x, point.y, getWidth(), getHeight());
g.drawImage(image, 0, 0, this);
}
}
public class FrameComponentListener extends ComponentAdapter {
private final TransparentJPanelView view;
private final TransparentJPanelModel model;
public FrameComponentListener(TransparentJPanelView view,
TransparentJPanelModel model) {
this.view = view;
this.model = model;
}
#Override
public void componentResized(ComponentEvent event) {
view.repaint();
}
#Override
public void componentMoved(ComponentEvent event) {
view.repaint();
}
}
public class FrameListener extends WindowAdapter {
private final TransparentJPanelView view;
private final TransparentJPanelModel model;
public FrameListener(TransparentJPanelView view,
TransparentJPanelModel model) {
this.view = view;
this.model = model;
}
#Override
public void windowDeiconified(WindowEvent event) {
model.setBackground();
view.repaint();
}
}
public class TransparentJPanelModel {
private BufferedImage background;
private final Rectangle screenRect;
private final Robot robot;
public TransparentJPanelModel() {
this.robot = createRobot();
this.screenRect = new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize());
setBackground();
}
private Robot createRobot() {
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
return robot;
}
public void setBackground() {
this.background = robot.createScreenCapture(screenRect);
}
public Image getSubImage(int x, int y, int width, int height) {
if (x < 0) {
x = 0;
width = Math.min(width, screenRect.width);
}
if (y < 0) {
y = 0;
height = Math.min(height, screenRect.height);
}
if (x + width > screenRect.width) {
width = screenRect.width - x;
}
if (y + height > screenRect.height) {
height = screenRect.height - y;
}
return background.getSubimage(x, y, width, height);
}
}
}
You can use setVisible(false) method for each element that is inside that JFrame. You use this in the intialize() method. Once you want them to be shown (for example after some button is clicked) than you will use the same method setVisible(true).

How can I pass an argument to paintComponent in order to call it in a different class?

In my main class I have the following code to load an image from my machine and display it on the frame to draw things on it:
public class ShowMap extends JPanel {
private static final int WIDTH = 1340;
private static final int HEIGHT = 613;
public void main(String args[]) {
JFrame frame = new JFrame("MAP");
frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
frame.setMinimumSize(new Dimension(WIDTH, HEIGHT));
frame.setMaximumSize(new Dimension(WIDTH, HEIGHT));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = (JPanel)frame.getContentPane();
JLabel label = new JLabel();
label.setIcon(new ImageIcon("map.png"));
panel.add(label);
}
}
The image I am loading is a map where I would like to indicate the position of some objects by drawing points in the right coordinates. So it is important here to dictate to the DrawPoint class (below) what coordinates should get the point.
Also, I would greatly appreciate an explanation of how to erase a point that has been drawn.
My search led me to the following, but as soon as I add int coordx, int coordy to the arguments of the method, it is no more highlighted, and I don't know how to call this method in ShowMap while passing the coordinates as arguments.
public class DrawPoint extends JPanel {
private int coordx;
private int coordy;
public void paintComponent(Graphics g, int coordx, int coordy){
g.setColor(Color.BLACK);
g.fillOval(coordx,coordy,8,8);
}
}
Here is a demonstration of what MadProgrammer wrote in his comment : "should be changing a state variable of the component and then calling repaint" :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SwingTest extends JFrame {
private static final int SIZE = 300;
private DrawPoint drawPoint;
public SwingTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
drawPoint = new DrawPoint();
drawPoint.setPreferredSize(new Dimension(SIZE, SIZE));
add(drawPoint);
pack();
setVisible(true);
}
//demonstrate change in DrawPoint state
private void reDraw() {
Random rnd = new Random();
Timer timer = new Timer(1000, e -> { //periodically change coordinates and repaint
drawPoint.setCoordx(rnd.nextInt(SIZE));
drawPoint.setCoordy(rnd.nextInt(SIZE));
drawPoint.repaint();
});
timer.start();
}
public static void main(String[] args){
SwingUtilities.invokeLater(() -> new SwingTest().reDraw());
}
}
class DrawPoint extends JPanel {
private int coordx, coordy;
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(coordx,coordy,8,8);
}
//use setters to change the state
void setCoordy(int coordy) { this.coordy = coordy; }
void setCoordx(int coordx) {this.coordx = coordx;}
}

Clicking a button within a JFrame passes an data to a JPanel

I have a Jframe with two buttons: '1' and '2'. Clicking the button '1' should display the capital letter A in the JPanel.
Code fore my JFrame:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawFrame extends JFrame{
private final int WIDTH = 500;
private final int HEIGHT = 300;
private JButton number1;
private JButton number2;
private JPanel numberPanel;
private DrawPanel graphicsPanel;
public DrawFrame()
{
createSelectionPanel();
createGraphicsPanel();
this.setSize(WIDTH, HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void createSelectionPanel()
{
numberPanel = new JPanel();
number1 = new JButton("1");
number2 = new JButton("2");
numberPanel.setLayout(new GridLayout(2,2));
numberPanel.add(number1);
numberPanel.add(number2);
this.add(numberPanel, BorderLayout.WEST);
}
private void createGraphicsPanel()
{
//instantiate drawing panel
graphicsPanel = new DrawPanel();
//add drawing panel to right
add(graphicsPanel);
}
private class Number1ButtonListener implements ActionListener {
public void actionPerformed (ActionEvent event) {
Number number = new Number();
number.setNumber('A');
}
}
//creates a drawing frame
public static void main(String[] args)
{
DrawFrame draw = new DrawFrame();
}
}
Code for my JPanel
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class DrawPanel extends JPanel{
public Coordinates current;
public DrawPanel(){
//nothing drawn initially
current = null;
//set white background for drawing panel
setBackground(Color.WHITE);
//add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
public void paint(Graphics g){
super.paint(g);
if(current!=null){
I want to replace "A" with number.getNumber()
g.drawString("A", current.getX(), current.getY());
}
}
//class to handle all mouse events
private class MouseHandler extends MouseAdapter implements MouseMotionListener
{
public void mousePressed(MouseEvent event)
{
current = new Coordinates(event.getX(), event.getY());
}
public void mouseReleased(MouseEvent event)
{
repaint();
}
}
}
I'm not sure if this is possible. So sorry if I am mistaken in my logic. Please provide an alternate way for me to approach this problem. Appreciate any guidance.
Thanks!
The Coordinates and Number classes weren't included, so I had to modify the code somewhat.
Here's the GUI I created.
The first thing I did was create a model class for the GUI. By creating a model class, I could make the display string and the drawing coordinate available to the view and the controller classes. This is a simple example of the model / view / controller pattern.
package com.ggl.drawing;
import java.awt.Point;
public class GUIModel {
private String displayString;
private Point coordinate;
public GUIModel(String displayString) {
this.displayString = displayString;
}
public Point getCoordinate() {
return coordinate;
}
public void setCoordinate(int x, int y) {
this.coordinate = new Point(x, y);
}
public void setCoordinate(Point coordinate) {
this.coordinate = coordinate;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
public String getDisplayString() {
return displayString;
}
}
Now that we have a model, lets look at the DrawFrame class.
package com.ggl.drawing;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawFrame implements Runnable {
private final int WIDTH = 500;
private final int HEIGHT = 300;
private JFrame frame;
private GUIModel model;
public DrawFrame() {
this.model = new GUIModel("A");
}
#Override
public void run() {
frame = new JFrame("Draw Letters");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createSelectionPanel(), BorderLayout.WEST);
frame.add(new DrawPanel(WIDTH, HEIGHT, model), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel createSelectionPanel() {
JPanel numberPanel = new JPanel();
ButtonListener listener = new ButtonListener();
JButton number1 = new JButton("A");
number1.addActionListener(listener);
JButton number2 = new JButton("B");
number2.addActionListener(listener);
numberPanel.setLayout(new GridLayout(0, 2));
numberPanel.add(number1);
numberPanel.add(number2);
return numberPanel;
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
model.setDisplayString(event.getActionCommand());
}
}
// creates a drawing frame
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawFrame());
}
}
I started the Java Swing application on the Event Dispatch thread with the call to the SwingUtilities invokeLater method.
I separated the JFrame construction from the 2 JPanels construction. I used a JFrame, rather than extend a JFrame. The only time you should extend any Java class is if you want to override one or more of the class methods.
I used the same ButtonListener for both JButtons. I'm guessing what you want, but I drew either an "A" or a "B", depending on which button you left clicked.
Let's look at the DrawPanel class.
package com.ggl.drawing;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
private static final long serialVersionUID = 3443814601865936618L;
private GUIModel model;
public DrawPanel(int width, int height, GUIModel model) {
this.setPreferredSize(new Dimension(width, height));
this.model = model;
// add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (model.getCoordinate() != null) {
Point p = model.getCoordinate();
Font font = g.getFont().deriveFont(48F);
g.setFont(font);
g.drawString(model.getDisplayString(), p.x, p.y);
}
}
// class to handle all mouse events
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent event) {
model.setCoordinate(event.getPoint());
}
#Override
public void mouseReleased(MouseEvent event) {
DrawPanel.this.repaint();
}
}
}
The major change I made in this class was to use the paintComponent method, rather than the paint method. The paintComponent method is the correct method to override.
I set the size of the drawing panel in the DrawPanel constructor. It's much better to let Swing figure out the size of the JFrame. That's what the pack method in the DrawFrame run method does.
I increased the font size so you can see the drawn letter better.
I removed the mouse motion listener code, as it wasn't needed.
I hope this was helpful to you.
OK, all I know so far is that you want the text displayed in a JPanel to change if a button is pressed. If so, then your code looks to be way too complex for the job. Suggestions include:
Give the DrawingPanel a setter method, say, setText(String text), that allows outside classes to change the text that it displays.
Within that method, set a field of DrawingPanel, say called text, and call repaint().
Override DrawingPanel's paintComponent not its paint method, and call the super's method within your override.
Within the paintComponent method, call drawString to draw the String held by the text field, if the field is not null.
Give your buttons ActionListeners or AbstractActions that call the DrawingPanel's setText(...) method, setting the text to be displayed.
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class DrawAorB extends JPanel {
private DrawingPanel drawingPanel = new DrawingPanel();
public DrawAorB() {
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
btnPanel.add(new JButton(new ButtonAction("A")));
btnPanel.add(new JButton(new ButtonAction("B")));
setLayout(new BorderLayout());
add(drawingPanel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = e.getActionCommand();
drawingPanel.setText(text);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DrawAorB");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawAorB());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class DrawingPanel extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private String text = null;
public void setText(String text) {
this.text = text; // set the JPanel's text
repaint(); // and draw it
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (text != null) {
int x = getWidth() / 2;
int y = getHeight() / 2;
// use FontMetrics if you want to center text better
g.drawString(text, x, y);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
Even simpler, easier, and probably better would be to display the text within a JLabel as it's much easier to center this text.

Move a BALL on Jpanel with keyboard down key

I have a class mypanel extends from jpanel where i use the graphics and make a ball. Second class is Main where i make a JFrame and add panel to frame. There is another class MKeyListener in Main which extends from KeyAdapter class where i handel the keyboard event. I have made a object of Jpanel class in Main class and register the MkeyListener class with the jpanel class. now i want to move down the ball on jpanel with down keyboard key butt ball is not moving down with down key that is code of my programe.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class mypanel extends JPanel{
int n=0;
int m=0;
int i=170;
int j=340;
int a=60;
int b=20;
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2= (Graphics2D)g;
g2.setColor(Color.green);
g2.fillOval(n,m,10,10);
}
}
public class Main {
JFrame frame;
mypanel p;
int x,y;
public Main (){
x=0;
y=0;
frame=new JFrame();
Container c = frame.getContentPane();
c.setLayout(new BorderLayout());
p = new mypanel();
c.add(p,BorderLayout.CENTER);
frame.setSize(400,400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MKeyListener k=new MKeyListener();
p.addKeyListener(k);
}
public static void main(String args []) {
Main a= new Main();
}
class MKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.VK_DOWN ) {
x =x+4;
y=y+4;
p.n+=x;
p.m+=y;
p.repaint();
System.out.println("success");
}
}
}
}
KeyListener is is picky, the component it is registered to must have focus AND be focuable before it will trigger key events. It can also be overridden by any other focusable component, which can be a good and bad thing.
It's generally recommended to use the key bindings API instead, which gives you control over the focus level required to trigger events. It's also generally far more flexible in it's configuration and re-usability
See How to Use Key Bindings for more details
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String args[]) {
Main a = new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MyPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyPanel extends JPanel {
private int n = 0;
private int m = 0;
private int i = 170;
private int j = 340;
private int a = 60;
private int b = 20;
public MyPanel() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Action.down");
am.put("Action.down", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
n += 4;
m += 4;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.green);
g2.fillOval(n, m, 10, 10);
}
}
}
As a general piece of advice, it's generally a bad idea to expose fields of you object as public or package-private, you lose control over there management, meaning that they could be modified from any where with out your knowledge or control.
Better to self contain the management of these values (either internally or through the use of getters) or via a model-controller paradigm

How to switch between JPanels in my JFrame

I don't know why this does not work. I have implemented an ItemListener to check if the continue button is clicked on on the SplashScreen to then switch to the MainMenu panel. When I run the code, I get the first panel with the background image and button and then when I click the button nothing happens.
Here is my Window class
package edu.ycp.cs.Main;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Window implements ItemListener{
private static final long serialVersionUID = 1L;
JPanel cards; // a panel that uses CardLayout
final static String SPLASHSCREEN = "SplashScreen";
final static String MAINMENU = "MainMenu";
public void addComponentToWindow(Container pane) {
// Put the JComboBox in a JPanel to get a nicer look.
JPanel gameWindow = new JPanel(); // use FlowLayout
// Create the "cards".
JPanel card1 = new JPanel();
JButton continueButton = new JButton("Continue");
continueButton.addItemListener(this);
card1.add(new SplashScreen());
card1.add(continueButton);
JPanel card2 = new JPanel();
card2.add(new MainMenuScreen());
cards = new JPanel(new CardLayout());
cards.add(card1, SPLASHSCREEN);
cards.add(card2, MAINMENU);
pane.add(gameWindow, BorderLayout.PAGE_START);
pane.add(cards, BorderLayout.CENTER);
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, (String) evt.getItem());
}
}
Here is my splashscreen code
the MainMenu code is exactly the same with a different image file
package edu.ycp.cs.Main;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
class SplashScreen extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage background;
public SplashScreen() {
try {
background = ImageIO.read(new File("Logo.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth());
int y = (getHeight() - background.getHeight());
g.drawImage(background, x, y, this);
}
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(Color.white);
g2d.drawString("Please wait...", getWidth() / 2, getHeight() * 3 / 4);
}
}
and here is my Main
package edu.ycp.cs.Main;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
makeGUI();
}
});
}
private static void makeGUI() {
// Create and set up the window.
JFrame frame = new JFrame("M&M Arcade");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
Window window = new Window();
window.addComponentToWindow(frame.getContentPane());
// Display the window.
frame.pack();
frame.setVisible(true);
}
}
An ItemListener will have no effect when you click on the continue JButton. Use an ActionListener instead:
continueButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, MAINMENU);
}
});
Consider also using CardLayout#next for navigation.

Categories