Two argument constructor to specify where the object should be drawn? - java

How would i make this into a two argument constructor that can be used to specify where to draw the object and/or scale the object.This is being used for a Jframe graphics project. I can post the Jframe too if it will help.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.JComponent;
import java.awt.GradientPaint;
/*
component that draws the concert speakers
*/
public class ConcertSpeaker extends JComponent
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
// Speaker base
g2.setColor(Color.BLACK);
Rectangle base = new Rectangle (300, 400, 50, 100);
g2.fill(base);
// Speakers circles gray top
g2.setColor(Color.DARK_GRAY);
Ellipse2D.Double speakerTop = new Ellipse2D.Double(310, 410, 30, 30);
g2.fill(speakerTop);
//speakers circles black top
g2.setColor(Color.BLACK);
Ellipse2D.Double speakerTop1 = new Ellipse2D.Double(315, 415, 20, 20);
g2.fill(speakerTop1);
// Speakers circles gray bottom
g2.setColor(Color.DARK_GRAY);
Ellipse2D.Double speakerBottom = new Ellipse2D.Double(310, 450, 30, 30);
g2.fill(speakerBottom);
//speakers circles black bottom
g2.setColor(Color.BLACK);
Ellipse2D.Double speakerBottom1 = new Ellipse2D.Double(315, 455, 20, 20);
g2.fill(speakerBottom1);
}
}

I'm not sure having a big component is the best thing to do but here is how you achieve what I understood you're asking (just the body of the class):
private int x, y;
private float scale;
public PosSCale(int x, int y, float scale) {
this.x = x;
this.y = y;
this.scale = scale;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
g2.translate(x, y);
g2.scale(scale, scale);
// Speaker base
g2.setColor(Color.BLACK);
Rectangle base = new Rectangle (0, 0, 50, 100);
g2.fill(base);
// Speakers circles gray top
g2.setColor(Color.DARK_GRAY);
Ellipse2D.Double speakerTop = new Ellipse2D.Double(10, 10, 30, 30);
g2.fill(speakerTop);
//speakers circles black top
g2.setColor(Color.BLACK);
Ellipse2D.Double speakerTop1 = new Ellipse2D.Double(15, 15, 20, 20);
g2.fill(speakerTop1);
// Speakers circles gray bottom
g2.setColor(Color.DARK_GRAY);
Ellipse2D.Double speakerBottom = new Ellipse2D.Double(10, 50, 30, 30);
g2.fill(speakerBottom);
//speakers circles black bottom
g2.setColor(Color.BLACK);
Ellipse2D.Double speakerBottom1 = new Ellipse2D.Double(15, 55, 20, 20);
g2.fill(speakerBottom1);
}

Related

Subtracting an inner radius/portion of an arc to achieve a ring style progress bar

