Hi I'm new to java GUI Programming. I created Jframe(MainFrame) and add JPanel(OutPanel) Which has another Jpanel(InnerPanel). I try to achieve drawing Image in InnerPanel, not drawing OutPanel. I want OutPanel used to be just Container. So as you see TestA. I get Graphics from InnerPanel in OutPanel's paintComponent() which is overided method.
So finally I can draw using InnerPanel's Graphics in OutPanel's paintComponent() method. but It couldn't work well. It couldn't draw Image one time when program starts. when I hided window and shown again, the program shows image. Even though that is part of Image, not all Image.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestA{
private static Image image = GUI.loadImage("PlayerBoard.jpg");
public static void main(String[] args) {
TestA testA = new TestA();
}
public TestA() {
JFrame mainFrame = new JFrame("Main Frame");
mainFrame.setLayout(null);
mainFrame.setSize(500, 500);
mainFrame.setVisible(true);
mainFrame.setBackground(Color.black);
mainFrame.setLocation(800, 400);
OutPanel outPanel = new OutPanel();
mainFrame.getContentPane().add(outPanel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
outPanel.repaint();
}
private class OutPanel extends JPanel {
JPanel innerPanel;
public OutPanel() {
this.setLayout(null);
this.setLocation(0, 0);
this.setSize(500, 50);
this.setBackground(Color.red);
innerPanel = new JPanel();
this.innerPanel.setSize(400, 50);
this.innerPanel.setVisible(true);
this.add(innerPanel);
}
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
int width = 500;
int height = 50;
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics gBuffer = resized.createGraphics();
gBuffer.drawImage(TestA.image, 0, 0, width, height, this);
Graphics gPanel = innerPanel.getGraphics();
gPanel.drawImage(resized, 0, 0, width, height, this);
}
}
}
So I try diffrerent way(TestB). Only different thing is I just moved drawImage() method and getGraphics() thing to InnerPanel's paintComponent() from OutPanel's paintComponent(). Here's another Code TestB. and It works well.
Why this happens. Is it relates to context?. What is Context. and could I draw InnerPanel's Image in OutPanel?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestB {
private static Image image = GUI.loadImage("PlayerBoard.jpg");
public static void main(String[] args) {
TestB testB = new TestB();
}
public TestB() {
JFrame mainFrame = new JFrame("Main Frame");
mainFrame.setLayout(null);
mainFrame.setSize(500, 500);
mainFrame.setVisible(true);
mainFrame.setBackground(Color.black);
mainFrame.setLocation(800, 400);
OutPanel outPanel = new OutPanel();
mainFrame.add(outPanel);
outPanel.repaint();
}
private class OutPanel extends JPanel {
JPanel innerPanel;
public OutPanel() {
this.setLayout(null);
this.setLocation(0, 0);
this.setSize(500, 50);
this.setBackground(Color.red);
innerPanel = new InnerPanel(this);
this.innerPanel.setSize(500, 50);
this.innerPanel.setVisible(true);
this.add(innerPanel);
this.repaint();
}
}
private class InnerPanel extends JPanel {
OutPanel outPanel;
public InnerPanel(OutPanel outPanel) {
this.outPanel = outPanel;
}
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
int width = 500;
int height = 50;
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(TestB.image, 0, 0, width, height, this);
}
}
}
The paintComponent() method of a component is responsible for painting itself only. It should never know or care about any other component.
I want OutPanel used to be just Container.
Then do just that. Create the panel and set the layout manager for the outer panel and then add the outer panel to the JFrame.
Then create your inner panel and add it to the outer panel. Make sure you override the getPreferredSize() method of the inner panel so the layout manager of the outer panel can do its job.
Read the section from the Swing tutorial on Custom Painting for more information and working examples to start with.
Related
I have just started with Graphics in java, and I'm already stuck. I have tried to set the color of the JPanel to red but nothing seems to work! Any help is highly appreciated.
JFrame class:
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Color;
public class redBoxFrame{
public static void main(String[]args){
JFrame f = new JFrame();
f.setSize(400, 200);
f.setTitle("A red box");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new redBoxPanel();
p.setBackground(Color.RED);
f.add(p);
f.setVisible(true);
}
}
JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.Color;
public class redBoxPanel extends JPanel {
public void paintComponent(Graphics g){
g.fillRect(0, 0, 100, 100);
g.setColor(Color.RED);
}
}
As you can see I have both tried to declare the color in the JFrame class and in the JPanel class but none of them seem to work.
Thank you!
Everyone here seems to miss the fact that the colour should be set before drawing.
I'll set the main background to BLUE for demo purposes.
public static void main(String[] args) {
//...
JPanel p = new redBoxPanel();
// BLUE bg. This covers the whole panel.
p.setBackground(Color.BLUE);
//...
}
And now for the red box!
public static class redBoxPanel extends JPanel {
#Override public void paintComponent(Graphics g) {
// You need to call the superclass' paintComponent() so that the
// setBackground() you called in main() is painted.
super.paintComponent(g);
// You need to set the colour BEFORE drawing your rect
g.setColor(Color.RED);
// Now that we have a colour, perform the drawing
g.fillRect(0, 0, 100, 100);
// More, for fun
g.setColor(Color.GREEN);
g.drawLine(0, 0, 100, 100);
}
}
I think you you are missing super.paintComponent(g); in your painComponent method.
I Believe that the solution is working however you are, like you said in your question, setting the background in the JFrame class and the JPanel class.
if you remove the setBackground from the JFrame class you should see only the rectangle that you are drawing. Please try the below solution and let us know if it works.
JFrame class:
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Color;
public class redBoxFrame{
public static void main(String[]args){
JFrame f = new JFrame();
f.setSize(400, 200);
f.setTitle("A red box");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new redBoxPanel();
f.add(p);
f.setVisible(true);
}
}
JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.Color;
public class redBoxPanel extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.RED);
}
}
The program works fine, but when I add the setUndecorated code, the panel does not appear. Problem is solving when I minimize and reopen the program. I tried repaint() , but It's not working.
package testing;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class test extends JFrame{
static int width = 900;
static int height = 520;
JFrame frame;
JPanel panel;
JButton selectKey = new JButton("Select KeyIMG");
static BufferedImage bg;
class MyCanvas extends JComponent{
public void paint(Graphics g) {
try {
bg = ImageIO.read(new File("BGFILE"));
} catch (IOException e) {
e.printStackTrace();
}
g.setClip(0, 0, width, height);
g.drawImage(bg,0,0,width,height, this);
g.dispose();panel.repaint();
}
}
public test(){
super("Test");
setBounds(250, 100, width, height);
selectKey.setBounds(width/9,height/2,width/45*8,height/13);
getContentPane().add(new MyCanvas());setUndecorated(true);setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setBackground( new Color(0, 0, 0, 0));
panel.setLayout(null);
panel.add(selectKey);
add(panel);
}
public static void main(String...Args){
new test();
}
}
What's wrong ?
Issues
Overriding paint. It's highly discouraged to override paint, painting is a complex series of compounding methods which work together to produce a the final result. It's highly recommended that you override paintComponent instead
Not calling super.paint, see the previous comment. Unless you know exactly what you're doing and are prepared to take over the responsibility of the paint method, call it's super method, there only a very few use cases I'd consider it safe not to do this.
Using a alpha based color on an opaque component; panel.setBackground(new Color(0, 0, 0, 0));. This is bad idea. Swing only knows how to deal with opaque and transparent components, it doesn't know how it should paint components with alpha based colors. The API will simply ignore any components beneath it, which is likely one of the major causes of your problem
g.dispose(); don't ever dispose of a Graphics context you did not create or copy. Doing so can prevent other components from been painted
Don't call panel.repaint(); from within any paint method, painting paints the current state, it should never do anything to change it, doing so well put you into a spiral of CPU death as it begins to chew up all the CPU cycles, in fact, MyCanvas has no right to be modifying panel anyway and the way your code is set up, it could generate a NullPointerException
"Other" concerns
static BufferedImage bg; is worrisome. No body else has any need to deal with this variable, the only class which should be dealing with it is the MyCanvas class
g.setClip(0, 0, width, height); is pointless (and potentially dangerous), this has already been done before the paint method was called. This is made worse by the fact that you are not relying on the components actual size, which could cause the painting to overrun the visible bounds of the component
Extending from JFrame. You should avoid extending from top level containers, they are complex components to which you rarely add any new/reusable functionality to and they lock you into a single use case, much better to start with a JPanel and add that to whatever container you need
An example...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
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 Test {
class Background extends JComponent {
private BufferedImage bg;
public Background() {
try {
bg = ImageIO.read(new File("/path/to/your/image"));
} catch (IOException e) {
e.printStackTrace();
}
setLayout(new BorderLayout());
}
#Override
public Dimension getPreferredSize() {
return bg == null ? super.getPreferredSize() : new Dimension(bg.getWidth(), bg.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
}
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setContentPane(new Background());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(new JLabel("This is a label, don't I look pretty"), gbc);
JButton selectKey = new JButton("Select KeyIMG");
panel.add(selectKey, gbc);
panel.setOpaque(false);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String... Args) {
new Test();
}
}
I'm new to Java and I'm trying to display an image on JFrame.
I have the main class:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PingPong extends JPanel{
Ball ball = new Ball(this);
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
}
public static void main(String[] args){
/* Creating the frame */
JFrame frame = new JFrame();
frame.setTitle("Ping Pong!");
frame.setSize(600, 600);
frame.setBounds(0, 0, 600, 600);
frame.getContentPane().setBackground(Color.darkGray);
frame.add(new JLabel(new ImageIcon("images/Table.png")));
frame.setVisible(true);
}
}
and Ball class:
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Ball {
int x,y;
ImageIcon ball = new ImageIcon("images/Ball.png");
Image ballImage = ball.getImage();
public Ball(JPanel panel){
this.x = panel.getWidth()/2;
this.y = panel.getHeight()/2;
}
public void repaint(Graphics g){
g.drawImage(ballImage, x, y, null);
}
}
I want to display the Ball image in the main.
How can I do it?
I saw something with repaint() and paintComponent.
I just want to draw the ball image on the frame.
Thanks in advance!
Fist you need to add your custom component PingPong to frame. Then custom paintComponent(Graphics g) will be called.
Secondly add drawing code to paintComponent(Graphics g).
public class PingPong extends JPanel {
private static final long serialVersionUID = 7048642004725023153L;
Ball ball = new Ball();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
ball.paint(g);
}
public static void main(String[] args) {
/* Creating the frame */
JFrame frame = new JFrame();
frame.setTitle("Ping Pong!");
frame.setSize(600, 600);
frame.setBounds(0, 0, 600, 600);
frame.getContentPane().setBackground(Color.darkGray);
frame.add(new PingPong());
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
You have to use the ball class in your main method. There isn't an instantiated ball object inside any method, only an instance of the Ball class inside the Pong class.
You also never paint the method in the frame created in the main method.
I've made a JFrame, and added a JPanel to it. I am trying to paint the window completely black, and it isn't working! Thank you in advance.
This is my Main class!
package com.lootdatdungeon.net;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args){
initWindow();
}
public static void initWindow(){
Window window = new Window();
Thread windowThread = new Thread(window);
windowThread.start();
}
}
Okay, and here is my Window class!
package com.lootdatdungeon.net;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 240;
private static final int WIDTH = 320;
private static final int SCALE = 2;
private BufferedImage image;
private Graphics2D g;
private boolean running = true;
public Window(){
System.out.println("Window object made");
JFrame frame = new JFrame("Loot dat dungeon");
JPanel panel = new JPanel();
frame.setSize(WIDTH*SCALE,HEIGHT*SCALE);
frame.setVisible(true);
frame.setResizable(false);
frame.add(panel);
image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
}
public void Draw(Graphics g){
System.out.println("Draw method ran");
g.setColor(Color.BLACK);
g.drawRect(0, 0, WIDTH, HEIGHT);
}
#Override
public void run() {
while(running){
Draw(g);
}
}
}
Simply do in this way using overriiden paintComponent() method of JPanel
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
// don't forget to call it
super.paintComponent(g);
// set color
g.setColor(Color.BLACK);
// fill a rect that cover whole panel with specified color
g.fillRect(0, 0, getWidth(), getHeight());
}
};
Note: There is no need of Thread and BufferedImage in this case.
You should give this a read http://www.gametutorial.net/article/Java-game-framework
That site has a lot of good info if you want to create games. That's there I started.
I'm trying to make a simple GUI using JAVA
no image is shown
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;
public class EmiloLadderSnack {
public JFrame frame=new JFrame("EmiloLadderSnack");
public Image img;
public Graphics g;
public EmiloLadderSnack()
{
frame.setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
try
{
img= ImageIO.read(new File("/media/01CCE00FA6888D80/Achieve/Eclipse/EmiloLadderSnack/src/photo.jpg"));
g.drawImage(img, 50, 50, null);
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
public static void main(String args[])
{
new EmiloLadderSnack();
}
}
please help me to show an image in my simple GUI using JAVA
I'm using Eclipse
Hovercraft Full Of Eels is right, as he/she usually is. It really did not look like you tried.
Look at the tutorials, but I do believe when Hovercraft Full Of Eels says the correct way, hover means as follows.
Let me explain what I did below. First I created a new class that extended the JFrame. The JFrame is what is suppose to hold all of the components in a window. Then draw on the JPanel so that all of your drawings are contained in a lightweight container. I set the layout with a new layout I just discovered due to StackOverflow which I am very thankful for. The layout is called the MigLayout and it is a third party resource. You have to download it and import it. Please note that you do not have to have the MigLayout, but it is preferable to use due to its ease of use. After I set the Layout Constraint to fill and docked the JPanel in the center I created a new class which extended the JPanel so that I could change the paint method. The #Override lets you, in a way, re create the method for that extended class. As you can see once draw to that one graphics class then you are all set. There is a lot more you should read up on. Read the comments below your post, they suggest fairly good material.
Anything I get wrong Hovercraft will say below in the comments. So look for that as well.
Hovers corrections:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GraphicExample extends JPanel {
private static final String IMG_FILE_PATH = "/media/01CCE00FA6888D80/" +
"Achieve/Eclipse/EmiloLadderSnack/src/photo.jpg";
private BufferedImage img;
public GraphicExample(BufferedImage img) {
this.img = img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (img != null) {
return new Dimension(img.getWidth(), img.getHeight());
}
return super.getPreferredSize();
}
private static void createAndShowGui() {
try {
BufferedImage img = ImageIO.read(new File(IMG_FILE_PATH));
JFrame frame = new JFrame("GraphicExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GraphicExample(img));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// the easy way to display an image -- in a JLabel:
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(frame, label);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
My initial recommendations:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class DrawCircle extends JFrame {
JPanel panel;
public DrawCircle(String title, int width, int height) {
this.setTitle(title);
this.setSize(width, height);
this.setLocationRelativeTo(null); // Center JFrame
this.setLayout(new MigLayout("fill")); // Download external jar
this.panel = new DrawOval();
this.add(panel, "dock center"); // Link: http://www.miglayout.com/
this.setVisible(true);
}
public class DrawOval extends JPanel {
Color color = new Color(1, 1, 1);
public DrawOval() {
}
#Override
public void paint(Graphics g) {
g.setColor(color.RED);
g.fillOval(0, 0, this.getWidth(), this.getHeight());
}
}
}
I can't imagine that this is compiling. There must be a NullPointerException.
When you want to draw something you usually subclass JPanel and do the drawing in the paintComponent() method, like this:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 50, 50, null);
}