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;
}
}
Related
My JFrame uses a BorderLayout and it has a JLabel nested in several panels with different layout managers. I've tried several methods, however, cannot get the true position of where it sits in the frame.
I made a test UI and it seems like when other components are added the getX and getY parameters do not update. Other methods like getLocation do not provide a correct result either. Is there any way to obtain the exact location without manually calculating every possible offset from each component.
I am tracking the stated positions of the label (content) using a similar sized panel called content2 in the glass pane which I want to sit underneath content perfectly.
public class test {
private Dimension pSize = new Dimension(100,100);
private JFrame frame = new JFrame();
public static void main(String[] args) {
new test();
}
public test() {
//setup frame basics
frame.setPreferredSize(new Dimension(500,500));
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// setup GUI
JMenuBar j = new JMenuBar();
JMenuItem a = new JMenuItem("lol");
j.add(a);
JPanel j2 = new JPanel();
//setup main panel
JPanel main = new JPanel();
main.setBackground(Color.DARK_GRAY);
//setup side panel
FlowLayout f1 = new FlowLayout(FlowLayout.LEADING);
f1.setHgap(10);
f1.setVgap(0);
JPanel side = new JPanel();
side.setLayout(new BorderLayout());
side.setBackground(Color.gray);
side.setPreferredSize(new Dimension(150,100));
//setup JLabel (the main focus)
JLabel content = new JLabel("a");
content.setOpaque(true);
content.setBackground(Color.blue);
content.setPreferredSize(pSize);
// Setup the internal panels of side
JPanel top = new JPanel();//The panel where CONTENT is, the main focus
JPanel bot = new JPanel();
top.setBackground(Color.WHITE);
bot.setBackground(Color.orange);
top.setLayout(f1);
top.add(content);
side.add(top, BorderLayout.NORTH);
side.add(bot, BorderLayout.CENTER);
frame.add(main, BorderLayout.CENTER);
frame.add(side, BorderLayout.WEST);
frame.add(j2, BorderLayout.NORTH);
frame.setJMenuBar(j);
frame.pack();
frame.setVisible(true);
//Setting up the glass panel
JPanel pane = new JPanel();
pane.setLayout(null);
pane.setOpaque(false);
JPanel content2 = new JPanel();
content2.setBackground(Color.red);
content.revalidate();
int x = content.getX();
int y = content.getY();
// y = (int) content.getLocation().getY(); //returns a completely wrong location
//y = (int) content.getLocationOnScreen(); //returns a completely wrong location
/*
Point p = new Point();
p.setLocation(x, y);
p = SwingUtilities.convertPoint(content2, x, y, frame);
//SwingUtilities.convertPoint(content, p, frame);
y = (int) p.getY();
*
* Tried multiple SwingUtility converions to no avail
*
*/
// y = y +j.getHeight() + j2.getHeight(); // Manually calculating the Y off set works successfully but is too tedious for large project
y = y + content.getHeight();
content2.setBounds(x,y,100,100);
pane.add(content2);
frame.setGlassPane(pane);
frame.getGlassPane().setVisible(true);
frame.pack();
}
}
//frame.getContentPane().add(content);
//frame.add(content);
frame.setPreferredSize(new Dimension(500,500));
content.setBorder(BorderFactory.createEmptyBorder());
side.setLayout(new BorderLayout());
JPanel top = new JPanel();
JPanel bot = new JPanel();
top.setBackground(Color.WHITE);
bot.setBackground(Color.orange);
side.add(top, BorderLayout.NORTH);
top.setLayout(f1);
top.add(content);
side.add(bot, BorderLayout.CENTER);
frame.add(main, BorderLayout.CENTER);
frame.add(j2, BorderLayout.NORTH);
frame.add(side, BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
JPanel pane = new JPanel();
pane.setLayout(null);
pane.setOpaque(false);
JPanel content2 = new JPanel();
content2.setBackground(Color.red);
content.revalidate();
int x = content.getX();
int y = content.getY();
// y = y +j.getHeight() + j2.getHeight();
y = y + content.getHeight();
content2.setBounds(x,y,100,100);
pane.add(content2);
frame.setGlassPane(pane);
frame.getGlassPane().setVisible(true);
frame.pack();
}
}
Conceptually you could make use of SwingUtilities.convertPoint or SwingUtilities.convertRectangle to convert between container contexts, for example...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GlassPane glassPane = new GlassPane();
JFrame frame = new JFrame();
frame.setGlassPane(glassPane);
frame.add(new MainPane(glassPane));
glassPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Tracker {
public void addTrackable(Trackable trackable);
public void removeTrackable(Trackable trackable);
}
public interface Trackable {
public JComponent[] getTrackedComponents();
}
public class MainPane extends JPanel {
private JLabel label = new JLabel("Catch me if you can");
public MainPane(Tracker tracker) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(32, 32, 32, 32));
add(label);
tracker.addTrackable(new Trackable() {
#Override
public JComponent[] getTrackedComponents() {
return new JComponent[] { label };
}
});
}
}
public class GlassPane extends JPanel implements Tracker {
private List<Trackable> trackables = new ArrayList<>(8);
public GlassPane() {
setOpaque(false);
}
#Override
public void addTrackable(Trackable trackable) {
trackables.add(trackable);
revalidate();
repaint();
}
#Override
public void removeTrackable(Trackable trackable) {
trackables.remove(trackable);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Trackable trackable : trackables) {
for (JComponent component : trackable.getTrackedComponents()) {
Rectangle relativeBounds = SwingUtilities.convertRectangle(component.getParent(), component.getBounds(), this);
g2d.draw(relativeBounds);
}
}
g2d.dispose();
}
}
}
Well, that's pretty boring, it's one component inside one container, let's trying something a little more complicated...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GlassPane glassPane = new GlassPane();
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(2, 2, 8, 8));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.setGlassPane(glassPane);
glassPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Tracker {
public void addTrackable(Trackable trackable);
public void removeTrackable(Trackable trackable);
}
public interface Trackable {
public JComponent[] getTrackedComponents();
}
public class MainPane extends JPanel {
private JLabel label = new JLabel("Catch me if you can");
public MainPane(Tracker tracker) {
setLayout(new GridBagLayout());
setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY, 1, true), new EmptyBorder(32, 32, 32, 32)));
add(label);
tracker.addTrackable(new Trackable() {
#Override
public JComponent[] getTrackedComponents() {
return new JComponent[]{label};
}
});
}
}
public class GlassPane extends JPanel implements Tracker {
private List<Trackable> trackables = new ArrayList<>(8);
private List<Color> masterColors = new ArrayList<>(Arrays.asList(new Color[]{
Color.RED,
Color.GREEN,
Color.BLUE,
Color.CYAN,
Color.DARK_GRAY,
Color.GRAY,
Color.MAGENTA,
Color.ORANGE,
Color.PINK,
Color.YELLOW,}));
public GlassPane() {
setOpaque(false);
}
#Override
public void addTrackable(Trackable trackable) {
trackables.add(trackable);
revalidate();
repaint();
}
#Override
public void removeTrackable(Trackable trackable) {
trackables.remove(trackable);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
List<Color> colors = new ArrayList<>(masterColors);
for (Trackable trackable : trackables) {
for (JComponent component : trackable.getTrackedComponents()) {
if (colors.isEmpty()) {
colors = new ArrayList<>(masterColors);
}
g2d.setColor(colors.remove(0));
Rectangle relativeBounds = SwingUtilities.convertRectangle(component.getParent(), component.getBounds(), this);
g2d.draw(relativeBounds);
}
}
g2d.dispose();
}
}
}
Here is a new smipler example program, trying to keep as close to your code as possible, that uses the convertRectangle but I can't manage to run it correctly
int y = (int) (r.getY() + r.getHeight()); ... are you deliberately trying to offset the "overlay"? This seems weird to me.
Another issue is, how does the GlassPane know when the child has changed position/size
So, I modified your code, getting rid of the "modification" to the x/y position (so I'm 100% sure that the conversion between context spaces is correct) and added a ComponentListener to monitor changes to the "target" component
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
public class Main {
private Dimension pSize = new Dimension(100, 100);
private JFrame frame = new JFrame();
private JLabel content = new JLabel("Grief");
private JPanel content2 = new JPanel();
private SidePane sidePane = new SidePane();
private GlassPane glass = new GlassPane();
private Menu menu = new Menu();
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
content.setBackground(Color.green);
content.setPreferredSize(pSize);
content.setOpaque(true);
//setup frame basics
frame.setPreferredSize(new Dimension(500, 500));
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setGlassPane(glass);
frame.add(new MainPane());
// glass.setNewLocation();
// glass.revalidate();
frame.getGlassPane().setVisible(true);
// glass.setNewLocation();
frame.pack();
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
//this.setBackground(Color.orange);
this.setLayout(new BorderLayout());
this.add(sidePane, BorderLayout.WEST);
this.add(menu, BorderLayout.NORTH);
}
}
public class SidePane extends JPanel {
public SidePane() {
FlowLayout f1 = new FlowLayout(FlowLayout.LEADING);
this.setLayout(f1);
this.setBackground(Color.blue);
this.add(content);
}
}
public class Menu extends JPanel {
public Menu() {
this.setBackground(Color.orange);
}
}
public class GlassPane extends JPanel {
private Rectangle target;
public GlassPane() {
this.setOpaque(false);
setLayout(null);
content2.setBackground(Color.BLACK);
content2.setPreferredSize(pSize);
content2.setOpaque(true);
add(content2);
content.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
updateOverlay();
}
#Override
public void componentMoved(ComponentEvent e) {
updateOverlay();
}
});
}
protected void updateOverlay() {
// Rectangle t = new Rectangle();
// t.setBounds((int) content.getLocation().getX(), (int) content.getLocation().getY(), content.getWidth(), content.getHeight());
// Rectangle r = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
// Rectangle r = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
target = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
content2.setBounds(target);
// r = SwingUtilities.convertRectangle(content.getParent(), t, this);
// int x = (int) r.getBounds().getX();
// x = (int) r.getX();
// int y = (int) (r.getY() + r.getHeight());
//
// content2.setBounds(x, y, 100, 100);
// this.add(content2);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
if (target != null) {
g2d.setColor(Color.RED);
g2d.draw(target);
}
g2d.dispose();
}
}
}
If you have the coordinate within the component, transfer it to screen coordinates using your component's convertPointToScreen(). Afterwards you can transfer back to see where in the window it sits by using the frame's convertPointFromScreen().
Or eliminate one of the two steps by directly using convertPoint().
Fixed the positioning issue using #MadProgrammer 's method of SwingUtilities.convertRectangle and called a new method at the end of the constructor which positioned the tracker panel.
Created a separate class for the glass pane
private class GlassPane extends JPanel {
public GlassPane() {
this.setLayout(null);
}
public void setNewLocation() {
Rectangle r = SwingUtilities.convertRectangle(top, content.getBounds(), this);
JPanel content2 = new JPanel();
int x = (int) r.getBounds().getX();
x = (int) r.getX();
int y = (int) (r.getY() + r.getHeight() + 1);
content2.setBounds(x, y, 100,100);
this.add(content2);
}
}
And added a call to the new method setNewLocation() at the end of the constructor
public test() {
**...**
frame.pack();
frame.setVisible(true);
glass.setNewLocation();
}
Hello I am new to Java GUI I made a second.java which is as below:
package theproject;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class second extends JPanel implements ActionListener {
private Timer animator;
private ImageIcon imageArray[];
private int delay=50, totalFrames=8, currentFreames=1;
public second()
{
imageArray= new ImageIcon[totalFrames];
System.out.println(imageArray.length);
for(int i=0; i<imageArray.length;i++)
{
imageArray[i]=new ImageIcon(i+1+".png");
System.out.println(i+1);
}
animator= new Timer(delay, this);
animator.start();
}
public void paintComponent(Graphics g )
{
super.paintComponent(g);
if(currentFreames<8)
{
imageArray[currentFreames].paintIcon(this, g, 0, 0);
currentFreames++;
System.out.println(currentFreames);
}
else{
currentFreames=0;
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
repaint();
}
}
And a Gui calling the constructor second and output is not showing . Can you please guide me what should I do and the gui is given below:
package theproject;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.SwingConstants;
import javax.swing.JTextField;
public class Sav {
private JFrame frame;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Sav window = new Sav();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Sav() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
textField = new JTextField();
textField.setBounds(10, 0, 261, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
JButton btnNewButton = new JButton("Submit");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
second s= new second();
frame.add(s);
}
});
btnNewButton.setBounds(273, -1, 89, 23);
frame.getContentPane().add(btnNewButton);
}
}
The gui has to basically call the constructor and which will showcase the animation on the screen If someone what i am doing wrong or if something that has to be done please let me know .
First, don't update the state within the paintComponent method, paint can occur for a number of reasons at any time, mostly without your interaction. Painting should simple paint the current state. In your ActionListener, you should advance the frame and make decisions about what should occur (like resetting the frame value)
Second, you never actually add second to anything, so it will never be displayed.
Third, you don't override getPreferredSize in second, so the layout managers will have no idea what size the component should be and will simply be assigned 0x0, making it as good as invisible as makes no difference
Fourth, you're using null layouts. This is going to make you life impossibly hard. Swing has been designed and optimised around the use of layout managers, they do important work in deciding how best to deal with differences in font metrics across different rendering systems/pipelines, I highly recommend that you take the time to learn how to use them
Fifthly, paintComponent has no business been public, no one should ever call it directly
Example
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
public class Sav {
private JFrame frame;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Sav window = new Sav();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Sav() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
textField = new JTextField(20);
frame.getContentPane().add(textField, gbc);
JButton btnNewButton = new JButton("Submit");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
second s = new second();
frame.add(s, gbc);
frame.getContentPane().revalidate();
frame.pack();
frame.setLocationRelativeTo(null);
}
});
frame.getContentPane().add(btnNewButton, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class second extends JPanel implements ActionListener {
private Timer animator;
private ImageIcon imageArray[];
private int delay = 50, totalFrames = 8, currentFreames = 1;
public second() {
imageArray = new ImageIcon[totalFrames];
for (int i = 0; i < imageArray.length; i++) {
imageArray[i] = new ImageIcon(getImage(i));
}
animator = new Timer(delay, this);
animator.start();
}
protected Image getImage(int index) {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
FontMetrics fm = g2d.getFontMetrics();
g2d.dispose();
String text = Integer.toString(index);
int height = fm.getHeight();
int width = fm.stringWidth(text);
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setColor(getForeground());
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
return img;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(imageArray[0].getIconWidth(), imageArray[1].getIconHeight());
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
imageArray[currentFreames].paintIcon(this, g, 0, 0);
}
#Override
public void actionPerformed(ActionEvent arg0) {
currentFreames++;
if (currentFreames >= imageArray.length) {
currentFreames = 0;
}
repaint();
}
}
}
Your code is also not working. It increment the values of image set but do not displays the images
Works just fine for me...
imageArray[i]=new ImageIcon(i+1+".png"); will not generate any errors if the image can't be loaded for some reason (and it will load the images in the background thread, which is just another issue).
Instead, I would recommend using ImageIO.read instead, which will throw a IOException if the image can't be read for some reason, which is infinitely more useful. See Reading/Loading an Image for more details
I have one class Names and it has a JTextField. I am trying to place getText from this textfield and save it in the variable nameString1. I then want the other class Game to call Names and place the string collected from ``the JTextField onto a label. For some reason it is not displaying. Please let me know if there are any rookie errors, I am only year 10.
Names
package com.aqagame.harrykitchener;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names()
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Names();
}
});
}
}
Game
package com.aqagame.harrykitchener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game
{
private JLabel player1Str, player2Str;
public Game()
{
JFrame window = new JFrame ("Main Game");
JPanel drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
Names namesCall2 = new Names();
player1Str = new JLabel(namesCall2.nameString1);
drawPanel.add(player1Str);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
}
The problem is that you are setting the label without getting the textfield text. The JLabel on your Game wont change by the time you click the button..
Okie I made some change in you classes What I did is that I maid an interface which will be called when your button is pressed
Here is the interface:
public interface Lawl {
public void changename(String name);
}
I then implemented this interface to the game:
public class Game implements Lawl
{
private JLabel player1Str, player2Str;
JPanel drawPanel;
Names namesCall2;
public Game()
{
JFrame window = new JFrame ("Main Game");
drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
// Names namesCall2 = new Names(this);
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
namesCall2 = new Names(Game.this);
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
#Override
public void changename(String name) {
System.out.println("I am clicked");
player1Str = new JLabel(name);
drawPanel.add(player1Str);
drawPanel.revalidate();
}
}
In the names class:
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names(){}
public Names(final Lawl game)
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
game.changename(nameString1);
// Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
How it works??
I created an interface and implemented it to the game class then pass the reference of the interface to the Names class which will then be called when button is clicked..
when it is called game.changename(nameString1);by the button clicked it will then be called on the game class as you could see there is an method from the implemented inteface in the game class that will be called when you click the button..
If you want to chain data dont create a new Main thread to just execute a new Window.. just use the one I did in the code..
replace
public final static JTextField player1Input;
instead of
private JTextField player1Input;
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;
}
}
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.