How to draw a String inside a filled rectangle? - java

I just want to display my String inside a rectangle filled with black. Thanks for the help!

Here you are:
public class MyPanel extends JPanel{
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(10/*x*/, 10/*y*/, 80/*width*/, 30/*hight*/);
g.drawString("TextToDraw", 25/*x*/, 25/*y*/);
}
}

public class LabeledRectangle extends Rectangle{
public LabeledRectangle(int x, int y, int width, int height, String text) {
super (x, y, width, height);
this.text = text;
}
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Rectangle2D.Double(x, y, width,height));
Font font = g2.getFont();
FontRenderContext context = g2.getFontRenderContext();
g2.setFont(font);
int textWidth = (int) font.getStringBounds(text, context).getWidth();
LineMetrics ln = font.getLineMetrics(text, context);
int textHeight = (int) (ln.getAscent() + ln.getDescent());
int x1 = x + (width - textWidth)/2;
int y1 = (int)(y + (height + textHeight)/2 - ln.getDescent());
g2.setColor(Color.red);
g2.drawString(text, (int) x1, (int) y1);
}
private String text;
}

Related

paintComponent overwrites pixels

So I've added a grid to my BufferedImage, by doing it in the PaintComponentlike this. It works perfect.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Color c=new Color(184, 184, 184, 255);
g.drawImage(canvas, 0, 0, this);
for ( int x = 0; x <= getWidth(); x += 10 ){
for ( int y = 0; y <= getHeight(); y += 10 ){
g.setColor(c);
g.drawRect( x, y, 10, 10 );
}
}
}
BUT, when I then draw my line/circles in this function:
public void drawPixels(Object val_x, Boolean highlight)
{
String[] values = val_x.toString().replaceAll("[()]", "").split(",");
if (highlight){
canvas.setRGB(Integer.parseInt(values[0]), Integer.parseInt(values[1]), Color.RED.getRGB());
}else{
canvas.setRGB(Integer.parseInt(values[0]), Integer.parseInt(values[1]), c.getRGB());
}
repaint();
}
I see that some of my pixels is overwriten by the grid from paintComponent.
Is there a way to z-index the grid behind the pixels I draw, or maybe draw the grid first, and then draw on the top of that?
My GUI looks like this, where you can see that my circles pixels is swapped with the grid:
If you want to look at the whole drawing .java file
package DrawCanvas;
import com.sun.org.apache.xpath.internal.operations.Bool;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class DrawCanvas extends JPanel {
private BufferedImage canvas;
private static Graphics g2;
final private Color c = Color.BLACK;
private final static Color def_bg = new Color(108, 108, 108, 255);
//private final static Color def_bg = new Color(80, 80, 80, 255);
int width = 1280;
int height = 720;
public DrawCanvas() {
canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2 = canvas.getGraphics();
fillCanvas(def_bg);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(canvas.getWidth(), canvas.getHeight());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Color c=new Color(184, 184, 184, 255);
g.drawImage(canvas, 0, 0, this);
for ( int x = 0; x <= getWidth(); x += 10 ){
for ( int y = 0; y <= getHeight(); y += 10 ){
g.setColor(c);
g.drawRect( x, y, 10, 10 );
}
}
}
public void fillCanvas(Color c) {
int color = c.getRGB();
for (int x = 0; x < canvas.getWidth(); x++) {
for (int y = 0; y < canvas.getHeight(); y++) {
canvas.setRGB(x, y, color);
}
}
repaint();
}
// Implementation from Wikipedia: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
public void drawPixels(Object val_x, Boolean highlight)
{
String[] values = val_x.toString().replaceAll("[()]", "").split(",");
if (highlight){
canvas.setRGB(Integer.parseInt(values[0]), Integer.parseInt(values[1]), Color.RED.getRGB());
}else{
canvas.setRGB(Integer.parseInt(values[0]), Integer.parseInt(values[1]), c.getRGB());
}
repaint();
}
public void clearImage() {
Graphics2D g2 = (Graphics2D) canvas.getGraphics();
g2.setBackground(def_bg);
g2.clearRect(0,0, (int)canvas.getWidth(), (int)canvas.getHeight());
repaint();
}
}
EDIT 1 solution
package DrawCanvas;
import com.sun.org.apache.xpath.internal.operations.Bool;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class DrawCanvas extends JPanel {
private BufferedImage canvas;
private static Graphics g2;
final private Color c = Color.BLACK;
private final static Color def_bg = new Color(108, 108, 108, 255);
private final static Color grid = new Color(149, 149, 149, 186);
//private final static Color def_bg = new Color(80, 80, 80, 255);
int width = 1280;
int height = 720;
public DrawCanvas() {
canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2 = canvas.getGraphics();
fillCanvas(def_bg);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(canvas.getWidth(), canvas.getHeight());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(canvas, 0, 0, this);
}
public void fillCanvas(Color c) {
int color = c.getRGB();
for (int x = 0; x < canvas.getWidth(); x++) {
for (int y = 0; y < canvas.getHeight(); y++) {
canvas.setRGB(x, y, color);
}
}
drawGrid();
repaint();
}
// Implementation from Wikipedia: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
// Implementation from Wikipedia: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
public void drawPixels(Object val_x, Boolean highlight)
{
Graphics2D graph = canvas.createGraphics();
String[] values = val_x.toString().replaceAll("[()]", "").split(",");
if (highlight){
graph.setColor(Color.RED);
graph.drawOval(Integer.parseInt(values[0]), Integer.parseInt(values[1]), 1, 1);
}else{
graph.setColor(c);
graph.drawOval(Integer.parseInt(values[0]), Integer.parseInt(values[1]), 1, 1);
}
}
public void drawGrid(){
Graphics2D graph = canvas.createGraphics();
for (int x = 0; x < canvas.getWidth(); x += 10) {
for (int y = 0; y < canvas.getHeight(); y += 10) {
graph.setColor(grid);
graph.drawRect( x, y, 10, 10 );
}
}
repaint();
}
public void clearImage() {
Graphics2D g2 = (Graphics2D) canvas.getGraphics();
g2.setBackground(def_bg);
g2.clearRect(0,0, (int)canvas.getWidth(), (int)canvas.getHeight());
drawGrid();
repaint();
}
}