I am trying to draw a ring/partial ring using arc's.
But I need the middle of the partial ring/ring to be transparent and show whats behind it. Since I am using an arc and spinning it, is there a way to subtract away the inner portion of each arc and leave only the end at the desired thickness which will be spun to create the ring?
This is my code so far: I have the arcs working, but I am only simulating the ring by layering over each one with a couple circles, I need to actually subtract out the area of each circle from each arc.
Not sure how to do that to achieve transparency in the center. If there is a better way to do this please let me know, this is going to be a custom progress bar.
public class JCustomProgressBar extends JComponent{
private final Dimension SIZE = new Dimension( 50, 50 );
public JCustomProgressBar() {
super();
this.setVisible(true);
System.out.println("CAlled");
}
int progress = 1;
public void updateProgress (int progress){
this.progress = progress;
}
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
System.out.println("called");
Graphics2D g2D = (Graphics2D) g.create();
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2D.translate(this.getWidth()/2, this.getHeight()/2);
g2D.rotate(Math.toRadians(270));
Arc2D.Float arc = new Arc2D.Float (Arc2D.PIE);
Ellipse2D circle = new Ellipse2D.Float(0, 0, 80, 80);
arc.setFrameFromCenter (new Point(0,0), new Point (90, 90));
circle.setFrameFromCenter(new Point(0,0), new Point (80, 80));
arc.setAngleExtent(-progress*360/100);
g2D.setColor(new Color(120,192,0));
g2D.draw(arc);
g2D.fill(arc);
g2D.setColor(this.getParent().getBackground());
g2D.draw(circle);
g2D.fill(circle);
arc.setFrameFromCenter (new Point(0,0), new Point (75, 75));
arc.setAngleExtent(-90*360/100);
g2D.setColor(new Color(197,228,146));
g2D.draw(arc);
g2D.fill(arc);
circle.setFrameFromCenter(new Point(0,0), new Point (70, 70));
g2D.setColor(this.getParent().getBackground());
g2D.draw(circle);
g2D.fill(circle);
circle.setFrameFromCenter(new Point(0,0), new Point (60, 60));
g2D.setColor(new Color(245, 245, 245));
g2D.draw(circle);
g2D.fill(circle);
g2D.setColor(Color.black);
g2D.rotate(Math.toRadians(90));
g2D.setFont(new Font("Verdana", Font.PLAIN, 30));
FontMetrics fm = g2D.getFontMetrics();
Rectangle2D r2D = fm.getStringBounds(progress + "%", g);
int x = (0 - (int) r2D.getWidth())/2;
int y = (0 - (int) r2D.getHeight())/2 +fm.getAscent();
g2D.drawString(progress + "%", x, y-10);
//Rectangle2D r2d = fm.getStringBounds(progress + "", g);
// g2D.setFont(new Font("Verdana", Font.PLAIN, 22));
// g2D.drawString("%", x + 40, y-10);
g2D.setFont(new Font("Verdana", Font.PLAIN, 15));
g2D.drawString("Progress", -35, y+5);
g2D.dispose();
}
}
There are a number of ways you "might" do this, but the simplest might be to just use BasicStroke and simply draw the arcs (and not fill anything at all)
This example deliberately sets the background color so you can see that it's transparent.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JCustomProgressBar pb = new JCustomProgressBar();
pb.setProgress(25);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class JCustomProgressBar extends JPanel {
private final Dimension SIZE = new Dimension(200, 200);
public JCustomProgressBar() {
super();
setBackground(Color.RED);
// Uncomment this to make it transparent
//setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return SIZE;
}
int progress = 1;
public void setProgress(int progress) {
this.progress = progress;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g.create();
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2D.translate(this.getWidth() / 2, this.getHeight() / 2);
BasicStroke bs = new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
Arc2D.Float arc = new Arc2D.Float(Arc2D.OPEN);
arc.setAngleStart(90);
arc.setFrameFromCenter(new Point(0, 0), new Point(90, 90));
arc.setAngleExtent(-((progress / 100d) * 360));
g2D.setStroke(bs);
g2D.setColor(new Color(120, 192, 0));
g2D.draw(arc);
bs = new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
arc.setFrameFromCenter(new Point(0, 0), new Point(75, 75));
arc.setAngleExtent(-(((100 - progress) / 100d) * 360));
g2D.setStroke(bs);
g2D.setColor(new Color(197, 228, 146));
g2D.draw(arc);
g2D.setColor(Color.black);
g2D.setFont(new Font("Verdana", Font.PLAIN, 30));
FontMetrics fm = g2D.getFontMetrics();
Rectangle2D r2D = fm.getStringBounds(progress + "%", g);
int x = (0 - (int) r2D.getWidth()) / 2;
int y = (0 - (int) r2D.getHeight()) / 2 + fm.getAscent();
g2D.drawString(progress + "%", x, y - 10);
g2D.setFont(new Font("Verdana", Font.PLAIN, 15));
g2D.drawString("Progress", -35, y + 5);
g2D.dispose();
}
}
}
You can take a look at Stroking and Filling Graphics Primitives for more details.
Before you tell me how you "don't want the ends rounded" (because I like it that way), make sure you take the time to read the BasicStroke JavaDocs

Java Graphics.fillXxx() in combination with Graphics2D.scale()

