I'm trying to draw a Rectangle to the center of a JPanel. I have made this code but when I run it, the rectangle does not appears in the panel. If I try with JFrame, the rectangle appears. Can someone help me?
RectangleTester
package eventi5;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class RectangleTester {
public static void main(String[] args) {
JFrame frame = new JFrame("Rectangle");
frame.setSize(250, 250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final RectangleComponent component = new RectangleComponent();
frame.setVisible(true);
JPanel panel=new JPanel();
panel.add(component);
frame.add(panel);
}
}
RectangleComponent
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class RectangleComponent extends JPanel{
private Rectangle box;
public RectangleComponent(){
box=new Rectangle(10,20,30,40);
}
public void paintComponent(Graphics g){
Graphics2D g2=(Graphics2D) g;
g2.draw(box);
g2.setColor(Color.BLUE);
g2.fill(box);
}
}
1) You need override getPreferredSize() of RectangleComponent like next:
#Override
public Dimension getPreferredSize() {
return new Dimension(box.width+box.x*2,box.height+box.y*2);
}
2) call super() method of paintComponent()( super.paintComponent(g);) before your customizations.
EDIT:
public class RectangleComponent extends JPanel {
private List<Rectangle> boxes;
private int width = 30;
private int height = 40;
private int startX = 10;
private int startY = 20;
public RectangleComponent() {
boxes = new ArrayList<Rectangle>();
for (int i = 0; i < 3; i++){
boxes.add(new Rectangle(startX+(width+startX)*i, startY, width, height));
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < boxes.size(); i++){
g2.draw(boxes.get(i));
}
g2.setColor(Color.BLUE);
for (int i = 0; i < boxes.size(); i++){
g2.fill(boxes.get(i));
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(boxes.size()*(width+startX)+startX, height+startY*2);
}
}
Related
I had to implement a JFrame with the size of 500 x 500 pixels that should have a 9 x 9 "field" of circles, but as you can see in the picture the distance between the first line of ovals and the second line of ovals is not equal.
The diameter should be 20 pixel and the distance between the center of one oval to another oval should be 40 pixel, but I don't know if I did this correctly:
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Color;
public class KreisFrame extends JFrame {
public KreisFrame() {
//Set JFrame size
setSize(500,500);
//Make JFrame visible
setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 500, 500);
for (int j = 0; j < 500; j += 60){
for (int i = 0; i < 500; i += 60) {
// draw circle
g.drawOval(i, 20, 20, 20);
g.drawOval(i, j, 20, 20);
// fill circle
g.fillOval(i, 20, 20, 20);
g.fillOval(i, j, 20, 20);
g.setColor(Color.BLUE);
}
}
}
public static void main(String[]args) {
KreisFrame myframe = new KreisFrame();
}
}
Can someone tell me what I did wrong?
You should really subclass a JPanel, not the JFrame. And all of this should be done on the EventDispatchThread, not the main thread. Further, don't use "magic" numbers like 500, 20, and 40. Here's a solution that paints the entire panel, regardless of what size it is (note that there is no provision here for having a border on the panel).
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Kreis extends JPanel {
protected int dia = 20;
protected int sep = 40;
public Kreis() {
// Set JFrame size
setPreferredSize(new Dimension(500, 500));
setBackground(Color.green);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension d = getSize();
g.setColor(Color.BLUE);
for (int y = 0; y < d.height; y += sep) {
for (int x = 0; x < d.width; x += sep) {
// draw circle
g.fillOval(x, y, dia, dia);
}
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Create and set up the window.
JFrame jf = new JFrame();
Kreis panel = new Kreis();
jf.add(panel);
jf.pack();
jf.setVisible(true);
jf.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing( WindowEvent arg0) {
System.exit(0);
}
});
}
});
}
}
The Problem is I make a class that extends JPanel with gradient Color background but the problem is when I am getting the background of it to use it to other component is I cannot get the color of it. I want to set the background color of components same to other components
I had tried to use .getBackground(); But it doesn't work on it. what should I do so that I can get the background of it?
import javax.swing.*;
import java.awt.*;
public class GradientPaintDemo extends JPanel {
private static final int scale = 2;
private static final Color c1 = Color.decode("#00F260");
private static final Color c2 = Color.decode("#0575E6");
private static final int size = (c2.getRed() - c1.getRed()) * scale;
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(20, 0, c1, 20, h, c2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
}
then when in my Main Class
GradientPaintDemo gpd = new GradientPaintDemo();
JPanel panel1 = new JPanel();
gpd.add(panel1);
panel.getBackground();
I want that to have only one background on all of my panels and buttons I want to look like this image below
At a "guess" I would say you need to make the child component transparent, using panel1.setOpaque(false), so the parent will show through it.
Also, at a "guess", the use of size in your getPreferredSize method could be causing you issues. Instead, I'd set the component's default layout manager to BorderLayout and let the child dictate the required size.
For example, opaque...
Transparent...
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() throws HeadlessException {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
GradientPaintDemo gpd = new GradientPaintDemo();
gpd.setBorder(new EmptyBorder(20, 20, 20, 20));
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(20, 20, 20, 20));
panel.add(new JLabel("This is a test"));
panel.setOpaque(false);
gpd.add(panel);
frame.add(gpd);
frame.pack();
frame.setVisible(true);
}
});
}
public static class GradientPaintDemo extends JPanel {
private static final int scale = 2;
private static final Color c1 = Color.decode("#00F260");
private static final Color c2 = Color.decode("#0575E6");
private static final int size = (c2.getRed() - c1.getRed()) * scale;
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(20, 0, c1, 20, h, c2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
}
}
}
I've read a lot of tutorials on drawing Graphics2D components and adding to JPanel/JFrame but I can't find how to add multiple these components into one JPanel simply. My code below adds only 1 component (line) and I can't find why it isn't possible to add more.
What am I doing wrong?
Desired behaviour: there should be 3 red lines.
My whole code:
package Examples;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example1 extends JFrame {
private final JPanel panel;
public Example1() {
// jpanel with graphics
panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.setBackground(Color.WHITE);
add(panel);
// adding lines to jpanel
AddMyLine(); // 1st: this works well
AddMyLine(); // 2nd: this doesn't work
AddMyLine(); // 3rd: this doesn't work
setLayout(new FlowLayout(FlowLayout.LEFT));
setSize(250, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);
}
// add new line to jpanel
private void AddMyLine() {
MyLine c = new MyLine();
System.out.println(c);
panel.add(c);
}
// line component
private class MyLine extends JComponent {
public MyLine() {
setPreferredSize(new Dimension(200, 200));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(1));
int x1 = (int)Math.round(Math.random()*200);
int y1 = (int)Math.round(Math.random()*200);
int x2 = (int)Math.round(Math.random()*200);
int y2 = (int)Math.round(Math.random()*200);
g2d.drawLine(x1,y1,x2,y2);
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example1();
}
});
}
}
Your MyLine class should not be a Swing component and thus should not extend JComponent. Rather it should be a logical entity, and in fact can be something that implements Shape such as a Line2D, or could be your own complete class, but should know how to draw itself, i.e., if it does not implement Shape, then it should have some type of draw(Graphics2D g) method that other classes can call. I think instead you should work on extending your panel's JPanel class, such that you override its paintComponent method, give it a collection to hold any MyLine items added to it, and draw the MyLine items within the paintComponent.
Other options include drawing directly on to a BufferedImage, and then displaying that BufferedImage in your JPanel's paintComponent method. This is great for static images, but not good for images that need to change or move.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class DrawChit extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private List<Shape> shapes = new ArrayList<>();
public DrawChit() {
setBackground(Color.white);
}
public void addShape(Shape shape) {
shapes.add(shape);
repaint();
}
#Override // make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Shape shape : shapes) {
g2.draw(shape);
}
}
private static void createAndShowGui() {
DrawChit drawChit = new DrawChit();
drawChit.addShape(new Line2D.Double(10, 10, 100, 100));
drawChit.addShape(new Ellipse2D.Double(120, 120, 200, 200));
JFrame frame = new JFrame("DrawChit");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(drawChit);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Or an example using my own MyDrawable class, which produces a GUI that looks like this:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class DrawChit extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private List<MyDrawable> drawables = new ArrayList<>();
public DrawChit() {
setBackground(Color.white);
}
public void addMyDrawable(MyDrawable myDrawable) {
drawables.add(myDrawable);
repaint();
}
#Override
// make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (MyDrawable myDrawable : drawables) {
myDrawable.draw(g2);
}
}
public void clearAll() {
drawables.clear();
repaint();
}
private static void createAndShowGui() {
final List<MyDrawable> myDrawables = new ArrayList<>();
myDrawables.add(new MyDrawable(new Line2D.Double(100, 40, 400, 400),
Color.red, new BasicStroke(40)));
myDrawables.add(new MyDrawable(new Ellipse2D.Double(50, 10, 400, 400),
Color.blue, new BasicStroke(18)));
myDrawables.add(new MyDrawable(new Rectangle2D.Double(40, 200, 300, 300),
Color.cyan, new BasicStroke(25)));
myDrawables.add(new MyDrawable(new RoundRectangle2D.Double(75, 75, 490, 450, 40, 40),
Color.green, new BasicStroke(12)));
final DrawChit drawChit = new DrawChit();
JFrame frame = new JFrame("DrawChit");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(drawChit);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
int timerDelay = 1000;
new Timer(timerDelay, new ActionListener() {
private int drawCount = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (drawCount >= myDrawables.size()) {
drawCount = 0;
drawChit.clearAll();
} else {
drawChit.addMyDrawable(myDrawables.get(drawCount));
drawCount++;
}
}
}).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyDrawable {
private Shape shape;
private Color color;
private Stroke stroke;
public MyDrawable(Shape shape, Color color, Stroke stroke) {
this.shape = shape;
this.color = color;
this.stroke = stroke;
}
public Shape getShape() {
return shape;
}
public Color getColor() {
return color;
}
public Stroke getStroke() {
return stroke;
}
public void draw(Graphics2D g2) {
Color oldColor = g2.getColor();
Stroke oldStroke = g2.getStroke();
g2.setColor(color);
g2.setStroke(stroke);
g2.draw(shape);
g2.setColor(oldColor);
g2.setStroke(oldStroke);
}
public void fill(Graphics2D g2) {
Color oldColor = g2.getColor();
Stroke oldStroke = g2.getStroke();
g2.setColor(color);
g2.setStroke(stroke);
g2.fill(shape);
g2.setColor(oldColor);
g2.setStroke(oldStroke);
}
}
You shouldn't be drawing lines by adding components. Components are things like panels, buttons etc.
See this tutorial on how to draw with Graphics2D: https://docs.oracle.com/javase/tutorial/2d/geometry/primitives.html
Your code adds three components but the panel is not big enough to show the other two components
panel.setPreferredSize(new Dimension(200, 600));
setSize(250, 800);
I am unable to draw line when I press the component in Java Swing. How can I do this? I already used paint method, my problem is when program executes paint method invoke automatically, DrawLine() method will be there in paint method, so is there any way that I can get the lines other than paint method?
Please give some suggestion.
Below code I have tried, it's displaying lines but I want to display the lines when I click the component.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class ReferenceLink1 extends JFrame
{
JLabel l1;
JLabel l2;
JPanel p1;
ReferenceLink1()
{
p1 = new JPanel();
p1.setLayout(null);
p1.setBackground(Color.ORANGE);
p1.setOpaque(true);
p1.setBounds(0,0,300,400);
setLayout(null);
l1 = new JLabel();
l1.setText("l1");
l1.setBounds(20, 40, 100, 40);
l1.setHorizontalAlignment(SwingConstants.CENTER);
l1.setBackground(Color.GREEN);
l1.setOpaque(true);
l2 = new JLabel(); ;
l2.setText("l2");
l2.setBounds(20, 100,100,40);
l2.setBackground(Color.BLUE);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setOpaque(true);
p1.add(l1);
p1.add(l2);
add(p1);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBounds(0,0,400,400);
}
public void paint(Graphics g)
{
super.paint(g);
g.drawLine(77,110,77,130);
}
public static void main(String args[])
{
ReferenceLink1 rf = new ReferenceLink1();
}
}
class Surface extends JPanel {
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.blue);
Dimension size = getSize();
Insets insets = getInsets();
int w = size.width - insets.left - insets.right;
int h = size.height - insets.top - insets.bottom;
Random r = new Random();
for (int i = 0; i < 1000; i++) {
int x = Math.abs(r.nextInt()) % w;
int y = Math.abs(r.nextInt()) % h;
g2d.drawLine(x, y, x, y);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class Points extends JFrame {
public Points() {
initUI();
}
private void initUI() {
setTitle("Points");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new Surface());
setSize(350, 250);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Points ps = new Points();
ps.setVisible(true);
}
});
}
}
You could simply add a mouse listener to the label that represents your button.
l2.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
p1.getGraphics().drawLine(77,110,77,130);
}
});
public class ReferenceLink1 extends JFrame {
JLabel l1;
JButton l2;
JPanel p1;
public static class MyListener implements ActionListener{
Graphics g;
public MyListener(Graphics g) {
this.g = g;
}
#Override
public void actionPerformed(ActionEvent e) {
g.drawLine(77, 110, 77, 130);
}
}
public ReferenceLink1() {
p1 = new JPanel();
setVisible(true);
p1.setLayout(null);
p1.setBackground(Color.ORANGE);
p1.setOpaque(true);
p1.setBounds(0,0,300,400);
setLayout(null);
l1 = new JLabel();
l1.setText("l1");
l1.setBounds(20, 40, 100, 40);
l1.setHorizontalAlignment(SwingConstants.CENTER);
l1.setBackground(Color.GREEN);
l1.setOpaque(true);
l2 = new JButton();
l2.addActionListener(new MyListener(this.getGraphics()));
l2.setText("l2");
l2.setBounds(20, 100,100,40);
l2.setBackground(Color.BLUE);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setOpaque(true);
p1.add(l1);
p1.add(l2);
add(p1);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0,0,400,400);
}
public static void main(String args[]) {
ReferenceLink1 rf = new ReferenceLink1();
}
}
I managed it to create a JPanel with a special picture as Background and put this JPanel in a JFrame.
Everytime a resize the JFrame the JPanel and the picture in it with be also resized. The ComponentListener is registered to the JFrame which notifies modifications in its size.
Here's the code:
package examples;
import images.MyImage;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class example3 {
private static JPanel panel = new MyPanel();
private static JFrame frame = new JFrame();
private static class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
private int width = 0;
private int height = 0;
public static final int DEFAULT_WIDTH = 400;
public static final int DEFAULT_HEIGHT = 100;
public MyPanel(int width, int heigth) {
super.setLayout(new BorderLayout());
setWidth(width);
setHeigth(heigth);
}
public MyPanel() {
super.setLayout(new BorderLayout());
setWidth(DEFAULT_WIDTH);
setHeigth(DEFAULT_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(MyImage.IMAGE_BLUE_BLACKGROUND, 0, 0,
getMyPanelWidth(), getMyPanelHeight(), null);
g2d.dispose();
}
#Override
public Dimension preferredSize() {
return new Dimension(getMyPanelWidth(), getMyPanelHeight());
}
private void setWidth(int width) {
this.width = width;
}
private void setHeigth(int height) {
this.height = height;
}
private int getMyPanelHeight() {
return height;
}
private int getMyPanelWidth() {
return width;
}
}
private static class ComponentHandler extends ComponentAdapter{
#Override
public void componentResized(ComponentEvent e) {
super.componentResized(e);
frame.remove(panel);
frame.getContentPane().add(
new MyPanel(frame.getSize().width, frame.getSize().height),
BorderLayout.CENTER);
frame.repaint();
frame.revalidate();
}
}
public static void main(String[] args) {
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(panel);
frame.addComponentListener(new ComponentHandler());
frame.pack();
frame.setVisible(true);
}
}
The problem is that I'm getting scaling errors:
Is it because the Event Dispatch Thread can not handle all the resize-Events which is fired by the resize-method? Is there any satisfying solution?