JTabbedPane Tab unselected does not fill JPanel while selected does

I have custom JTabbedPane, I am having issue with making the tabs the same size as each other.
as you can see in the image, The green tab is selected, while the Red is unselected, I would like the Red Tab (Unselected) to be the same size as the Green Tab (Selected) here is my code
here is the code.
import javax.swing.*;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import java.awt.*;
public class UITest {
public static void main(String[] args){
JFrame jFrame = new JFrame();
JTabbedPane jTabbedPane = new JTabbedPane();
jTabbedPane.add(new JPanel(), "test");
jTabbedPane.add(new JPanel(), "test2");
jTabbedPane.setUI(new LynxTabbedPane());
jFrame.setContentPane(jTabbedPane);
jFrame.setSize(200,200);
jFrame.setVisible(true);
}
public static class LynxTabbedPane extends BasicTabbedPaneUI {
private Polygon shape;
#Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
Graphics2D g2D = (Graphics2D) g;
int xp[] = new int[]{x, x, x + w, x + w, x};
int yp[] = new int[]{y, y + h, y + h, y, y};
shape = new Polygon(xp, yp, xp.length);
if (isSelected) {
g2D.setColor(Color.GREEN);
} else if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g2D.setColor(Color.RED);
}
g2D.fill(shape);
}
}
}
I have fixed the issue by moving g2D.fill(shape); inside isSelected
#Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
Graphics2D g2D = (Graphics2D) g;
int xp[] = new int[]{x, x, x + w, x + w, x};
int yp[] = new int[]{y, y + h, y + h, y, y};
shape = new Polygon(xp, yp, xp.length);
if (isSelected) {
g2D.fill(shape);
g2D.setColor(selectColor);
} else if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g2D.setColor(deSelectColor);
}
}
This will only fill it with the shape if the tab is selected.
Result:

Resizing Image Not working