I have this program:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class TestLine {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestLine().start();
}
});
}
private static void start() {
JFrame frame = new JFrame();
frame.setContentPane(new CarthPanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static class CarthPanel extends JComponent {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D gg = (Graphics2D) g;
int w = gg.getClipBounds().width;
int h = gg.getClipBounds().height;
System.out.println("(w,h)=(" + w + "," + h + ")");
gg.translate(w - 1, 0); // <<< when uncommenting both lines, mirroring applies
gg.scale(-1.0, 1.0); //
paintTest(gg, w, h);
}
private static void paintTest(Graphics2D g, int w, int h) {
// black background
g.setColor(Color.black);
g.fillRect(0, 0, w, h);
// colored corners
g.setColor(Color.RED);
g.drawLine(0, 0, 10, 0);
g.drawLine(0, 0, 0, 10);
g.setColor(Color.RED);
g.drawLine(0, 199, 10, 199);
g.drawLine(0, 199, 0, 189);
g.setColor(Color.CYAN);
g.drawLine(189, 0, 199, 0);
g.drawLine(199, 0, 199, 10);
g.setColor(Color.CYAN);
g.drawLine(189, 199, 199, 199);
g.drawLine(199, 199, 199, 189);
// yellow squares
g.setColor(Color.yellow);
g.drawRect(3, 3, 10, 10);
g.fillRect(186, 3, 11, 11);
g.fillRect(3, 186, 11, 11);
g.drawRect(186, 186, 10, 10);
String chars = "ABC";
g.setFont(Font.decode("Arial 72"));
Rectangle2D rect = g.getFontMetrics().getStringBounds(chars, g);
g.drawString(chars, (int) (200 - rect.getWidth()) / 2, (int) (200 - rect.getHeight()));
}
}
}
If you run this program once with two particular lines commented in and then once with the same lines commented out (see the code), then you get to see this:
[
If you didn't spot the problem, here's a zoomed pic:
One would expect the image to be perfectly mirrored. This is true for all strokes and hollow shapes (= drawXxx() methods). All filled shapes however (= fillXxx() methods) are drawn exactly one pixel to the left of where I expect them; e.g. the filled yellow rectangles, and you can also notice that the black background has shifted, as seen by the white line at the right border.
Is this a bug or is this intended? I suspect that it has something to do with the difference how "width" and "height" are being handled in drawXxx() and fillXxx() methods:
drawRect(x,y,w,h) results in a hollow rectangle with X-axis boundaries x and x+w, so the rectangle is w+1 pixels wide.
fillRect(x,y,w,h) results in a filled rectangle with X-axis boundaries x and x+w-1, so the rectangle is w pixels wide.
What am I missing?
Not an answer, rather a hypothesis - the "contains(x,y)" of a rectangle will be true for the sides which forms the (x,y) corner of the rect and false for the sides making the (maxx, maxy) corner. Demo:
Rectangle r=new Rectangle(0, 0, 10, 10);
System.out.println(r.contains(0, 5)); // true
System.out.println(r.contains(5, 0)); // true
System.out.println(r.contains(10, 5)); // false
System.out.println(r.contains(5, 10)); // false
The hypothesis is that fillRect will not consider the "max sides" as inside points to be filled.
To assess the hypothesis, I'd suggest you to try using a GeneralPath which defines the same rectangle and see it there is any difference in filling it. GeneralPath should be forbidden to make any assumption on "the right-top borders are out of the shape's interior"
It is a bug, it is not a feature :)
Surely it is not intended, the mirrored image should be perfect, there's no reason why it shouldn't.
There is a way to use BufferedImage to render on it normally, and then drawing this BufferedImage flipped, the only drawback is a little performance influence and not well looking text drawn using LCD subpixeling.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class TestLine {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestLine().start();
}
});
}
private static void start() {
JFrame frame = new JFrame();
frame.setContentPane(new CarthPanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static class CarthPanel extends JComponent {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D gg = (Graphics2D) g;
// System.out.println("(w,h)=(" + w + "," + h + ")");
gg.translate(getWidth(), 0); // <<< when uncommenting both lines, mirroring applies
gg.scale(-1.0, 1.0); //
BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
try {
paintTest(img.createGraphics());
} catch (Exception e) {
e.printStackTrace();
}
g.drawImage(img, 0, 0, null);
}
private void paintTest(Graphics2D g) {
// black background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// colored corners
g.setColor(Color.RED);
g.drawLine(0, 0, 10, 0);
g.drawLine(0, 0, 0, 10);
g.setColor(Color.RED);
g.drawLine(0, 199, 10, 199);
g.drawLine(0, 199, 0, 189);
g.setColor(Color.CYAN);
g.drawLine(189, 0, 199, 0);
g.drawLine(199, 0, 199, 10);
g.setColor(Color.CYAN);
g.drawLine(189, 199, 199, 199);
g.drawLine(199, 199, 199, 189);
// yellow squares
g.setColor(Color.yellow);
g.drawRect(3, 3, 10, 10);
g.fillRect(186, 3, 11, 11);
g.fillRect(3, 186, 11, 11);
g.drawRect(186, 186, 10, 10);
String chars = "ABC";
g.setFont(Font.decode("Arial 72"));
Rectangle2D rect = g.getFontMetrics().getStringBounds(chars, g);
g.drawString(chars, (int) (200 - rect.getWidth()) / 2, (int) (200 - rect.getHeight()));
}
}
}

