I tried to override method paintComponent in inner class JPanel and paint some picture. But if I load image in the constructor, method paintComponent is not calling. If load image in main class, everythig is fine. What is it? Here's the code, that does'nt work
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
JFrame window;
//Image image=new ImageIcon("D://domik.png").getImage();
class JPanelExt extends JPanel {
Image image;
public JPanelExt (){
image=new ImageIcon("D://domik.png").getImage();
System.out.println("constructor");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("paint");
g.drawImage(image, 0, 0, this);
g.drawRect(0, 400, 100, 100);
}
}
public Main(){
window=new JFrame("Flowers");
window.setSize(430, 480);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanelExt flower1 =new JPanelExt();
flower1.setBounds(100, 100, 200, 200);
flower1.setToolTipText("House");
window.setLayout(null);
window.add(flower1);
}
public static void main(String[] args) {
Main main=new Main();
}
}
And sysout writes only "constructor"
But if I change code this way
public class Main {
JFrame window;
Image image=new ImageIcon("D://domik.png").getImage();
class JPanelExt extends JPanel {
//Image image;
public JPanelExt (){
//image=new ImageIcon("D://domik.png").getImage();
System.out.println("constructor");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("paint");
g.drawImage(image, 0, 0, this);
g.drawRect(0, 400, 100, 100);
}
And sysout writes "constructor","paint"
I can't understand this ))
Your "problem" is the order of statements in the Main constructor.
First you are constructing a new frame. Second, you set it visible. At this point it is painted and also calls the paint methods on its associated panels. Also at this point, there is no associated panel. Third, you construct a new JPanelExt and add it to the frame. This will not cause the frame to be repainted.
Put the call
window.setVisible(true);
at the end of the construction process. Then you will see your image.
Related
So I am trying to create a simple program that prints out a rectangle but I am having this problem and I don't know how to fix it. Here is my code:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
public class GraphicsEditor extends JPanel{
public void drawShape(Graphics g) {
super.drawShape(g);
g.setColor(Color.BLUE);
g.drawRect(100, 100, 120, 150);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
GraphicsEditor ga = new GraphicsEditor();
frame.setSize(1280, 720);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ga);
}
}
The error is when I am trying to add the super in here:
public void drawShape(Graphics g) {
super.drawShape(g);
g.setColor(Color.BLUE);
g.drawRect(100, 100, 120, 150);
}
A JPanel has no drawShape(Graphics) method, so calling the 'super' method makes no sense. When you think you're overriding a method, be sure to add the #Override notation to get a compiler warning when the method is incorrectly spelled, uses the wrong arguments, or is just entirely non-existent (as is the case here).
The correct way to go about this is to override the paintComponent method, call the (existing) super method, then immediately call the drawShape method with the Graphics instance provided to the paintComponent method.
This is the result when the GUI is shrunk down:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
public class GraphicsEditor extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawShape(g);
}
// #Override // does NOT override an existing method!
public void drawShape(Graphics g) {
//super.drawShape(g);
g.setColor(Color.BLUE);
g.drawRect(100, 100, 120, 150);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
GraphicsEditor ga = new GraphicsEditor();
frame.setSize(280, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ga);
}
}
I have to draw an archery target with two black lines in the innermost circle that forms a cross, but every time i adjust the lines so that the lines are closer to the centre it goes behind the image instead of appearing on top. How can I stop this? Does it need to have a separate set of instructions entirely?
This is my code:
package sumshapes;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;
public class SumShapes extends JFrame
implements ActionListener {
private JPanel panel;
public void paint(Graphics g)
{
g.setColor(Color.BLACK);
g.drawLine(250, 200, 250, 200);
g.drawOval(140,90,200,200);
g.setColor(Color.BLACK);
g.fillOval(140,90,200,200);
g.drawOval(162,109,155,155);
g.setColor(Color.BLUE);
g.fillOval(162,109,155,155);
g.drawOval(183,129,112,112);
g.setColor(Color.RED);
g.fillOval(183, 129, 112, 112);
g.drawOval(210,153,60,60);
g.setColor(Color.YELLOW);
g.fillOval(210, 153, 60, 60);
g.setColor(Color.BLACK);
}
public static void main(String[] args) {
SumShapes frame = new SumShapes();
frame.setSize(500,400);
frame.setBackground(Color.yellow);
frame.createGUI();
frame.setVisible(true);
}
private void createGUI(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout (new FlowLayout());
}
public void actionPerformed(ActionEvent event) {
Graphics paper = panel.getGraphics();
paper.drawLine(20,80,120,80);
}
}
All your drawing should go into the paintComponent method of a lightweight component, such as a JPanel.
There should never be a need to call getGraphics. If you wish to change the drawing upon a particular action you should a) program the logic into paintComponent b) alter the logic in the Action c) call repaint on the Component
For example:
private JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);//call parent method first thing
//paint here
}
#Override
public Dimension getPreferredSize(){//provided so you can size this component as necessary
return new Dimension(500,400);
}
};
....
frame.add(panel);
frame.pack();
As an aside, I'd recommend placing all calls to to Swing components on the EDT - this means wrapping your Swing calls in the main method with SwingUtilities. eg
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable(){
#Override
public void run() {
SumShapes frame = new SumShapes();
....
}
});
}
public void paint(Graphics g){
g.setColor(Color.red);
g.drawString("hello",50,50);
}
the background of the frame looks strange and transparent.
This problem only happens when I draw a string, but when I draw a rectangle or any another shape, the frame looks good.
this is the code:
import javax.swing.*;
import java.awt.*;
public class B extends JFrame {
public B() {
this.setTitle("programme");
this.setSize(400, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.setVisible(true);
}
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawString("hello", 50, 50);
}
}
this is the result:
Thank you for helping .
I have found the answer.
The problem happened because I didn't pass the object (g) to the constructor in paint method
This is the whole code :
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JFrame;
class B extends JFrame {
public B() {
this.setTitle("programme");
this.setSize(400,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
// I have added the previous line and it solved the problem
g.setColor(Color.red);
g.drawString("hello", 50, 50);
}
}
public class main {
public static void main(String[] args) {
B obj = new B();
}
}
Anyway thank you for helping.
strange, at my place everythings works fine.
Try in constructor use:
super("programme");
instead setTitle("programme");
if doesn't work add
setBackground(Color.lightGray);
in constructor.
Anyway, when you want to paint String you should use JLabel class.
I have a JFrame. Within that JFrame I have a JLayeredPane layed out with an OverlayLayout that contains multiple Jpanels. in one of those JPanels I have a BufferedImage. When the JFrame is resized, the image quickly dissapears and dislocates, then it jumps back again, dislocates again, back again, and so on.
I have tried a lot of things to stop the image from flickering, but I don't know what the cause of the problem exactly is.
The Jpanel that holds the image contains the following code to render the image:
protected void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawImage(myBufferedImage, 0, 0, 200, 200, null);
}
In trying to reconstruct and simplify the problem, I got a working version of what I wanted. I still don't know what the problem is with my other code though.
This is the code that works:
import java.awt.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Main {
public Main() {
// Create the JFrame:
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(600, 400);
window.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
// Create the pane to hold layers:
JLayeredPane layers = new JLayeredPane();
layers.setLayout(new OverlayLayout(layers));
// Add two layers:
layers.add(new MyGraphics());
layers.add(new MyImage());
//
window.add(layers);
window.setVisible(true);
}
public static void main(String[] args) {
Main app = new Main();
}
public class MyImage extends JPanel {
public BufferedImage source;
public MyImage () {
this.setPreferredSize(new Dimension(180,180));
this.setLocation(0,0);
try {
this.source = ImageIO.read(new File("image.jpg"));
} catch (IOException ie) {
ie.printStackTrace();
}
}
protected void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawImage(this.source, 0, 0, 180, 180, null);
}
}
public class MyGraphics extends JPanel {
public MyGraphics () {
this.setOpaque(false);
this.setPreferredSize(new Dimension(180,180));
this.setLocation(0,0);
}
protected void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, 180, 180);
}
}
}
Try adding below line of code in constructor:
public FlickerDemo()
{
// No flickering during resize
System.setProperty("sun.awt.noerasebackground", "true");
}
I'm having issues with this code. For some reason, paintComponent(Graphics g) simply doesn't work and there doesn't seem to be an answer how to force it to. This is my code:
import javax.swing.JFrame;
public class Robotron extends JFrame
{
public Robotron ()
{
//add(this); This one gave me an error
setSize(800, 600);
new TestFrame();
setVisible(true);
}
public static void main(String [ ] args)
{
new Robotron();
}
and this is my TestFrame class that has the paintComponent function:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class TestFrame extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.YELLOW);
g.fillRect(100, 100, 10, 30);
System.out.println("Abdullah Paint");
}
public TestFrame()
{
setFocusable(true);
repaint();
}
}
What can I do in order to make paintComponent actually play. What I get in the end is just an empty JFrame, with no running of the System.out.println thingy.
Thanks a whole lot, been tackling this for a long time.
You're not adding anything to the JFrame, because of this
//add(this);
Here, you were trying to add the component to itself, which is not going to fly.
Instead, you need to add the TestFrame instance to the Frame.
add(new TestFrame());
setSize(800, 600);
setVisible(true);
You need to add the panel to the frame:
public Robotron ()
{
//add(this); This one gave me an error
setSize(800, 600);
add(new TestFrame());
setVisible(true);
}
As mentioned by others, you need to add the panel to the frame:
public Robotron() {
add(new TestFrame());
setSize(800, 600);
setVisible(true);
}
As not mentioned by others, you need to call super.paintComponent(g) the first thing in your overridden method:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.YELLOW);
g.fillRect(100, 100, 10, 30);
System.out.println("Abdullah Paint");
}
Notes:
Don't call repaint() in the constructor. At best it does nothing.
Don't call setSize(...) for the frame, instead call pack(). You will need to override the getPreferredSize method in your panel for this.