I've made a Button class which allows me to have buttons (Kind of obvious). But in my button class, I'm using an image to display the button on the screen. I got that to work, but I want to resize the image to the size of the button.
My "Image Resizer" works flawlessly, but when I try to resize the button, the button doesn't show up. I don't get any errors.
Here's my Button class:
private String text;
private int size = 0;
private BufferedImage buttonHD;
public Button(int x, int y, int width, int height, int size) {
super(x, y, width, height);
this.size = size;
buttonHD = Renderer.resizeImage(Images.button, x, y, width, height);
}
public Button setText(String text) {
this.text = text;
return this;
}
public void drawButton(Graphics g, int xoffset, int yoffset) {
int xx = x + xoffset;
int yy = y + yoffset;
if(!MouseInput.MOUSE.intersects(this)) {
g.drawImage(buttonHD, x, y, width, height, null);
} else if(MouseInput.MOUSE.intersects(this)){
g.setColor(Color.DARK_GRAY);
g.fillRect(x, y, width, height);
}
Renderer.drawText(text, g, xoffset, yoffset, size);//Draws button text
}
The original image that I'm resizing is stored into my Images class as:
public static BufferedImage button;
Here's my "Button Resizer" method:
public static BufferedImage resizeImage(BufferedImage origImg, int x, int y, int initWidth, int initHeight) {
BufferedImage resizedImg = new BufferedImage(initWidth, initHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resizedImg.createGraphics();
g2d.drawImage(origImg, x, y, initWidth, initHeight, null);
g2d.dispose();
return resizedImg;
}
The way I'm using these buttons are in ScreenState classes. Each class representing as each state. The buttons are set in there and are loaded up by the class's constructor.
The buttons do work as they should, but the images just don't show up. If more code is needed, just let me know and I'll provide you with it.
I've been trying to fix this problem, but had no luck. If someone could just hint out as to where my problem is or maybe have a solution, that'd be great. Thanks!
This function resizes the BufferedImage to the given width and height:
public static BufferedImage resizeImage(BufferedImage image, int width, int height) {
// calculate the scale factor
double xScale = width / (double) image.getWidth();
double yScale = height / (double) image.getHeight();
// create the object that will contain the resized image
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// resize the image
Graphics2D g = (Graphics2D) resizedImage.getGraphics();
g.scale(xScale, yScale);
g.drawImage(image, 0, 0, null);
g.dispose();
// return the resized image
return resizedImage;
}
Then simply use it:
public class MyButton extends JButton
{
private BufferedImage image;
public MyButton() {
image = resizeImage(ImageIO.read(IMAGE_PATH), BUTTON_WIDTH, BUTTON_HEIGHT);
}
#Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
IMAGE_PATH is the File where your image is located, BUTTON_WIDTH and BUTTON_HEIGHT is your button dimension.

Java paintComponent as a JComponent

Don't know if it was a very specific title, but I have already asked this question but has gone dead.
I am trying to execute paintComponent() so I can draw rectangles, triangles and more with the class being a JComponent.
Here is my code so far:
public class Design extends JComponent {
private static final long serialVersionUID = 1L;
private List<ShapeWrapper> shapesDraw = new ArrayList<ShapeWrapper>();
private List<ShapeWrapper> shapesFill = new ArrayList<ShapeWrapper>();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int screenWidth = gd.getDisplayMode().getWidth();
int screenHeight = gd.getDisplayMode().getHeight();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for(ShapeWrapper s : shapesDraw){
g2d.setColor(s.color);
g2d.draw(s.shape);
}
for(ShapeWrapper s : shapesFill){
g2d.setColor(s.color);
g2d.fill(s.shape);
}
}
public void drawRect(int xPos, int yPos, int width, int height) {
shapesDraw.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void fillRect(int xPos, int yPos, int width, int height) {
shapesFill.add(new Rectangle(xPos, yPos, width, height));
repaint();
}
public void drawTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesDraw.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public void fillTriangle(int leftX, int topX, int rightX, int leftY, int topY, int rightY) {
shapesFill.add(new Polygon(
new int[]{leftX, topX, rightX},
new int[]{leftY, topY, rightY},
3));
repaint();
}
public Dimension getPreferredSize() {
return new Dimension(getWidth(), getHeight());
}
public int getWidth() {
return screenWidth;
}
public int getHeight() {
return screenHeight;
}
}
class ShapeWrapper {
Color color;
Shape shape;
public ShapeWrapper(Color color , Shape shape){
this.color = color;
this.shape = shape;
}
}
As shown above, everything works perfectly fine, except for being able to choose a colour.
I want to be able to define the rectangles and triangles with their respective positions and lengths but also want to add a colour with it.
But I get an error.
The error says:
The method add(ShapeWrapper) in the type List< ShapeWrapper > is not applicable for the arguments (Rectangle)
And:
The method add(ShapeWrapper) in the type List< ShapeWrapper > is not applicable for the arguments (Polygon)
Please help! I am so stressed trying to figure this out as it is blocking me from doing many things.
The answer is pretty basic...Shape is not a type of ShapeWrapper, therefore it can't be added to a List decalred as List<ShapeWrapper>
What you should be doing instead of
shapesDraw.add(new Rectangle(xPos, yPos, width, height));
is something more like...
shapesDraw.add(new ShapeWrapper(Color.BLACK, new Rectangle(xPos, yPos, width, height)));
The same goes for your ...Triangle methods. You need to wrap the resulting Polygon in a ShapeWrapper before trying to add it to the List

How to set a 3D border for a JDialog with rounded corners?

I could add a rounded corner border to my JDialog as in How to create a rounded title border in Java Swing. But it is still one color. I want to make the border looks like 3D.
Here is how I tried.
Graphics2D g2d = (Graphics2D) g;
Color c1 = getBackground();
Color c2 = color1.darker();
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(
0, 0, c1,
0, h, c2);
g2d.setPaint(gp);
g2d.fill3DRect(0,0, w, h,true);
Then, no 3D look, but the border has been widen more with its border color.
How can I achieve this?
Any sample code or links will be highly appreciated.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
public class ThreeDimensionalBorder extends AbstractBorder {
private static final long serialVersionUID = 1L;
private Color color;
private int thickness = 8;
private int radii = 8;
private Insets insets = null;
private BasicStroke stroke = null;
private int strokePad;
RenderingHints hints;
int shadowPad = 3;
ThreeDimensionalBorder(Color color) {
this(color, 128, 8);
}
ThreeDimensionalBorder(Color color, int transparency, int shadowWidth) {
this.color = color;
shadowPad = shadowWidth;
stroke = new BasicStroke(thickness);
strokePad = thickness/2;
hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int pad = radii + strokePad;
int bottomPad = pad + strokePad + shadowPad;
int rightPad = pad + strokePad + shadowPad;
insets = new Insets(pad,pad,bottomPad+shadowPad,rightPad);
}
#Override
public Insets getBorderInsets(Component c) {
return insets;
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
#Override
public void paintBorder(
Component c,
Graphics g,
int x, int y,
int width, int height) {
Graphics2D g2 = (Graphics2D)g;
int bottomLineY = height-thickness-shadowPad;
RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(
0+strokePad,
0+strokePad,
width-thickness-shadowPad,
bottomLineY,
radii,
radii
);
Area area = new Area(bubble);
g2.setRenderingHints(hints);
g2.setColor(color);
g2.setStroke(stroke);
g2.draw(area);
Area shadowArea = new Area(new Rectangle(0,0,width,height));
shadowArea.subtract(area);
g.setClip(shadowArea);
Color shadow = new Color(color.getRed(),color.getGreen(),color.getBlue(),128);
g2.setColor(shadow);
g2.translate(shadowPad,shadowPad);
g2.draw(area);
AffineTransform at = g2.getTransform();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel();
String t = "The quick brown fox jumps over the lazy dog!";
JLabel l1 = new JLabel(t);
l1.setBorder(new ThreeDimensionalBorder(Color.MAGENTA.darker(),128,4));
p.add(l1);
JLabel l2 = new JLabel(t);
l2.setBorder(new ThreeDimensionalBorder(Color.BLACK,200,5));
p.add(l2);
JLabel l3 = new JLabel(t);
l3.setBorder(new ThreeDimensionalBorder(Color.BLUE,40,6));
p.add(l3);
JOptionPane.showMessageDialog(null, p);
}
});
}
}
Would this suffice??
It's far from perfect, but the basic idea works...
public class MyRoundedBorder implements Border {
protected static final Insets DEFAULT_INSETS = new Insets(4, 4, 4, 4);
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.setColor(Color.WHITE);
Shape corner = new RoundedShape(width - 8, height - 8);
g2d.translate(x + 2, y + 2);
g2d.draw(corner);
g2d.transform(AffineTransform.getRotateInstance(Math.toRadians(180), (width - 8) / 2, (height - 8) / 2));
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(corner);
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
return DEFAULT_INSETS;
}
#Override
public boolean isBorderOpaque() {
return true;
}
public class RoundedShape extends Path2D.Float {
public RoundedShape(int width, int height) {
moveTo(0, height - 20);
append(new Arc2D.Float(0, height - 20, 20, 20, 180, 45, Arc2D.CHORD), false);
lineTo(0, 20);
curveTo(0, 0, 0, 0, 20, 0);
lineTo(width - 10, 0);
append(new Arc2D.Float(width - 20, 0, 20, 20, 90, -45, Arc2D.CHORD), false);
}
}
}

Categories