How to disable java.awt.Graphics.fillRect(int x, int y, int width, int height)'s effect?

It's the original image:
I use java.awt.Graphics.fillRect(int x, int y, int width, int height) to add a coloured rectangle on the image.
Graphics imageGraphics = image.createGraphics();
Color color = new Color(0,0,0,100);
imageGraphics.setColor(color);
imageGraphics.fillRect(0, 0, 800, 600);
So the image has been inverted and looks like this:
After that,I want to clear the black transparent rectangle partly and show the original image.
imageGraphics.clearRect(100,100,100,100);
But the effect is like this:
What my requirement is:
I want to know why it doesn't work and is there any other way to realize it?
Remember, painting is destructive. It might be possible to use AlphaComposite to achieve this result, but a simpler solution might be to simple constructive a compound shape and paint that instead.
The following example creates two Rectangles, one been the area we want to fill and one been the area we want to show, the second is then subtracted from the first (to create the window) and then the result is painted on top of the image
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ShowArea {
public static void main(String[] args) {
new ShowArea();
}
public ShowArea() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(new File("sample.png"));
Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Rectangle clip = new Rectangle(150, 10, 100, 100);
Area area = new Area(bounds);
area.subtract(new Area(clip));
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.BLACK);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(area);
g2d.dispose();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
If I were doing some kind of paint program, I would do this all within the paintComponent method or in some way that it didn't effect the original image, otherwise you've basic destroyed the image until you re-load it
Another solution might be to take a copy of the original area you want to keep and repaint it back on top after, for example...
img = ImageIO.read(new File("sample.png"));
// This is the portion of the image we want to save...
BufferedImage cutout = img.getSubimage(150, 10, 100, 100);
// This is the area we want to paint over...
Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.BLACK);
// Save the current Composite so we can reset it...
Composite comp = g2d.getComposite();
// Apply the composite and fill the area...
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(area);
// Reset the composite
g2d.setComposite(comp);
// Draw the part of the image we saved previously...
g2d.drawImage(cutout, 150, 10, this);
g2d.dispose();
You cant do that the way you're trying to.
It can be done by creating a BufferedImage filled with Color(0,0,0,200), then in that image draw rectangle with color Color(0,0,0,200) and then apply it on image.
Remember, that drawing filledRectange is not a "undo operation"- it is written on pixels and it can't be undone.
EDIT
Icon imageIcon = new javax.swing.ImageIcon("image.jpg");
BufferedImage mask = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage image = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
imageIcon.paintIcon(null, image.getGraphics(), 0, 0);
Graphics maskGraphics = mask.getGraphics();
//drawing grey background
maskGraphics.setColor(new Color(0, 0, 0, 120));
maskGraphics.fillRect(0, 0, mask.getWidth(), mask.getHeight());
//drawing black frame
maskGraphics.setColor(new Color(0, 0, 0, 255));
maskGraphics.drawRect(99, 99, 301, 301);
//drawing original image window
maskGraphics.drawImage(image, 100, 100, 400, 400, 100, 100, 400, 400, null);
//apply mask on image
new ImageIcon(mask).paintIcon(null, image.getGraphics(), 0, 0);
//result presentation
label.setIcon(new ImageIcon(image));
Yes this is easily doable. The problem is that any draw operation is destructive, what you see is what you get, the information that was painted upon is lost.
Something like this where you store a subimage, do your paint operation then draw the subimage back on top.
public class Q23709070 {
public static void main(String[] args) {
JFrame frame = new JFrame();
Panel p = new Panel();
frame.getContentPane().add(p);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
static class Panel extends JPanel {
int w = 400;
int h = 400;
int x = 100;
int y = 100;
BufferedImage img;
BufferedImage subImg;
BufferedImage save;
public Panel() {
try {
img = ImageIO.read(getClass().getResourceAsStream("0qzCf.jpg"));
} catch (IOException e) {
}
subImg = img.getSubimage(x, y, w, h);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Color g2dColor = g2d.getColor();
Color fillColor = new Color(0, 0, 0, 100);
g2d.drawImage(img, 0, 0, null);
g2d.setColor(fillColor);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.drawImage(subImg, x, y, null);
g2d.setColor(g2dColor);
if (save == null) {
save = new BufferedImage(img.getWidth(), img.getHeight(),
img.getType());
this.paint(save.getGraphics());
try {
ImageIO.write(save, "jpg", new File("save.jpg"));
} catch (IOException e) {
}
}
}
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
}
}
Rendering

Change JButton on down and on up?

I overrided the paint component of a JButton, but now when I click it doesn't get darker. I searched google and stack overflow, but there doesn't seem to be an answer. So how do I make the button get darker when I click down and then return to normal when I finish the click?
Here is my code:
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();
RenderingHints qualityHints =
new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHints(qualityHints);
g2.setPaint(new GradientPaint(
new Point(0, 0),
BUTTON_TOP_GRADIENT,
new Point(0, getHeight()),
BUTTON_BOTTOM_GRADIENT));
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
g2.dispose();
}
This code snippet at the bottom works for me. Here's how it works:
I check the button's model to see if the button is clicked. When it is clicked, it paints itself differently.
package com.sandbox;
import javax.swing.*;
import java.awt.*;
public class SwingSandbox {
public static void main(String[] args) {
JFrame frame = buildFrame();
frame.add(new MyButton());
}
private static class MyButton extends JButton {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Color color;
if (getModel().isPressed()) {
color = new Color(0, 0, 0);
} else {
color = new Color(0, 0, 255);
}
Graphics2D g2 = (Graphics2D) g.create();
RenderingHints qualityHints =
new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHints(qualityHints);
g2.setPaint(new GradientPaint(
new Point(0, 0),
color,
new Point(0, getHeight()),
new Color(255, 255, 0)));
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
g2.dispose();
}
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
}

