How to switch between JPanels in my JFrame - java

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.

Related

When button clicked, replace entire window content with an image

SOLVED
So I have an issue where when I click the button, I want an image to replace the entire content of the window. But it's only replacing, what I believe to be, a part of a panel. Should I not use panels in this instance? I found some code online which didn't use panels which worked, but maybe there is a scenario where I can remove the panel and just cover the entire frame with my image when the button is clicked?
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class SatNav extends JFrame {
private JFrame frame;
private JPanel panel;
private JLabel satelliteLabel;
private JLabel aboutLabel;
private JButton satellite;
private JButton about;
public SatNav() {
frame = new JFrame("Work Package 5");
frame.setVisible(true);
frame.setSize(300, 380);
about = new JButton("About");
add(about);
event abo = new event();
about.addActionListener(abo);
panel = new JPanel();
frame.add(panel);
panel.add(about);
setLocationRelativeTo(null); //This is for centering the frame to your screen.
setDefaultCloseOperation(EXIT_ON_CLOSE); //This for closing your application after you closing the window.
}
public class event implements ActionListener {
public void actionPerformed(ActionEvent abo) {
ImagePanel imagePanel = new ImagePanel();
//JFrames methods
panel.add(imagePanel, BorderLayout.CENTER);
revalidate();
repaint();
about.setVisible(false);
//satellite.setVisible(false);
}
}
public class ImagePanel extends JPanel {
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("about.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
setBorder(BorderFactory.createLineBorder(Color.black, 2));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
}
public static void main(String[] args) {
new SatNav();
}
}
Your problem is that you're treating the panel JPanel as if it has a BorderLayout when it doesn't. Rather it has JPanel's default FlowLayout which will size components to their preferred sizes (here [0, 0]) rather than have contained components fill the container. The simple solution: give your panel a BorderLayout:
panel = new JPanel(new BorderLayout());
Now when adding components, the BorderLayout constants will be respected by the container's layout.
Another and possibly better and more durable solution is to use a CardLayout to help you swap components.
For example:
import java.awt.CardLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SatNav2 extends JPanel {
private static final long serialVersionUID = 1L;
// a publicly available example image for demonstration purposes:
public static final String SAT_PATH = "https://upload.wikimedia.org"
+ "/wikipedia/commons/1/18/AEHF_1.jpg";
private static final String INTRO_PANEL = "intro panel";
private static final String IMAGE_LABEL = "image label";
// our layout
private CardLayout cardLayout = new CardLayout();
// JLabel to display the image
private JLabel imgLabel = new JLabel();
public SatNav2(Image img) {
// put image into JLabel
imgLabel.setIcon(new ImageIcon(img));
// JPanel to hold JButton
JPanel introPanel = new JPanel();
// add button that does the swapping
introPanel.add(new JButton(new ShowImageAction("Show Image")));
// set the CardLayout and add the components. Order of adding
// is important since the first one is displayed
setLayout(cardLayout);
// add components w/ String constants
add(introPanel, INTRO_PANEL);
add(imgLabel, IMAGE_LABEL);
}
private class ShowImageAction extends AbstractAction {
public ShowImageAction(String text) {
super(text);
}
#Override
public void actionPerformed(ActionEvent e) {
// tell card layout to show next component
cardLayout.next(SatNav2.this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
});
}
private static void createAndShowGui() throws IOException {
// get the image
URL imgUrl = new URL(SAT_PATH);
Image img = ImageIO.read(imgUrl);
// pass image into our new JPanel
SatNav2 mainPanel = new SatNav2(img);
JFrame frame = new JFrame("Satellite");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Why doesnt the keylistener react CardLayout's panel as other listeners in the code do successfully?

I wrote a keylistener to that would switch from a screensaver JPanel back to the main screen and added it to the screensaver JPanel creation method however it is not firing on key press and nothing is happening.
Anyone have any idea what is happening?
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import static javax.swing.SwingUtilities.invokeLater;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class layoutdemo {
JPanel cards; // panel that uses CardLayout
CardLayout clo;
final static String WELCOMEPANEL = "Card with welcome message";
final static String SCREENSAVERPANEL = "Card with screensaver";
final static String ENTERPINPANEL = "Card with PIN input"; // not implemented yet
final static String[] FILEARRAY = new String[] {"/cardlayouttest/newpackage/btc-zg.jpg","/cardlayouttest/newpackage/pic2.jpeg"};
static layoutdemo ldm = null;
private static int INDEX = 0;
private JLabel screenImage;
private Timer changeTimer;
public void addComponenttoPane(Container pane){ //method for adding CardLayout and components to JFrame
cards = new JPanel(new CardLayout());
cards.add(welcomePanel(),WELCOMEPANEL);
cards.add(screensaverPanel(),SCREENSAVERPANEL);
pane.add(cards,BorderLayout.CENTER);
}
public JPanel welcomePanel(){ //method for creating the "Welcome" panel
JPanel welcomePanel;
welcomePanel = new JPanel();
JLabel welcomeLabel = new JLabel("Dobrodošli na depozitni bankomat!",SwingConstants.CENTER);
JLabel instructionLabel = new JLabel("Molim vas ubacite karticu u utor sa desne strane",SwingConstants.CENTER);
instructionLabel.setFont(new Font(instructionLabel.getFont().getFontName(),Font.PLAIN,28));
welcomeLabel.setFont(new Font(instructionLabel.getFont().getFontName(),Font.PLAIN,28));
welcomePanel.setLayout(new GridLayout(0,1));
welcomePanel.add(welcomeLabel);
welcomePanel.add(instructionLabel);
return welcomePanel;
}
public JPanel screensaverPanel(){ // method for creating the "Screensaver" panel
JPanel screensaverPanel;
screensaverPanel = new JPanel();
screenImage = new JLabel();
screenImage.setIcon(new ImageIcon(getClass().getResource("/cardlayouttest/newpackage/btc-zg.jpg")));
screensaverPanel.add(screenImage);
screensaverPanel.addKeyListener(stopScreensaver());
screensaverPanel.setFocusable(true);
return screensaverPanel;
}
private static layoutdemo createAndShowGUI(){ // method for creating and showing the GUI
JFrame frame1 = new JFrame("layoutdemowithswitch");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
layoutdemo ldm = new layoutdemo();
ldm.addComponenttoPane(frame1);
frame1.pack();
frame1.setVisible(true);
frame1.getGraphicsConfiguration().getDevice().setFullScreenWindow(frame1);
ldm.clo = (CardLayout) ldm.cards.getLayout();
ldm.clo.show(ldm.cards, WELCOMEPANEL);
return ldm;
}
public ActionListener timeoutPanelListener(Timer timer){ //listener for main screen timeout - returns to ads
ActionListener timeout = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, SCREENSAVERPANEL);
timer.stop();
changeTimer = new Timer(5000,changeImageListener(screenImage));
changeTimer.start();
}
};
return timeout;
}
public ActionListener changeImageListener(JLabel image){ //listener for changing images in Screensaver
ActionListener change = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
image.setIcon(new ImageIcon(getClass().getResource(FILEARRAY[INDEX])));
INDEX++;
if (INDEX >= FILEARRAY.length) INDEX = 0;
}
};
return change;
}
public KeyListener stopScreensaver(){
KeyListener key = new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, WELCOMEPANEL);
Timer timer2 = new Timer(10000,null);
ActionListener timeout = ldm.timeoutPanelListener(timer2);
timer2.addActionListener(timeout);
timer2.start();
System.out.println("key typed");
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, WELCOMEPANEL);
Timer timer2 = new Timer(10000,null);
timer2.start();
ActionListener timeout = ldm.timeoutPanelListener(timer2);
}
};
return key;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, UnsupportedLookAndFeelException{
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
invokeLater(new Runnable(){
#Override
public void run(){
ldm = createAndShowGUI();
Timer timer = new Timer(5000,null);
ActionListener timeout = ldm.timeoutPanelListener(timer);
timer.addActionListener(timeout);
timer.start();
}
});
}
}
When using CardLayout focus is not placed on the panel when the card is switched. Since the panel doesn't have focus it can't receive KeyEvents.
So first you need to make the panel focusable.
Secondly, you need to give the panel focus when it is made visible. Check out Card Layout Focus. This is a class extends CardLayout and gives the panel focus when it is made visible.

