Setting the stroke on a border for a JPanel - java

I am having problems setting the thickness of my border. I wanted to have a JPanel with a rounded dashed border. I was able to set it rounded by overriding the paintComponent to make it round. However, when I set the stroke to make the border thicker and dashed it does not work. I use the setStroke() method. My code is the following
private void loadTopPane() {
JPanel topSection = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension arcs = new Dimension(15, 15); // Border corners arcs
// {width,height},
// change this to
// whatever you want
int width = getWidth();
int height = getHeight();
Graphics2D graphics = (Graphics2D) g;
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
float dash1[] = { 10.0f };
final BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f,
dash1, 0.0f);
// Draws the rounded panel with borders.
graphics.setColor(getBackground());
graphics.fillRoundRect(0, 0, width - 1, height - 1, arcs.width, arcs.height);// paint
// background
graphics.setColor(getForeground());
graphics.drawRoundRect(0, 0, width - 1, height - 1, arcs.width, arcs.height);// paint
// border
graphics.setStroke(dashed);
}
};
topSection.setLayout(null);
topSection.setSize(1150, 175);
topSection.setBackground(new Color(222, 225, 226));
topSection.setBounds(25, 13, topSection.getPreferredSize().width, topSection.getPreferredSize().height);
topSection.add(new JLabel("TESTING"));
topSection.setBounds(20, 10, 1180, 180);
frame.add(topSection);
}
So the output shows me a JPanel with a rounded border but it does not give me a border that is dashed and thicker. How can I fix this?

Have you considered calling setStroke BEFORE you paint the border...
float dash1[] = {10.0f};
final BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f,
dash1, 0.0f);
graphics.setStroke(dashed);
// Draws the rounded panel with borders.
graphics.setColor(getBackground());
graphics.fillRoundRect(0, 0, width - 1, height - 1, arcs.width, arcs.height);// paint
// background
graphics.setColor(getForeground());
graphics.drawRoundRect(0, 0, width - 1, height - 1, arcs.width, arcs.height);// paint

Related

How to use a setStroke on a graphics object?

I am trying to make a program where when you click a check box saying that you want an object to be drawn with a dashed line you can, but when I create a stroke and try to use it my graphics does not acknowledge it. The code is set to double buffer so the image doesn't disappear when you are creating it. I am not sure how to make the objects draw in with the dashed line and would appreciate any help!
Graphics bgg = bg.getGraphics();
if(!jCheckBox1.isSelected()){
bgg.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
else{
Graphics2D g2d = (Graphics2D) bgg;
float[] fa = {10, 10, 10};
BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, fa, 10);
g2d.setStroke(bs);
g2d.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
In order to draw a rectangle onto your image you will need to use the Graphics.drawRect() method something like this (just off the top of my head with what you've already got):
Graphics bgg = bg.getGraphics();
if(!jCheckBox1.isSelected()){
bgg.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
else{
Graphics2D g2d = (Graphics2D) bgg;
//Draw image into panel...
g2d.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
//Draw dashed rectagle in center of panel...
int pW = jPanel1.getWidth(); // Get panel Width
int pH = jPanel1.getHeight(); // Get panel Height
float[] fa = {10, 10, 10}; // The dash pattern
// Set Brush thickness (5)
BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, fa, 10);
g2d.setStroke(bs);
Dimension rectangle = new Dimension(200, 50); // Our desired rectangle dimensions
// Center locations for rectangle...
int x1 = (pW / 2) - (rectangle.width / 2);
int y1 = (pH / 2) - (rectangle.height / 2);
int x2 = rectangle.width;
int y2 = rectangle.height;
g2d.setColor(Color.RED); // Set the dashed shape line color
g2d.drawRect(x1, y1, x2, y2); // Draw the dashed rectangle
// free resourses
bgg.dispose();
g2d.dispose();
jPanel1.revalidate(); // update panel graphics
}
A brush stroke of 5 makes for a pretty heavy dash :)

How can I paint a custom circular JComponent without an "invisible box" around it?

I'm writing a JApplet that displays a diagram with numbers in circles and lines connecting the circles. I've created a class that extends JComponent to act as the circles. I overrode the paintComponent() method to draw a circle with the numbers inside, and I placed these circles on my applet, on which I drew the lines in the paint() method.
However, if the lines hit the circle at an angle, they cut out early, before the circle, at the square that outlines the entire JComponent, even though the background should be transparent. this forms an "invisible box" around the circle.
I've prepared a smaller program to demonstrate the issue:
And here is the code for that example:
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.*;
public class Circle extends JApplet {
private static final long serialVersionUID = 1L;
myCircle myC = new myCircle(10, 215, 215); // custom circle
Container c;
public void init() {
setSize(500, 500);
c = getContentPane();
c.setLayout(null);
c.setBackground(Color.lightGray);
c.add(myC);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
//draw lines
g2d.draw(new Line2D.Double(0f, 0f, 500f, 500f));
g2d.draw(new Line2D.Double(0f, 500f, 500f, 0f));
g2d.draw(new Line2D.Double(0f, 250f, 500f, 250f));
g2d.draw(new Line2D.Double(250f, 0f, 250f, 500f));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
myC.repaint(); // put the circle on top
}
public class myCircle extends JComponent {
private static final long serialVersionUID = 1L;
int number; // number to display
public myCircle(int num, int x, int y) {
this.number = num;
this.setLocation(x, y);
this.setSize(75, 75);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.white);
g2d.fill(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.setColor(Color.black);
g2d.draw(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.drawString(Integer.toString(number), 15f, 20f);
}
}
}
I wouldn't use a component to represent the circle shape alone. Instead, just paint it all on one JPanel (I'm using a JFrame instead of an applet):
public class Circle extends JPanel {
int number = 10;
float size = 500f;
float rad = 70f;
float stringLocX = 15f, stringLocy = 20f;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.BLACK);
g2d.draw(new Line2D.Double(0f, 0f, size, size));
g2d.draw(new Line2D.Double(0f, size, size, 0f));
g2d.draw(new Line2D.Double(0f, size / 2, size, size / 2));
g2d.draw(new Line2D.Double(size / 2, 0f, size / 2, size));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
Ellipse2D.Float circle = new Ellipse2D.Float((size - rad) / 2, (size - rad) / 2, rad, rad);
g2d.setColor(Color.WHITE);
g2d.fill(circle);
g2d.setColor(Color.BLACK);
g2d.draw(circle);
g2d.drawString(Integer.toString(number), (size - rad) / 2 + stringLocX,
(size - rad) / 2 + stringLocy);
}
#Override
public Dimension getPreferredSize() {
return new Dimension((int) size, (int) size);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.add(new Circle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
});
}
}
Depending on how many circles you have and what data they must contain, you can just keep a list of those numbers, then iterate over the list in painComponent and draw them.
Notes:
Don't use null layout.
Better to keep the hard coded numbers as fields so you can change them more easily, possibly make them final.
You need to look at the length of the line being drawn. From the edge of your figure to the circle is longer at an angle than at the sides. Recall for a triangle with 45 degrees, 45 degree, and 90 degree angles the ratio of the length of the sides is 1:1:sqrt(2)

