I made a simple draw rectangle application with JFrame and JPanel
Graphics2D g2d = (Graphics2D)jPanel1.getGraphics();
g2d.setColor(Color.red);
g2d.drawRect(x,y,w,h);
Whenever I draw something and click on menu, the overlapped part disappears
How to fix it?
As I already said in my comment, never use jPanel1.getGraphics(), but overridie the method paintComponent instead. This method will always be called when panel is repainted. Here is a small example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
/**
* <code>PaintExample</code>.
*/
public class PaintExample extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// correct approach
g.setColor(Color.RED);
g.fillRect(20, 20, Math.max(getWidth() - 200, 0), Math.max(getHeight() - 100, 0));
}
#Override
public Dimension getPreferredSize() {
// required for correct work of JFrame.pack method
return new Dimension(500, 400);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(PaintExample::createAndShowGUI);
}
private static void createAndShowGUI() {
JFrame frm = new JFrame();
JMenuBar menuBar = new JMenuBar();
JMenu m = new JMenu("File");
m.add("Test menu item 1");
m.add("Test menu item 2");
m.add("Test menu item 3");
menuBar.add(m);
frm.setJMenuBar(menuBar);
frm.add(new PaintExample());
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.pack();
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
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);
}
}
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.
I am currently making a version of the board-game Khet and was planning on displaying the laser fired between turns using a Glass Pane, but for the life of me I can't get the drawings to show up at all. To save posting all of the code for the game I've posted the code only related to the glass pane as it's own separate application below. Can anyone tell me why the graphics aren't showing up?
package glasspane;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Line2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GlassPane {
JPanel panel, glass;
GlassPane() {
JFrame f = new JFrame("GlassPane");
panel = new JPanel();
JButton show = new JButton("Show glass");
JButton hide = new JButton("Hide glass");
show.addActionListener(e -> changeVisibility());
hide.addActionListener(e -> changeVisibility());
panel.add(show);
panel.add(hide);
glass = (JPanel) f.getGlassPane();
glass.add(new line());
glass.setVisible(false);
f.add(panel);
f.setSize(300, 300);
f.setVisible(true);
}
private void changeVisibility() {
glass.setVisible(!glass.isVisible());
panel.repaint();
}
#SuppressWarnings("serial")
private class line extends JComponent {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Shape s = new Line2D.Float(0, 0, 300, 300);
g2.setColor(Color.GREEN);
g2.setStroke(new BasicStroke(20));
g2.draw(s);
System.out.println("doing something...");
}
}
public static void main(String[] args) {
new GlassPane();
}
}
Your line Component has zero size. Thats because JFrame.getGlassPane() returns a java.awt.Component that has no default layoutManager. So set a layoutManager for your glassPane should solve your problem.
glass = (JPanel) f.getGlassPane();
glass.setLayout(new BorderLayout());
glass.add(new line(), BorderLayout.CENTER);
glass.setVisible(false);
Now your line Compnent should be as big as glassPane
I did this and the line get showed up:
glass = (JPanel) f.getGlassPane();
glass.setLayout(new BorderLayout());
glass.add(new line());
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'm uploading the aller font in java with the following code:
private Font loadFont(final String path) {
Font font = null;
InputStream fontFile = null;
fontFile = FontLoaderClass.class.getResourceAsStream(path);
if (fontFile != null) {
try {
font = Font.createFont(Font.PLAIN, fontFile);
} catch (FontFormatException e) {
LOGGER.error("Error with font format {}", e);
} catch (IOException e) {
LOGGER.error("Error accessing font {}", e);
}
}
return font;
}
The font is loaded correctly:
http://www.fontsquirrel.com/fonts/Aller
the font is set to all ".font" changing the default settings for java application, but in Linux is shown correctly but Windows isn't.
private Font buildFont(final String key, final int size) {
Font f = loadFont(ALLER_LT_FONT_PATH);
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(f);
if (f == null) {
f = (Font) UIManager.get(key);
}
f = f.deriveFont(Font.TRUETYPE_FONT, size);
return f;
}
Linux shows:
Windows shows:
As you can see in the images, there is some cut off in Windows that causes the image not to be shown correctly.
Has anyone experienced with this issue before?
find two small demos attached, wich enables antialiasing for Swing components respectivly for draw operations.
for Swing components
// to enable antialiasing (AA) for Swing components
//
// either:
// start the JVM with the option -Dawt.useSystemAAFontSettings=on
// see also: http://docs.oracle.com/javase/6/docs/technotes/guides/2d/flags.html#aaFonts
// or:
// System.setProperty("awt.useSystemAAFontSettings", "on");
// - you must call it before the first Swing component is rendered
// - if AA it's on by default you must set it "off", otherwise you can't
// toggle it inside the application
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import static java.awt.RenderingHints.KEY_ANTIALIASING;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_OFF;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
public class SwingAntiAliasingDemo {
public static void main(String[] args) {
System.setProperty("awt.useSystemAAFontSettings", "off");
initGui();
}
public static void initGui() {
JFrame frame = new JFrame();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
Font font = new Font("Serif", Font.TRUETYPE_FONT, 96);
JPanel jpanel = new JPanel(new BorderLayout());
JLabel labelAA = new JLabel("Antialiasing ON") {
#Override
public void paintComponent(Graphics g) {
Graphics2D graphics2d = (Graphics2D) g;
graphics2d.setRenderingHint(KEY_ANTIALIASING,
VALUE_ANTIALIAS_ON);
super.paintComponent(g);
}
};
labelAA.setFont(font);
labelAA.setForeground(Color.WHITE);
JLabel labelNoAA = new JLabel("Antialiasing OFF") {
#Override
public void paintComponent(Graphics g) {
Graphics2D graphics2d = (Graphics2D) g;
graphics2d.setRenderingHint(KEY_ANTIALIASING,
VALUE_ANTIALIAS_OFF);
super.paintComponent(g);
}
};
labelNoAA.setFont(font);
labelNoAA.setForeground(Color.WHITE);
jpanel.setBackground(new Color(0, 22, 95));
jpanel.add(labelAA, BorderLayout.NORTH);
jpanel.add(labelNoAA, BorderLayout.SOUTH);
frame.setTitle("stackoverflow question 16304254");
frame.getContentPane().add(jpanel);
frame.setLocation(200, 200);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
for draw operations
// to enable antialiasing (AA) for draw operations
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import static java.awt.RenderingHints.KEY_ANTIALIASING;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_OFF;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
public class DrawAntiAliasingDemo extends JFrame {
private Font font;
private Color backGroundColor;
public static void main(String[] args) {
new DrawAntiAliasingDemo();
}
public DrawAntiAliasingDemo() {
font = new Font("Serif", Font.TRUETYPE_FONT, 96);
backGroundColor = new Color(0, 22, 95);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
setTitle("stackoverflow question 16304254");
setSize(850, 260);
setResizable(false);
setVisible(true);
}
#Override
public void paint(Graphics g) {
Graphics2D d = (Graphics2D) g;
d.setColor(backGroundColor);
d.fillRect(0, 0, getWidth(), getHeight());
d.setFont(font);
d.setPaint(Color.white);
d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
d.drawString("Antialiasing ON", 10, 115);
d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF);
d.drawString("Antialiasing OFF", 10, 230);
}
}
cheers
Frank
It seems to me that Windows OS isn't using ClearType. ClearType is an option, when enabled it smoothes the fonts. Sometimes it is disabled for tuning or performance reasons. See http://support.microsoft.com/kb/306527. Try to enable it.
To use ClearType for screen fonts:
Click Start, click Control Panel, click Appearance and Themes, and
then click Display.
On the Appearance tab, click Effects.
Click to select the Use the following method to smooth edges of screen fonts check box, and then click ClearType in the list.
I have faced a similar issue before till I found this library in SourceForge which is called Smooth Metal you can download it from Here
Library Home Smooth Metal
The Smooth Metal look and feel is an addition to some of the look and feels including with Java, enhancing them with anti-aliased text.
You would notice that ClearType option in Windows will not affect the Result...
After adding the jar file of the library in the class path I wrote this small java app that renders the JLabel and undo rendering with two JButtons the results were crystal clear:
Here is the code which you can test:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.plaf.basic.BasicLabelUI;
import smoothmetal.SmoothLabelUI; // UI Class to set for the JLabel
public class LabelRender extends JFrame{
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
JButton button = new JButton("RENDER");
JButton button2 = new JButton("UNDO");
JLabel label = new JLabel("HELLO WORLD");
public LabelRender(){
setSize(600, 250);
setLocationRelativeTo(null);
setTitle("JLabel Renderer");
setLayout(new BorderLayout());
label.setFont(new Font("Aller", Font.PLAIN, 70));
label.setForeground(Color.WHITE);
panel.add(label);
panel2.add(button);
panel2.add(button2);
panel.setBackground(Color.BLACK);
this.add(panel2, BorderLayout.NORTH );
this.add(panel,BorderLayout.CENTER);
setVisible(true);
validate();
// System.out.println(label.getUI());
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setUI(new SmoothLabelUI());
}
});
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setUI(new BasicLabelUI());
}
});
}
public static void main(String args[]){
new LabelRender();
}
}