I'm almost done with my hangman java code. I want to add a picture in the background though.(nightsky.png) How do I do this in the paint graphics method? I created a imageicon in the beginning.
public HangmanRevised() {
setSize(600,400);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
ImageIcon background = new ImageIcon("nightsky.png");
Letter = new TextField();
JLabel label = new JLabel("pick a Letter");
button = new Button("Enter");
add(label);
add(button);
add(Letter);
button.addActionListener(this);
createGame();
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(background, 0, 156, Color.green, button);
}
If you are painting the image at its actual size, there is no need to do any custom painting.
As has already been suggested you just add the Icon to a JLabel and add the label to your frame (or panel). Then if you want the image to appear at a certion position within the label, then you simply add an EmptyBorder to the label.
By overriding a JPanel, you can redo paintComponent() to paint the image and the JPanel itself should have a paint function for its children (although I haven't tested this functionality).
http://www.java2s.com/Code/Java/Swing-JFC/Panelwithbackgroundimage.htm
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageTest {
public static void main(String[] args) {
ImagePanel panel = new ImagePanel(new ImageIcon("images/background.png").getImage());
JFrame frame = new JFrame();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
}
You need to put the background somewhere, i.e.:
//add the following in the HangmanRevised() constructor (?)
button.addActionListener(this);
//To add
ImagePanel panel = new ImagePanel(background.getImage());
JFrame frame = new JFrame();
frame.getContentPane().add(panel);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
add(frame);
//end...
createGame();
You can also construct any image you like on-the-fly using 2D Graphics, as suggested in RotatableImage.
Related
So I am new in java graphics and I am creating a program that will show a rectangle. But when I run my program it only show like a small box and not the rectangle. I don't really know why it is happening.
Here is my code:
import javax.swing.*;
public class GraphicsEditor{
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
Rectangle rectangle = new Rectangle();
frame.setSize(1280, 720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(panel);
panel.add(rectangle);
}
}
This is my rectangle class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Rectangle extends JPanel implements Shape {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.fillRect(0, 0, 200, 130);
}
}
This is my shape interface:
import java.awt.*;
public interface Shape {
void paintComponent(Graphics g);
}
Here, try this
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class GraphicsEditor {
public static void main(String[] args) {
JFrame frame = new JFrame();
Rectangle rectangle = new Rectangle();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(rectangle);
frame.pack();
// center frame on screen
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Rectangle extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.fillRect(0, 0, 200, 130);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
}
A couple of things.
you don't need the interface.
unlike components, just painting a picture doesn't affect the layout manager, so the panel will be reduced to it's default size with out regard to any painting.
so you need to override getPreferredSize() in your JPanel.
As the comments said, you should set the preferred size of both your panel and rectangle to your desired size, and then pack the frame, like:
panel.setPreferredSize(new Dimension(500,500));
rectangle.setPreferredSize(new Dimension(500,500));
frame.pack();
Otherwise your LayoutManager (when not specified it defaults to FlowLayout) will handle your rectangle the way it wants. So another way would be learning about Layout Managers, and using your desired one.
As a side note, I would like to make some suggestions to your code. Remember, Swing is not thread safe, so place your code inside an invokeLater() call, such as:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
Rectangle rectangle = new Rectangle();
frame.setSize(1280, 720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500,500));
rectangle.setPreferredSize(new Dimension(500,500));
frame.add(panel);
panel.add(rectangle);
frame.pack();
frame.setVisible(true);
}
});
Also, calling frame.setVisible(true) should be called after adding your components.
I'm building a PongClone but I encounter a bug. **I think the bug is cause by JPanel.
I tried the Image instead of BufferedImage.
I tried the drawImage outside the paintComponent method.
I create to another panel and then add that panel inside a mainpanel.
Menu Class
package me.pong;
import javax.swing.*;
public class TestMenu {
JFrame frame;
public void createFrame () {
TestMain main = new TestMain ();
frame = new JFrame("TEST");
frame.setSize (800, 450);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane ().add (main.panel);
frame.setVisible (true);
}
}
MainClass
package me.pong;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class TestMain extends JPanel {
JPanel panel = new JPanel ();
BufferedImage img;
Graphics g;
public static void main (String[] args) {
TestMain testMain = new TestMain ();
TestMenu menu = new TestMenu ();
menu.createFrame ();
testMain.drawGraphics ();
}
public void drawGraphics(){
panel.add (new TestMain ());
img = new BufferedImage(800, 450, BufferedImage.TYPE_INT_RGB);
g = img.createGraphics ();
g.drawString ("TEST STRING 2", 250,250);
}
#Override
protected void paintComponent (Graphics g) {
super.paintComponent (g);
g.clearRect (0,0,800,450);
g.drawImage (img, 0,0,null);
g.setColor (Color.white);
g.drawString ("TEST STRING", 500,250);
g.setColor (Color.black);
g.drawRect (150,100,10,70);
}
}
I expect the Image fill the component but actual output is little tiny box.
Just like that
EDIT: Delete the code and added MCVE/SSCCE Code(I didn't know that). Still same. If I add the image inside the frame it's works but other way doesn't. I know I'm missing something, but I don't know what that is.
**Yes. Problem caused by JPanel but I don't know how to fix it.
The extra panel declared within the custom painted class that is a panel was not only unnecessary, but the source of problems. See further comments in code.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class TestMain extends JPanel {
JFrame frame;
// Not needed or useful!
//JPanel panel = new JPanel();
BufferedImage img;
Graphics g;
public static void main(String[] args) {
TestMain testMain = new TestMain();
testMain.createFrame();
testMain.drawGraphics();
}
public void createFrame() {
TestMain main = new TestMain();
frame = new JFrame("TEST");
frame.setSize(400, 250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.getContentPane().add(main.panel);
frame.getContentPane().add(main);
frame.setVisible(true);
}
public void drawGraphics() {
//panel.add(new TestMain());
add(new TestMain());
img = new BufferedImage(800, 450, BufferedImage.TYPE_INT_RGB);
g = img.createGraphics();
g.drawString("TEST STRING 2", 250, 250);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, 800, 450);
// all JComponent instances are image observers
//g.drawImage(img, 0, 0, null);
g.drawImage(img, 0, 0, this);
g.setColor(Color.WHITE);
// NEW! Otherwise invisible
g.setColor(Color.RED);
g.drawString("TEST STRING", 200, 100);
g.setColor(Color.BLACK);
g.drawRect(150, 100, 10, 70);
}
}
As an aside:
That code still has problems, but I thought it best to stick closely to fixing only the immediate problem.
The easiest way to display a BufferedImage is to show it in a JLabel via an ImageIcon.
I've made a code to draw a simple oval in a panel and then according to the button clicked (left or right) or arrow button, it will move accordingly. This code I have here doesn't seem to make the shape appear in the yellow background. Is there anything that I can change?
Also, I will also link the made oval into two separate keyboard and button click events. Is using KeyAdaptor method and lambda expression on the mouse event a good measure here? Thank you in advance!
private JButton btnLeftMvmt, btnRightMvmt;
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponents(g);
int width = getWidth()/2;
int top = (getHeight() - HEIGHT) / 2;
/* Code above is a vain attempt to center the oval to the yellow
background.
Is this correct, as well?*/
g.fillOval(width, top, 150, 150);
g.setColor(Color.RED);
}
}
public MyFrame(){
setTitle("Red Oval Translator");
setSize(500, 200);
setLayout(new BorderLayout());
JPanel panel1, panel2;
panel1 = new JPanel();
panel2 = new JPanel();
panel1.add(new MyPanel());
panel1.setBackground(Color.YELLOW);
btnLeftMvmt = new JButton("Left Translation");
btnRightMvmt = new JButton("Right Translation");
panel2.add(btnLeftMvmt);
panel2.add(btnRightMvmt);
add(panel1);
add(panel2, BorderLayout.SOUTH);
setLocationRelativeTo(null);
setVisible(true);
I assume you wanted something like that:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
class MyPanel extends JPanel {
public MyPanel() {
setPreferredSize(new Dimension(300, 250));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
int width = getWidth()/2;
int top = (getHeight() - HEIGHT) / 2;
g.setColor(Color.RED); //need to apply color before painting
g.fillOval(width, top, 150, 150);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new MyFrame());
}
}
class MyFrame extends JFrame{
private JButton btnLeftMvmt, btnRightMvmt;
public MyFrame() {
setTitle("Red Oval Translator");
setLayout(new BorderLayout()); //BorderLayout for JFrame
JPanel panel2 = new JPanel();
btnLeftMvmt = new JButton("Left Translation");
btnRightMvmt = new JButton("Right Translation");
panel2.add(btnLeftMvmt);
panel2.add(btnRightMvmt);
add(new MyPanel());
add(panel2, BorderLayout.SOUTH);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
}
Always post mcve
One problem with your code is that you should swap the order of g.fillOval(width, top, 150, 150); and g.setColor(Color.RED); to get a red oval and not a default-colored oval.
I want to create a java Application like a widget. Here is my code below
package newpackage;
public class MainFrame extends JFrame {
JLabel imageLabel = new JLabel();
public MainFrame() {
try {
this.setUndecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(360, 360));
ImageIcon ii = new ImageIcon(this.getClass().getResource("imageexcel.gif"));
imageLabel.setIcon(ii);
add(imageLabel, java.awt.BorderLayout.CENTER);
this.setVisible(true);
Shape shape=new Ellipse2D.Float(0,0,360,360);
AWTUtilities.setWindowShape(this, shape);
AWTUtilities.setWindowOpaque(this, false);
imageLabel.add(new JButton("START"));
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
new MainFrame();
}
}
In the above code, I have done the following:
Created a Frame
Removed the Title Bar
Added the Background using JLabel
Changed the shape of window as circle according to the shape of image
Now I would like to add some components in to it and perform some action with them but no component is visible after adding.
I have tried adding to Frame as well as JLabel and no use from either.
This is the image i used for background
Please help me to proceed further....
Thanking you
JLabels use null layouts by default, and so your button will default to size 0,0. Try giving it a decent layout manager, even FlowLayout would likely work. Another solution is to keep the null layout and set the sizes and positions of added components, but this route is a dangerous route and one I don't recommend.
Actually a GridBagLayout works nice to center the components. Also add all components before calling setVisible(true):
imageLabel.setLayout(new GridBagLayout());
this.setUndecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(360, 360));
ImageIcon ii = new ImageIcon(this.getClass().getResource("imageexcel.gif"));
imageLabel.setIcon(ii);
add(imageLabel, java.awt.BorderLayout.CENTER);
imageLabel.add(new JButton("START"));
this.setVisible(true);
or better?
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.net.URL;
import javax.swing.*;
import com.sun.awt.AWTUtilities;
#SuppressWarnings("serial")
public class MainPanelOvalFrame extends JPanel {
private static final String RESOURCE_PATH = "imageexcel.gif";
private Window window;
private Image img;
public MainPanelOvalFrame(Window window, Image image) {
this.window = window;
this.img = image;
setLayout(new GridBagLayout());
add(new JButton(new StartAction("Start", KeyEvent.VK_S)));
int w = image.getWidth(this);
int h = image.getHeight(this);
Shape shape = new Ellipse2D.Float(0, 0, w, h);
AWTUtilities.setWindowShape(window, shape);
AWTUtilities.setWindowOpaque(window, false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int w = img.getWidth(this);
int h = img.getHeight(this);
return new Dimension(w, h);
}
private class StartAction extends AbstractAction {
public StartAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
window.dispose();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame();
frame.setUndecorated(true);
URL imgUrl = MainPanelOvalFrame.class.getResource(RESOURCE_PATH);
Image image = new ImageIcon(imgUrl).getImage();
MainPanelOvalFrame mainPanel = new MainPanelOvalFrame(frame, image);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You just need to set a Layout manager for imageLabel ,or use null as the Layout manager, then set the size and location of the JButton manually.
to use Layout Manager
imageLabel.setIcon(ii);
imageLabel.setLayout(new FlowLayout());
imageLabel.add(new JButton("START"));
//need to setLayout and add JButton before setVisible(true)
add(imageLabel, java.awt.BorderLayout.CENTER);
this.setVisible(true);
to use null layout
JButton j=new JButton("START");
j.setSize(100,50);
j.setLocation(imageLabel.getWidth()/2-j.getWidth()/2, imageLabel.getHeight()/2-j.getHeight()/2);
//then add Button into imageLabel
imageLabel.add(j);
Layout manager is usually recommended because it can fit different environment.
My problem is I want to draw a huge Panel but its not possible to see this panel in a small size frame so i supposed to use ScrollPane and I used it..
But by scrolling clashes occurs so i cant see any panel there .i just want to fix it
Please anyone see my code and run it and help to solve the problem
import java.awt.*;
import javax.swing.*;
public class Swing{
JFrame frame;
Panel panel;
public static void main(String [] args){
Swing a = new Swing();
a.go();
}
public void go(){
frame = new JFrame();
panel = new Panel();
panel.setPreferredSize(new Dimension(5000, 5000));
JScrollPane scroll = new JScrollPane(panel);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
}
class Panel extends JPanel{
public void paintComponent(Graphics g){
Graphics2D a = (Graphics2D)g;
a.setColor(Color.RED);
a.drawLine(50, 50, 5000, 5000);
}
}
}
Thanks in advance!
Always make sure to call super.paintComponent(g); to redraw the rest of the component. Otherwise these types of painting artifacts are seen.
import java.awt.*;
import javax.swing.*;
public class Swing{
JFrame frame;
Panel panel;
public static void main(String [] args){
Swing a = new Swing();
a.go();
}
public void go(){
frame = new JFrame();
panel = new Panel();
panel.setPreferredSize(new Dimension(5000, 5000));
JScrollPane scroll = new JScrollPane(panel);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
}
class Panel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g); // VERY IMPORTANT!
Graphics2D a = (Graphics2D)g;
a.setColor(Color.RED);
a.drawLine(50, 50, 5000, 5000);
}
}
}