Java 2D Graphics rotating objects keeping original coords system?

I've already searched this topic everywhere on the Internet, but nothing.
I'm programming with JAVA and I'm painting in a JPanel some shapes like yellow stars with a sort of spaceship in the center of the screen. My purpose is to make the entire scene, apart from the spaceship which remains stationary at the center, rotate around the center (and of course around the spaceship) when I press a certain button.
Now, when I rotate the stars I make them rotate around the center point wich changes as the spaceship moves, but when I do a rotation, the coordinates system changes and the ship moves diagonally, while I want to rotate the scene keeping possible to move the spaceship vertically and horizontally.
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
// RIEMPIMENTO SFONDO
g2.setColor(new Color(10, 10, 10));
g2.fillRect(0, 0, 1366, 768);
// DEBUGGER
g2.setColor(Color.WHITE);
g2.drawString("|" + posx + "|" + posy + "| " + scale, 1250, 758);
// TRASFORMAZIONE NAVICELLA
AffineTransform at = new AffineTransform();
at.translate(683, 384);
at.scale(scale, scale);
g2.setTransform(at);
AffineTransform backup = g2.getTransform();
// DISEGNO NAVICELLA
g2.setColor(Color.LIGHT_GRAY);
int[] xp = {0, -25, -25, 0, 25, 25};
int[] yp = {-25, 0, 25, 0, 25, 0};
g2.drawPolygon(xp, yp, 6);
// TRASFORMAZIONE SPAZIO
at.translate(posx, posy);
at.rotate(Math.toRadians(rotation), -posx, -posy);
g2.setTransform(at);
// DISEGNO SPAZIO
STAR(g2, 300 + posx, 100 + posy, 200, 200, Color.YELLOW);
STAR(g2, -100 + posx, -200 + posy, 200, 200, Color.YELLOW);
g2.dispose();
}

java get color of pixel for transparent, gradient overlay

In my application I have an image (world map) as background picture. Over this background picture, there is a polygon with a color gradient and transparent filling effect.
Here you find a code snippet of the overlay:
public void paint(Graphics g) {
//draw a polygon with a gradient filling effect
Graphics2D g2 = (Graphics2D)g;
GradientPaint gp = new GradientPaint(x1, y1, color1, x2, y2, color2, false);
g2.setPaint(gp);
g2.fill(polygon);
}
Does somebody know a method to get the color of one pixel of the overlay? I don't need the color, which can be seen on the screen including the background picture - just the color of the overlay.
Best regards,
Michael
This is somewhat ugly, but works:
GradientPaint gp = new GradientPaint(0, 0, new Color(255, 0, 0, 50),
10, 10, new Color(128, 255, 0, 150));
ColorModel cm = ColorModel.getRGBdefault();
Rectangle r = new Rectangle(0, 0, 10, 10);
Raster raster = gp.createContext(cm, r, r, new AffineTransform(), null)
.getRaster(0, 0, 10, 10);
int[] rgba = raster.getPixel(5, 5, (int[])null);
Alternately, you could just paint the overlay into a BufferedImage (which you had first cleared to transparent).

