I am trying to understand why the following short piece code does not work.
I understand that when there are no Layout or the size of the component is 0, the paint component method isn't called.
But this isn't the case here.
Can you explain why I can't set the background for this?
public class Login extends JPanel {
private BufferedImage bgImage;
public Login() {
super();
initImages();
setLayout(new BorderLayout());
setPreferredSize(new Dimension(600, 600));
add(new JLabel("Hi"), BorderLayout.CENTER);
}
private void initImages() {
try {
bgImage = ImageIO.read(new File("images/login.jpg"));
System.out.println("image loaded");
} catch (IOException e) {
e.printStackTrace();
System.out.println("image not loaded");
}
}
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
g.drawImage(bgImage, 0, 0, null);
System.out.println("repaint");
}
public static void createAndShowGui() {
JFrame frame = new JFrame();
Login login = new Login();
frame.add(login, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
If you want this to work, then you will need to change...
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
g.drawImage(bgImage, 0, 0, null);
System.out.println("repaint");
}
to something more like...
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bgImage, 0, 0, this);
}
paintComponent is responsible for painting the "bottom" layer of the component, paintComponents is responsible for painting the children
Related
I have two classes that extend JPanel: MapPanel and CityPanel. I am trying to draw a CityPanel into a MapPanel but nothing appears. I do not understand why if I add a JButton in the same way it will be displayed perfectly.
Here's the code:
public class PanelMap extends JPanel {
public PanelMap() {
CityPanel city = new CityPanel();
city.setVisible(true);
this.add(city);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
public class CityPanel extends JPanel {
private BufferedImage image;
public CityPanel() {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Test", 0, 0); }
}
EDIT:
I have this code in CityMap. It display the string but no the image.
public CityPanel(String filePath, int red, int green, int blue) {
this.image = colorImage(filePath, red, green, blue);
this.setSize(100, 100);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 50, 50, null);
g.drawString("sdjkfpod", 50, 50);
}
Could you please replace your following constructor of PanelMap.java:
public PanelMap() {
CityPanel city = new CityPanel();
city.setVisible(true);
this.add(city);
}
By following constructor:
public PanelMap() {
String filePath = "C:\\...\\city2.png";
CityPanel city = new CityPanel(filePath, 0, 255, 255);
this.setLayout(new BorderLayout());
this.add(city, BorderLayout.CENTER);
}
and see the result?
Following changes have been made to your code:
The statement city.setVisible(true); is removed since it is not
required at all.
The statement this.add(city); was indeed adding CityPanel to
PanelMap but CityPanel took up very small space and looked as a
very small rectangle. This is the reason the BorderLayout has been
used.
Following PanelMapDemo.java adds PanelMap to a JFrame and creates an executable example.
public class PanelMapDemo extends javax.swing.JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
PanelMapDemo demoFrame = new PanelMapDemo("PanelMapDemo");
demoFrame.setVisible(true);
}
});
}
public PanelMapDemo(String title) {
super(title);
setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
add(new PanelMap());
setSize(new java.awt.Dimension(400, 200));
setLocationRelativeTo(null);
}
}
On my system when the original picture was:
Your MapPanel changes the picture to:
Hope, this helps.
Simple problem for Swing regular costumers.
The idea is to load an image and use it as a background of a JPanel through a JComponent object. It seems to load just fine as the image information from toString() method is loading properly and the paintComponent() method is running, but for some reason it is not rendering correctly inside the JFrame leading to an empty frame. Here's the code:
RicochetFrame.java
public class RicochetFrame extends JFrame {
RicochetStartPanel startPanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
RicochetFrame window = new RicochetFrame();
window.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public RicochetFrame() throws IOException {
startPanel = new RicochetStartPanel();
this.getContentPane().add(startPanel);
this.setBounds(0, 0, 500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//this.pack();
this.setVisible(true);
}
}
RicochetStartPanel.java
public class RicochetStartPanel extends JPanel {
RicochetStartPanel() throws IOException {
BufferedImage myImage = ImageIO.read(new File("frame_bg.jpg"));
this.add(new RicochetImagePanel(myImage));
this.setVisible(true);
this.validate();
this.repaint();
}
}
RicochetImagePanel.Java
public class RicochetImagePanel extends JComponent {
private Image image;
public RicochetImagePanel(Image image) {
this.setVisible(true);
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
Your RicochetImagePanel is sizing itself to its preferred size => [0, 0]. Override its getPreferredSize() to return the dimensions of the image (if not null). Better still, why not simply display the image as an ImageIcon in a JLabel?
I tried to make game with 2 panel stack each other, first panel is for canvas where all tiles and all game object is drawing on it and the second one is for the top layer frame where I have png image with transparency for the background and will contain JTextBox, JTabbedPanel and JLabel
My problems is when i repaint the canvas, part of the top frame becoming covered by a canvas.
Why is that? and also when i add JButton on canvas, the JButton is draw on top of my top frame panel.
Edit:
I have tried using JLayeredPane but still give me same result.
// initComponent from MyGame
private void initComponent() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("My Game");
this.setSize(320, 240);
this.setLayout(null);
this.setUndecorated(true);
this.setResizable(false);
JLayeredPane layered = this.getLayeredPane();
layered.add(new Canvas(), 0);
layered.add(new TopFrame(), 1);
}
This top frame and my canvas:
What I get | what I want
Main
#SuppressWarnings("serial")
public class MyGame extends JFrame {
public MyGame() {
this.initComponent();
}
private void initComponent() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("My Game");
this.setSize(320, 240);
this.setLayout(null);
this.setUndecorated(true);
this.setResizable(false);
this.add(new TopFrame());
this.add(new Canvas());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame game = new MyGame();
game.setVisible(true);
}
});
}
}
TopFrame
#SuppressWarnings("serial")
public class TopFrame extends JPanel {
private static final int FRAME_WIDTH = 320;
private static final int FRAME_HEIGHT = 240;
private BufferedImage bgImage;
public TopFrame() {
this.initComponent();
}
private void initComponent() {
this.setLayout(null);
this.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
bgImage = new BufferedImage(FRAME_WIDTH, FRAME_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR_PRE);
try {
bgImage = ImageIO.read(new File("FRAME.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bgImage, 0, 0, this);
}
}
Canvas
#SuppressWarnings("serial")
public class Canvas extends JPanel {
private static final int CANVAS_WIDTH = 227;
private static final int CANVAS_HEIGHT = 240;
BufferedImage image;
BufferedImage imgBuffer;
Graphics2D g2d;
public Canvas() {
this.initComponent();
}
private void initComponent() {
Timer timer = new Timer();
this.setBounds(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
imgBuffer = new BufferedImage(CANVAS_WIDTH, CANVAS_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR_PRE);
g2d = imgBuffer.createGraphics();
try {
image = ImageIO.read(new File("tile.png"));
} catch (IOException e) {
e.printStackTrace();
}
timer.schedule(new TimerTask(){
#Override
public void run() {
drawComponent();
repaint();
}
}, 0, 100);
}
public void drawComponent() {
/* will do tile drawing */
g2d.drawImage(image, 0, 0, this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(imgBuffer, 0, 0, this);
}
}
Is it possible to get my canvas with all contained object drawn at the bottom?
[Solved] using JLayeredPane and make TopFrame setOpaque(false);
I have wrong code when try using JLayeredPane.
My final code working code now:
Main
#SuppressWarnings("serial")
public class MyGame extends JFrame {
public MyGame() {
this.initComponent();
}
private void initComponent() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("My Game");
this.setSize(320, 240);
this.setLayout(null);
this.setUndecorated(true);
this.setResizable(false);
JLayeredPane layered = this.getLayeredPane();
layered.add(new Canvas(), new Integer(0));
layered.add(new TopFrame(), new Integer(1));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame game = new MyGame();
game.setVisible(true);
}
});
}
}
TopFrame
#SuppressWarnings("serial")
public class TopFrame extends JPanel {
private static final int FRAME_WIDTH = 320;
private static final int FRAME_HEIGHT = 240;
private BufferedImage bgImage;
public TopFrame() {
this.initComponent();
}
private void initComponent() {
this.setLayout(null);
this.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
this.setOpaque(false);
bgImage = new BufferedImage(FRAME_WIDTH, FRAME_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR_PRE);
try {
bgImage = ImageIO.read(new File("FRAME.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
// super.paintComponent(g);
g.drawImage(bgImage, 0, 0, this);
}
}
Canvas
#SuppressWarnings("serial")
public class Canvas extends JPanel {
private static final int CANVAS_WIDTH = 227;
private static final int CANVAS_HEIGHT = 240;
BufferedImage image;
BufferedImage imgBuffer;
Graphics2D g2d;
public Canvas() {
this.initComponent();
}
private void initComponent() {
Timer timer = new Timer();
this.setBounds(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
imgBuffer = new BufferedImage(CANVAS_WIDTH, CANVAS_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR_PRE);
g2d = imgBuffer.createGraphics();
try {
image = ImageIO.read(new File("tile.png"));
} catch (IOException e) {
e.printStackTrace();
}
timer.schedule(new TimerTask(){
#Override
public void run() {
drawComponent();
repaint();
}
}, 0, 100);
}
public void drawComponent() {
/* will do tile drawing */
g2d.drawImage(image, 0, 0, this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(imgBuffer, 0, 0, this);
}
}
I'm not that familiar with Java and I'm a little clueless about my current problem.
I'm trying to draw an Image within a separate class of my Main JFrame, but it
always draw just a little piece of the picture (maybe 10x10px).
(A test with a Label worked)
Maybe I didn't used the g.drawImage method correct, or the JPanel don't have enough space??
MainWindow:
public class Deconvolutioner extends JFrame {
Draw z;
Picturearea picturearea;
class Draw extends JPanel {
public void paint(Graphics g) {
}
}
public Deconvolutioner() {
setTitle("Deconvolutioner");
setLocation(30,1);
setSize(1300,735);
super.setFont(new Font("Arial",Font.BOLD,11));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flow = new FlowLayout(FlowLayout.CENTER);
this.setLayout(flow);
picturearea = new Picturearea();
this.add(picturearea);
add(z = new Draw());
setVisible(true);
}
class Open implements ActionListener {
public void actionPerformed(ActionEvent e) {
JFileChooser fileOpen = new JFileChooser();
FileFilter filter = new FileNameExtensionFilter("png & jpg files", "png",
"jpg");
fileOpen.addChoosableFileFilter(filter);
int returnVal = fileOpen.showDialog(null, "Open file");
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
String path = fileOpen.getSelectedFile().getPath();
URL url = new File(path).toURI().toURL();
BufferedImage img = ImageIO.read(url);
picturearea.setPicture(img);
} catch (IOException ex) {
System.err.println("Some IOException accured (set the right path?): ");
System.err.println(ex.getMessage());
}
} else {
}
repaint();
}
}
And the separate class:
public class Picturearea extends JPanel {
public BufferedImage image;
Draw z;
public Picturearea() {
add(z = new Draw());
setVisible(true);
}
class Draw extends JPanel {
#Override
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
}
public void setPicture(BufferedImage picture) {
try {
image = picture;
} catch (Exception e) {
System.err.println("Some IOException accured (did you set the right path?): ");
System.err.println(e.getMessage());
}
repaint();
}
}
I'm grateful for every help.
thanks for your time.
You are using FlowLayout for JFrame's contentPane's layout. FlowLayout obeys component's preferredSize. Try setting preferredSize of your pictureArea by pictureArea.setPreferredSize(Dimension) or overriding getPreferredSize(Dimension) function in PictureArea class.
you are using paint(Graphics g) for custom painting:
#Override
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
Do not override paint() for custom painting override paintComponent(Graphics g) instead. And You may need to scale your image to fit in the size of the JPanel. you can use g.drawImage(x, y, width, height, observer) function if you need to scale your image.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
I want to make a panel which extends JPanel and when it's going to be visible, it starts to get more transparent and more transparent and finally gets disappeared. what is the problem of my code?
public class BaloonPanel extends JPanel
{
private float transparency = 1f;
Timer timer;
public BaloonPanel()
{
setBackground(Color.white);
ActionListener action = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
transparency = transparency - 0.01f;
if (transparency < 0.0f)
{
timer.stop();
}
repaint();
}
};
timer = new Timer(100, action);
timer.start();
}
#Override
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
super.paint(g2);
g2.dispose();
}
}
Because the BallonPanel is opaque, the repaint manager isn't bothering to paint underneath it. This is an optimization of the paint process, why paint that which doesn't need to be painted.
You need to "persuade" the repaint manger to paint underneath your component, while still painting its background.
Set the BallonPanel to transparent (setOpaque(false)) and update the paint method to fill the background.
public class FadePane {
public static void main(String[] args) {
new FadePane();
}
public FadePane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.BLUE);
frame.setBackground(Color.BLUE);
frame.add(new BaloonPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BaloonPanel extends JPanel {
private float transparency = 1f;
Timer timer;
public BaloonPanel() {
setBackground(Color.white);
ActionListener action = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
transparency = transparency - 0.1f;
if (transparency < 0.1f) {
transparency = 0;
timer.stop();
}
invalidate();
repaint();
}
};
timer = new Timer(100, action);
timer.setRepeats(true);
setOpaque(false);
final JButton fade = new JButton("Fade");
fade.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
fade.setEnabled(false);
}
});
setLayout(new GridBagLayout());
add(fade);
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
System.out.println(transparency);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
super.paint(g2);
g2.dispose();
}
}
}