Java JFrame size and centre

I'm working on a uni project which is to create a dice face using 2d graphics shapes. I have got that all done but I have a problem: I want my shape to change size when I adjust the window size, instead of just staying still also so that it stays in the middle.
I thought I could set the position so that is was center tried this but didn't work. I'm not sure but would I have to write co-ordinates so that its changes size with the window? Any help with both problems would be great.
GUI setup code
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class DiceSimulator {
public static void main(String[] args) {
JFrame frame = new JFrame("DiceSimulator");
frame.setVisible(true);
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw object = new draw();
frame.add(object);
frame.setLocationRelativeTo(null);
object.drawing();
}
}
Painting code
import javax.swing.*;
import java.awt.*;
//import java.util.Random;
public class draw extends JComponent {
public void drawing() {
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//Random1 random = new Random1();
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.BLACK);
Rectangle box = new Rectangle(115, 60, 150, 150);
g2.fill(box);
g.setColor(Color.WHITE);
g.fillOval(145, 75, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(205, 75, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(145, 115, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(205, 115, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(145, 155, 30, 30);
g.setColor(Color.WHITE);
g.fillOval(205, 155, 30, 30);
}
}
In the paintComponent() method you need to use
int width = getSize().width;
int height = getSize().height;
to get the current size of the component as it changes size when the frame changes size. Then based on this current size you can draw your components. This means that you can't hardcode the values in your drawing methods.
If you want to shift all the drawing coordinates with one command then you can use:
g.translate(5, 5);
at the top of the method. Then all hardcoded (x, y) values will be adjusted by 5 pixels each. This will allow you to change the centering of the drawing.

Categories