How do I code a filthy rich gradient-painted border using Java Swing

Revised: The problem is to paint a four sided border where each side starts with a solid base color and fades to white inward over the span of the border. The challenge was to make the intersection of the borders look seamless. To accomplish this, one may draw the borders, then use triangles to 'blend' the corners. Two triangles may be used per corner if there is no overlap in the rectangles drawing the broder, or one triangle per corner is sufficient (as shown below) if two parallel border sides extend the full length of the border (ie the rectangles overlap).
private static final int GRADIENT_LENGTH = 29;
private static final int BAR_LENGTH = 25;
public static void paintGradientBorder(Graphics g, Color borderColor) {
Graphics2D g2 = (Graphics2D) g.create();
GradientPaint gradientColorWest = new GradientPaint(0, 0, borderColor,
GRADIENT_LENGTH, 0, Color.WHITE);
GradientPaint gradientColorEast = new GradientPaint(WINDOW_WIDTH - GRADIENT_LENGTH,
0, Color.WHITE, WINDOW_WIDTH, 0, borderColor);
GradientPaint gradientColorNorth= new GradientPaint(0, 0, borderColor, 0,
GRADIENT_LENGTH, Color.WHITE);
GradientPaint gradientColorSouth = new GradientPaint(0, WINDOW_HEIGHT - GRADIENT_LENGTH,
Color.WHITE,0, WINDOW_HEIGHT, borderColor);
//south bar
g2.setPaint(gradientColorSouth);
g2.fillRect(0, WINDOW_HEIGHT - BAR_LENGTH, WINDOW_WIDTH, BAR_LENGTH);
//north bar
g2.setPaint(gradientColorNorth);
g2.fillRect(0, 0, WINDOW_WIDTH, BAR_LENGTH);
//west bar
g2.setPaint(gradientColorWest);
g2.fillRect(0, BAR_LENGTH, BAR_LENGTH, WINDOW_HEIGHT - BAR_LENGTH * 2);
//east bar
g2.setPaint(gradientColorEast);
g2.fillRect(WINDOW_WIDTH - BAR_LENGTH, BAR_LENGTH, WINDOW_WIDTH, WINDOW_HEIGHT - BAR_LENGTH * 2);
//NORTH WEST CORNER
//left triangle
Polygon p = new Polygon();
p.addPoint(0, 0);
p.addPoint(BAR_LENGTH, BAR_LENGTH);
p.addPoint(0, BAR_LENGTH);
g2.setPaint(gradientColorWest);
g2.fillPolygon(p);
//NORTH EAST CORNER
//right triangle
p.reset();
p.addPoint(WINDOW_WIDTH, 0);
p.addPoint(WINDOW_WIDTH - BAR_LENGTH, BAR_LENGTH);
p.addPoint(WINDOW_WIDTH, BAR_LENGTH);
g2.setPaint(gradientColorEast);
g2.fillPolygon(p);
//SOUTH WEST CORNER
//left triangle
p.reset();
p.addPoint(0, WINDOW_HEIGHT);
p.addPoint(0,WINDOW_HEIGHT - BAR_LENGTH);
p.addPoint(BAR_LENGTH, WINDOW_HEIGHT - BAR_LENGTH);
g2.setPaint(gradientColorWest);
g2.fillPolygon(p);
//SOUTH EAST CORNER
//right triangle
p.reset();
p.addPoint(WINDOW_WIDTH, WINDOW_HEIGHT);
p.addPoint(WINDOW_WIDTH, WINDOW_HEIGHT - BAR_LENGTH);
p.addPoint(WINDOW_WIDTH - BAR_LENGTH, WINDOW_HEIGHT - BAR_LENGTH);
g2.setPaint(gradientColorEast);
g2.fillPolygon(p);
g2.dispose();
}
What if you don't intersect the rectangles but instead use a polygon (GeneralPath)?
GeneralPath topBox = new GeneralPath();
topBox.moveTo(0, 0);
// upper right
topBox.lineTo(width, 0);
// lower right; move diagonally down and to the left as in a picture frame
topBox.lineTo(width - (insetX / 2), 0 + (insetY / 2));
// lower left
topBox.lineTo((insetX / 2), 0 + (insetY / 2));
topBox.closePath();
g2.fill(topBox);
That way the rectangles will not overlap, but instead you'll have nice crisp edges between the different segments.
Rather than creating and painting 4 rectangles, I would create a single Shape representing your border area by subtracting an inner rectangle from an outer one using Area:
Area area = new Area(new Rectangle2D.Double(...));
Area inner = new Area(new Rectangle2D.Double(...));
area.subtract(inner);
g2.setPaint(new GradientPaint(...));
g2.fill(area);

Categories