Image not appearing in jbutton with wordGen

The image isn't being painted when this is run with WordGen, how do i fix this?
When I run this without wordgen I can get the image to appear. I'm not sure what i'm doing wrong since i'm not getting any errors.
Any help is appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class tfot extends JComponent{
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
JFrame window = new JFrame("Window");
window.setContentPane(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(Toolkit.getDefaultToolkit().getImage("Pictures/background1.png"), 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text","hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}
First...
Don't load resources or perform long running tasks within the paint methods, these may be called a number of times in quick succession. Instead, load the images before hand and paint them as needed...
public Tfot() {
setLayout(new BorderLayout());
try {
background = ImageIO.read(new File("pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
Generally, you are discouraged from overriding paint and instead should use paintComponent, lots of reasons, but generally, this is where the background is painted...
Second...
You need to add Tfot to something that is displayable, otherwise it will never be painted
JFrame window = new JFrame("Window");
window.setContentPane(new Tfot());
window.add(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
Thrid...
JPanel by default is not transparent, you need to set it's opaque property to false
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
//...
JPanel content = new JPanel();
content.setOpaque(false);
Then it will allow what ever is below it to show up (ie, the background image)
Take a look at Painting in AWT and Swing, Performing Custom Painting and Reading/Loading an Image for more details
Fourth...
You need to learn the language basics for embarking on advance topics like GUI and custom painting, without this basic knowledge, this topics will bite you hard.
You need to declare background as a instance field of the class Tfot
private BufferedImage background;
public Tfot() {
Updated - Fully runnable example
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Tfot extends JComponent {
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setOpaque(false);
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
Tfot tfot = new Tfot();
tfot.setLayout(new BorderLayout());
tfot.add(content);
JFrame window = new JFrame("Window");
window.setContentPane(tfot);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
private BufferedImage background;
public Tfot() {
try {
background = ImageIO.read(new File("Pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text", "hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}

Java - Creating PNG/Textlogo and drawing it to JFrame

I'm trying to print a string that the user can enter to a textbox, to a JFrame.
My problem is that the paintComponent method is never being called. Why?
PNGCreatorWindow Class:
public class PNGCreatorWindow {
private JFrame frame;
private JTextField txtText;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PNGCreatorWindow window = new PNGCreatorWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public PNGCreatorWindow() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 678, 502);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
txtText = new JTextField();
txtText.setBounds(121, 13, 216, 22);
frame.getContentPane().add(txtText);
txtText.setColumns(10);
JButton btnGenerate = new JButton("Generate");
btnGenerate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnGenerate.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
GeneratePNGImage();
}
});
btnGenerate.setBounds(436, 6, 183, 36);
frame.getContentPane().add(btnGenerate);
JPanel panel = new JPanel();
panel.setBounds(107, 151, 338, 160);
frame.getContentPane().add(panel);
}
protected void GeneratePNGImage() {
PNGImage img = new PNGImage(txtText.getText());
frame.getContentPane().add(img);
frame.getContentPane().validate();
frame.getContentPane().setVisible(true);
frame.repaint();
}
}
PNGImage Class:
public class PNGImage extends JComponent {
private String text;
public PNGImage(String text){
this.text = text;
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.red);
g2.drawString(this.text, 100,100);
g2.fillRect(50, 50, 1000, 1000);
}
}
I made a few changes to your code to get it to draw the text on the JPanel.
I put the JTextField and the JButton inside of a control panel (JPanel) and set a layout manager (FlowLayout) for the control panel. You should always use a layout manager for laying out Swing components.
I defined the image panel (PNGImage) as part of the laying out of the Swing components. First, you lay all of the Swing components out. Then, you change their state.
I removed the mouse adapter and just used an action listener on the JButton. The action listener works with the mouse.
In the PNGImage class, I added a setter, so I could pass the text to the class later, after the user typed the text in the JTextField.
I added a call to setPreferredSize so that I could set the size of the drawing canvas. I removed all other sizing, and used the pack method of JFrame to make the JFrame the appropriate size to hold the Swing components.
I added a null test to paintComponent, so that the text would only be drawn when there was some text to draw.
Here's the code. I put all the code in one module to make it easier to paste.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.JTextField;
public class PNGCreatorWindow {
private JFrame frame;
private JTextField txtText;
private PNGImage imagePanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new PNGCreatorWindow();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public PNGCreatorWindow() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
txtText = new JTextField(10);
controlPanel.add(txtText);
JButton btnGenerate = new JButton("Generate");
btnGenerate.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
generatePNGImage();
}
});
controlPanel.add(btnGenerate);
imagePanel = new PNGImage();
frame.getContentPane().add(controlPanel, BorderLayout.NORTH);
frame.getContentPane().add(imagePanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
protected void generatePNGImage() {
imagePanel.setText(txtText.getText());
imagePanel.repaint();
}
public class PNGImage extends JPanel {
private static final long serialVersionUID = 602718701626241645L;
private String text;
public PNGImage() {
setPreferredSize(new Dimension(400, 300));
}
public void setText(String text) {
this.text = text;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.text != null) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.drawString(this.text, 100, 100);
}
}
}
}
Edited to add an action listener that saves the contents of a JPanel as a .png file:
package com.ggl.crossword.controller;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import com.ggl.crossword.view.CrosswordFrame;
public class CreateImageActionListener implements ActionListener {
private CrosswordFrame frame;
private JPanel panel;
public CreateImageActionListener(CrosswordFrame frame,
JPanel panel) {
this.frame = frame;
this.panel = panel;
}
#Override
public void actionPerformed(ActionEvent event) {
writeImage();
}
public void writeImage() {
FileFilter filter =
new FileNameExtensionFilter("PNG file", "png");
JFileChooser fc = new JFileChooser();
fc.setFileFilter(filter);
int returnValue = fc.showSaveDialog(frame.getFrame());
if (returnValue == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
if (!file.getAbsolutePath().endsWith(".png")) {
file = new File(file.getAbsolutePath() + ".png");
}
RenderedImage image = createImage(panel);
try {
ImageIO.write(image, "png", file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private BufferedImage createImage(JPanel panel) {
int w = panel.getWidth();
int h = panel.getHeight();
BufferedImage bi = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
g.dispose();
return bi;
}
}

CardLayout Input Issue Java

For the game I'm making I'm trying to make a simple title screen with a play button that begins the game once it's pressed. I've heard that a card layout is best suited for this, but now that I implemented it for some reason my input into the game is being ignored. Here's a simplified version of the problem, and thanks for the help.
MainFrame.java
//package panels.examples;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
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;
public class MainFrame extends JFrame implements ActionListener
{
JPanel headerPanel;
JPanel bodyPanel;
JPanel panel1,panel2;
JButton button1,button2;
Container con;
CardLayout clayout;
public MainFrame()
{
//con=getContentPane();
clayout=new CardLayout();
headerPanel=new JPanel();
bodyPanel=new JPanel(clayout);
button1=new JButton("button1");
button2=new JButton("button2");
//add three buttons to headerPanel
headerPanel.add(button1);
headerPanel.add(button2);
button1.addActionListener(this);
button2.addActionListener(this);
panel1=new JPanel();
panel1.add(new JLabel("Panel1"));
panel1.setBackground(Color.pink);
panel2=new PrizePanel();
panel2.add(new JLabel("Panel2"));
panel2.setBackground(Color.gray);
//add above three panels to bodyPanel
bodyPanel.add(panel1,"one");
bodyPanel.add(panel2,"two");
setLayout(new BorderLayout());
setSize(800,400);
add(headerPanel,BorderLayout.NORTH);
add(bodyPanel,BorderLayout.CENTER);
// headerPanel.setBounds(0,0,600,100);
bodyPanel.setBounds(0,100, 600, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String args[])
{
new MainFrame();
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button1)
{
clayout.show(bodyPanel, "one");
}
else if(e.getSource()==button2)
{
clayout.show(bodyPanel, "two");
}
}
}
PrizePanel.java
//INCLUDE
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.IOException;
//CLASS
public class PrizePanel extends JPanel {
//DECLARATION
private static final int FRAMEX = 800;
private static final int FRAMEY = 400;
private static final Color BACKGROUND = new Color(204, 204, 204);
private BufferedImage myImage;
private Graphics myBuffer;
private Player pd;
private Timer t;
int points = 0;
//CONSTRUCTOR
public PrizePanel()
{
myImage = new BufferedImage(FRAMEX, FRAMEY, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
myBuffer.setColor(BACKGROUND);
myBuffer.fillRect(0, 0, FRAMEX,FRAMEY);
int xPos = (int)(Math.random()*(FRAMEX-100) + 50);
int yPos = (int)(Math.random()*(FRAMEY-100)+ 50);
pd = new Player(150,150,50);
t = new Timer((17), new Listener());
t.start();
addKeyListener(new KeyHandler());
setFocusable(true);
}
//PAINT
public void paintComponent(Graphics g)
{
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
//LISTENER
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
myBuffer.setColor(BACKGROUND);
myBuffer.fillRect(0,0,FRAMEX,FRAMEY);
pd.move();
pd.draw(myBuffer);
myBuffer.setColor(Color.BLACK);
repaint();
}
}
//MOVE
private class KeyHandler extends KeyAdapter
{
//Ground
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
pd.setdx(-2);
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
pd.setdx(2);
}
if(e.getKeyCode() == KeyEvent.VK_UP){
pd.setY(pd.getY()-1);
pd.setdy(-5.5);
}
}
}
}
The problems not the CardLayout, the problem is the use of KeyListener
Basically what's happening is when you the layout is switched, you component is not being given focus, meaning your KeyListener can't respond to key input.
The simplest solution is to use Key Bindings instead, as they allow you to define the focus level that key events will be raised.
Add one line - and panel2 keys will work:
//LISTENER
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
myBuffer.setColor(BACKGROUND);
myBuffer.fillRect(0,0,FRAMEX,FRAMEY);
pd.move();
pd.draw(myBuffer);
myBuffer.setColor(Color.BLACK);
repaint();
requestFocusInWindow();//---->> New line
}
}

Categories