How to add imagepanel in jpanel inside Jframe? - java

I'm trying to add an imagepanel which extends JPanel to another JPanel. Which is not working well for me. The paint function of image panel don't get invoked inside Jpanel but works fine in JFrame. Any ideas or help will be appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
class ImagePanel extends JPanel
{
int g_h=10,g_w=10;
int width=50,height=50;
int cornerradius;
Image castle;
Dimension size;
protected int x1,y1;
Color c1=new Color(255, 0, 0);
Rectangle rec;
boolean b=false;
boolean imboo=false;
boolean roundb= false;
Graphics g= this.getGraphics();
protected int strokeSize = 1;
protected Color shadowColor = Color.BLACK;
boolean shadowed = false;
public ImagePanel()
{
//super();
setOpaque(false);
setLayout(null);
System.out.println("it executed");
}
public ImagePanel(int x, int y)
{
setSize(x, y);
}
public void setSize(int x,int y){
width=x;
height=y;
}
public int getheight(){
return height;
}
public int getwidth(){
return width;
}
public void setImagePanelBounds(
int x, int y, int width, int height){
x1=x;
y1=y;
this.width= width;
this.height= height;
System.out.println("6it executed");
}
public void setroundcorners(boolean b, int i){
roundb=b;
cornerradius=i;
System.out.println("5it executed");
}
public void setImage(String s){
imboo=true;
size = new Dimension();
castle = new ImageIcon(s).getImage();
size.width = castle.getWidth(null);
size.height = castle.getHeight(null);
setPreferredSize(size);
System.out.println("4it executed");
}
public void paint(Graphics gh){
System.out.println("it executed p");
{int x=this.getWidth();
int j=20,a=20;
Graphics2D g2= (Graphics2D)gh.create();
{
g2.setColor(Color.WHITE);
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.SrcAtop);
rec= new Rectangle(x1, y1, width, height);
//Start of If-else
if(roundb){
g2.setClip(new RoundRectangle2D.Float(
(int)rec.getX(),(int)rec.getY(),
(int)rec.getWidth(),(int)rec.getHeight(),
cornerradius, cornerradius));
System.out.println("it executed");
}
// End of If-Else
// Image condition Starts
if (imboo){
g2.drawImage(castle, (int)rec.getX(),
(int)rec.getY(), (int)rec.getWidth(),
(int)rec.getHeight(), null);
//g.drawImage(castle, (int)rec.getX(),(int)rec.getY(), null);
}
// Image condition Ends
g2.setColor(Color.BLUE);
}
}
}
public static void main(String[]args)
{
ImagePanel t1=new ImagePanel();
JPanel jp1= new JPanel();
jp1.add(t1);
jp1.setLayout(null);
jp1.setBounds(0, 0, 600, 600);
JFrame jf1= new JFrame("Testing");
t1.setImage("icons/1.png");
//t1.setImage("1.jpg");
t1.setLayout(null);
t1.setroundcorners(true, 10);
//t1.setShadow(true);
t1.add(new JLabel("niak"));
//t1.setShadowDimensions(18, 18, 305, 305, 12);
t1.setImagePanelBounds(20, 20, 100, 100);
// jf1.add(t1);
jf1.setSize(600, 600);
jf1.setDefaultCloseOperation(jf1.EXIT_ON_CLOSE);
jf1.setVisible(true);
//jf1.revalidate();
jf1.setLayout(null);
}
}

Let's start with...
Don't use getGraphics. This is not how to perform custom painting. getGraphics may return null and is, at best, a snapshot, which will be discard when the next paint cycle occurs.
JPanel already has getWidth, getHeight and setSize methods, you should never have a need to overridden them. Instead, you should override getPreferredSize and return a size hint back that the parent layout manager can use.
If you create a Graphics context, you should dispose of it. In your paint method, you use gh.create, this is consuming resources and under some systems, until the Graphics context is disposed, it may not actually paint anything.
Don't override paint, instead use paintComponent
DO NOT modify the clip rectangle. Seriously, this is going to cause you more issues then you can imagine.
Don't use null layout managers without EXTREMELY good reason.
JPanel has a setBounds method, while, under normal circumstances, you shouldn't need to use it, since you've thrown away the layout manager, you should use it.
Basically, you've discard all the inner workings of the JPanel that enable the paint system to know that it should actually paint your panel
Updated with example
As an example...
Instead of using the clip, I use a masking technique, and mask the shape I want over the source image. I also buffer the result, which should make it more memory conservative as well as render faster
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class ImagePaneExample {
public static void main(String[] args) {
new ImagePaneExample();
}
public ImagePaneExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
BufferedImage img = ImageIO.read(new File("C:\\hold\\thumbnails\\2005-09-29-3957.jpeg"));
ImagePane imgPane = new ImagePane();
imgPane.setImage(img);
imgPane.setRounded(true);
imgPane.setBorder(new EmptyBorder(20, 20, 20, 20));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(imgPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
public class ImagePane extends JPanel {
private BufferedImage img;
private BufferedImage renderImg;
private boolean rounded;
public ImagePane() {
}
public void setRounded(boolean value) {
if (value != rounded) {
rounded = value;
renderImg = null;
firePropertyChange("rounded", !rounded, rounded);
repaint();
}
}
public boolean isRounded() {
return rounded;
}
public void setImage(BufferedImage value) {
if (value != img) {
BufferedImage old = img;
img = value;
renderImg = null;
firePropertyChange("image", old, img);
repaint();
}
}
public BufferedImage getImage() {
return img;
}
#Override
public Dimension getPreferredSize() {
Dimension size = img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
Insets insets = getInsets();
size.width += (insets.left + insets.right);
size.height += (insets.top + insets.bottom);
return size;
}
protected void applyQualityRenderHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
protected BufferedImage getImageToRender() {
if (renderImg == null) {
BufferedImage source = getImage();
if (source != null) {
if (isRounded()) {
BufferedImage mask = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, mask.getWidth(), mask.getHeight());
g2d.setBackground(new Color(255, 255, 255, 255));
g2d.fillRoundRect(0, 0, mask.getWidth(), mask.getHeight(), 40, 40);
g2d.dispose();
BufferedImage comp = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = comp.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, source.getWidth(), source.getHeight());
g2d.drawImage(source, 0, 0, this);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
g2d.drawImage(mask, 0, 0, this);
g2d.dispose();
renderImg = comp;
} else {
renderImg = source;
}
}
}
return renderImg;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = getImageToRender();
System.out.println(img);
if (img != null) {
Insets insets = getInsets();
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int x = ((width - img.getWidth()) / 2);
int y = ((height - img.getHeight()) / 2);
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
I'd recommend some more reading through Creating a UI with Swing, in particular the section on layout managers, as well as Performing Custom Painting and Painting in AWT and Swing

All you have to do is to set the Layout of your panel jp1 to BorderLayout and add the image panel t1 to BorderLayout.CENTER, like this:
JPanel jp1= new JPanel(new BorderLayout());
jp1.add(t1, BorderLayout.CENTER);

Related

How can I darken a rectangular part of an image in Java?

The code creates a JFrame with a JPanel onto which it draws an image loaded from a file. The objective is to make a rectangular area of the picture, such as for example the red square, appear darker than the rest. I'm assuming this may involve taking a subimage of the image, looping through an array of pixels, scaling them, and then painting that subimage onto the JPanel, but I don't know how to do this using the Java API.
package SpriteEditor_Tests;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class ImageTestApp extends JFrame
{
public BufferedImage image;
int x1 = 50;
int x2 = 100;
int y1 = 50;
int y2 = 100;
public static void main (String [] args)
{
new ImageTestApp();
}
public ImageTestApp()
{
setTitle("Image Test App");
try
{
image = ImageIO.read(new File("C:/Users/Paul/Desktop/derp.png"));
}
catch (IOException io)
{
System.out.println("IO caught"); System.exit(0);
}
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
add(new ImageDisplay());
}
class ImageDisplay extends JPanel
{
public void paintComponent(Graphics g)
{
g.drawImage(image, -100, -100, getWidth(), getHeight(), Color.RED, null);
g.setColor(Color.RED);
g.drawRect(x1, y1, Math.abs(x2 - x1), Math.abs(y2 - y1));
}
}
}
A "simple" solution would be to just create a new instance of Color with the desired alpha applied to it and fill the area you want darkened.
This is great if you have a color you want to use, but when I want to use a predefined color, it's not as simple. Instead, I prefer to use an AlphaComposite as it gives me some advantages.
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage background;
public TestPane() {
try {
background = ImageIO.read(getClass().getResource("/images/background.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
if (background == null) {
return new Dimension(200, 200);
}
return new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
int x = (getWidth() - 100) / 2;
int y = (getHeight() - 100) / 2;
Rectangle rect = new Rectangle(x, y, 200, 200);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.fill(rect);
g2d.dispose();
g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.drawRect(x, y, 200, 200);
g2d.dispose();
}
}
}
Now, if want to generate a new image with the are darkened, you can follow the same basic concept, but instead of painting to the components Graphics context, you'd paint directly to the BufferedImages Graphics content. This is the wonderful power of the abstract nature of the Graphics API.
Don't forget, when you override a method, you are obliged to either over take ALL of its responsibilities or call its super implementation.
paintComponent does some basic, but important work and you should make sure to call super.paintComponent before you start performing your custom painting, this will just reduce any possibility of issues.
Darken each pixel individually
Okay, if, instead, you want to darken each pixel in the rectangle individually, this becomes a "little" more complicated, but not hard.
After a lot of time and testing, I settled on using the follow algorithm to darken a given color. This will push the color towards "black" the more you darken it, which some algorithms don't do.
public static Color darken(Color color, double fraction) {
int red = (int) Math.round(Math.max(0, color.getRed() - 255 * fraction));
int green = (int) Math.round(Math.max(0, color.getGreen() - 255 * fraction));
int blue = (int) Math.round(Math.max(0, color.getBlue() - 255 * fraction));
int alpha = color.getAlpha();
return new Color(red, green, blue, alpha);
}
Then, all you have to do is get the the color of the pixel, darken it and reapply.
For this example, I actually use a separate sub image, but you can do it directly to the parent image
BufferedImage subImage = background.getSubimage(x, y, 200, 200);
for (int row = 0; row < subImage.getHeight(); row++) {
for (int col = 0; col < subImage.getWidth(); col++) {
int packedPixel = subImage.getRGB(col, row);
Color color = new Color(packedPixel, true);
color = darken(color, 0.5);
subImage.setRGB(col, row, color.getRGB());
}
}
Now, before someone jumps down my throat, no, this is not the most performant approach, but it gets over messing about with "packed" pixel values (because I can never remember how to unpack those :P) and most of my API code is based around the use of Color anyway
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setVisible(true);
}
});
}
public static Color darken(Color color, double fraction) {
int red = (int) Math.round(Math.max(0, color.getRed() - 255 * fraction));
int green = (int) Math.round(Math.max(0, color.getGreen() - 255 * fraction));
int blue = (int) Math.round(Math.max(0, color.getBlue() - 255 * fraction));
int alpha = color.getAlpha();
return new Color(red, green, blue, alpha);
}
public class TestPane extends JPanel {
private BufferedImage background;
private BufferedImage darkended;
public TestPane() {
try {
background = ImageIO.read(getClass().getResource("/images/background.jpg"));
int x = (background.getWidth() - 100) / 2;
int y = (background.getHeight() - 100) / 2;
BufferedImage subImage = background.getSubimage(x, y, 200, 200);
for (int row = 0; row < subImage.getHeight(); row++) {
for (int col = 0; col < subImage.getWidth(); col++) {
int packedPixel = subImage.getRGB(col, row);
Color color = new Color(packedPixel, true);
color = darken(color, 0.5);
subImage.setRGB(col, row, color.getRGB());
}
}
darkended = subImage;
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
if (background == null) {
return new Dimension(200, 200);
}
return new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
int x = (getWidth() - 100) / 2;
int y = (getHeight() - 100) / 2;
g2d.drawImage(darkended, x, y, this);
g2d.setColor(Color.RED);
g2d.drawRect(x, y, 200, 200);
g2d.dispose();
}
}
}

Wrap image to Jframe

I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
The objective with this solution is to convert a PDF to a image, identify a particular area using the visual mapper and then use PDFBox (PDFTextStripperbyArea) to extract against this area.
The co-ordinates being given by the below code is not extracting the required area's.
This is the code:
public class PDFVisualMapper extends JFrame {
BufferedImage image = null;
public static void main(String[] args) throws IOException {
new PDFVisualMapper();
}
public PDFVisualMapper() throws IOException {
this.setSize(1700, 2200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new PaintSurface(), BorderLayout.CENTER);
this.setVisible(true);
}
private class PaintSurface extends JComponent {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public PaintSurface() throws IOException {
image = ImageIO.read(new File("C:\\Users\\Rusty\\Desktop\\temp\\Test_PDF-1.png"));
if ( image != null ) {
Dimension size = new Dimension(image.getWidth(null), image.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
private void paintBackground(Graphics2D g2) {
g2.setPaint(Color.LIGHT_GRAY);
for (int i = 0; i < getSize().width; i += 10) {
Shape line = new Line2D.Float(i, 0, i, getSize().height);
g2.draw(line);
}
for (int i = 0; i < getSize().height; i += 10) {
Shape line = new Line2D.Float(0, i, getSize().width, i);
g2.draw(line);
}
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(g2);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.drawImage(image, null, 0, 0);
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
Can anybody help?
This might be simpler: using a JLabel within the contentpane, using FlowLayout:
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class WarpImage {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException{
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
BufferedImage image = ImageIO.read(url);
ImageIcon icon= new ImageIcon(image);
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel lbl= new JLabel();
lbl.setIcon(icon);
frame.add(lbl);
frame.pack();
//check size :
Rectangle bounds = lbl.getBounds();
System.out.println(bounds.getWidth() +"-"+ bounds.getHeight());
frame.setVisible(true);
}
}
I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
Then you paint the image yourself. Why? Because components like JLabel have their own internal layout mechanics which provide no way for you to determine the offset of the image within in, if the image is to large or to small for the component size.
Something like this, for example:
public class ImagePane extends JPanel {
private BufferedImage img;
public ImagePane(BufferedImage img) {
this.img = img;
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(0, 0) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(img, 0, 0, this);
g2.dispose();
}
}
}
This places the image in the top left corner of the component, so if it's resized for some reason, the image will always be in the top left position. To be frank, it wouldn't be hard to generate an offset to allow the image to be centred, this could then be used by decedents of the component to calculate the offset required to adjust their own output as needed

Drawing the shape of an image

In Java swing, is there any way to draw only the shape of an image, instead of the image itself? And if so, how can I do it?
I added a picture to show you what I mean:
.
My image would consist of a one-colored shape and a transparent background. My intention is to be able to change the images color.
ImageFilter is what you sought. GrayFilter could be used.
class ShapeFilter extends RGBImageFilter {
public RedBlueSwapFilter() {
// The filter's operation does not depend on the
// pixel's location, so IndexColorModels can be
// filtered directly.
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb) {
return (rgb & 0x00_ff_ff_ff) == 0x00_ff_ff_ff // White
|| rgb & 0xff_00_00_00) == 0x00_00_00) // or transparent
? rgb : 0xff_ff_00_00; // Red opaque
}
}
Usage inside a Component (JComponent) with createImage:
Image img = ImageIO.readImage(...);
ImageFilter filter = new ShapeFilter();
ImageProducer producer = new FilteredImageSource(img.getSource(), filter);
Image img2 = createImage(producer);
You could generate a "mask" of the image
The great feature of this technique is that you can generate the mask in what ever color or opacity you want
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Transparency;
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;
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 (Exception ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) {
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = imgMask.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(imgSource, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
g2.setColor(color);
g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
g2.dispose();
return imgMask;
}
public BufferedImage tint(BufferedImage master, BufferedImage tint) {
int imgWidth = master.getWidth();
int imgHeight = master.getHeight();
BufferedImage tinted = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = tinted.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(master, 0, 0, null);
g2.drawImage(tint, 0, 0, null);
g2.dispose();
return tinted;
}
public class TestPane extends JPanel {
private BufferedImage master;
private BufferedImage mask;
public TestPane() {
try {
master = ImageIO.read(new File(bring your own image));
mask = generateMask(master, Color.RED, 1.0f);
} catch (IOException exp) {
exp.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
if (master != null && mask != null) {
size = new Dimension(master.getWidth() + mask.getWidth(), Math.max(master.getHeight(), mask.getHeight()));
}
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = (getWidth() - (master.getWidth() + mask.getWidth())) / 2;
int y = (getHeight() - master.getHeight()) / 2;
g.drawImage(master, x, y, this);
x += mask.getWidth();
y = (getHeight() - mask.getHeight()) / 2;
g.drawImage(mask, x, y, this);
}
}
}

Write a text on JDeskopPane

I want to write a multiline text (3-4 lines is ok) on the bottom right corner of a JDesktopPane, how can I do this?
The text is not fixed, it can change every time i start the swing application but once the application is started it remains the same, I don't need to update from the application.
My first thought was to create an image, put it as background of the JDesktopPane and then write on it, but it doesn't seem a simple solution.
Thanks for the help.
Combining the examples seen here and here, the print() method in the variation below illustrates using FontMetrics to right justify multiple lines of text in the bottom, right corner of a JDesktopPane.
import java.awt.*;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
/** #see http://stackoverflow.com/a/45055215/230513 */
public class JDPTest extends JDesktopPane {
private MyFrame one = new MyFrame("One", 100, 100);
public JDPTest() {
this.setPreferredSize(new Dimension(640, 480));
this.add(one);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.lightGray);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
g2d.setFont(new Font(Font.SERIF, Font.BOLD, 16));
print(g2d, 3, "Hello, world!");
print(g2d, 2, "This is a test.");
print(g2d, 1, "This is another test.");
print(g2d, 0, "This is still another test.");
}
private void print(Graphics2D g2d, int line, String s) {
FontMetrics fm = g2d.getFontMetrics();
int x = this.getWidth() - fm.stringWidth(s) - 5;
int y = this.getHeight() - fm.getDescent()
- line * (fm.getHeight() + fm.getLeading());
g2d.drawString(s, x, y);
}
private final class MyFrame extends JInternalFrame {
MyFrame(String name, int x, int y) {
super(name, true, true, true, true);
this.setSize(320, 240);
this.setLocation(x, y);
this.setVisible(true);
}
}
private void display() {
JFrame f = new JFrame("JDPTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JDPTest().display();
}
});
}
}
Use this example class.
The background if set will be scaled.
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.swing.JDesktopPane;
public class MyDesktopPane extends JDesktopPane {
Image img;
public MyDesktopPane() {
super();
}
#Override
public void paintComponent(Graphics g) {
int width = this.getWidth();
int height = this.getHeight();
int infoWidth = 150;
int infoHeight = 100;
super.paintComponent(g);
// alpha
final Float alpha = new Float(0.9);
final Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(makeComposite(alpha.floatValue()));
// draw bacground image is set
if (img != null) {
g.drawImage(img, 0, 0, width, height, this);
}
//draw 3 line text in red reound rectangle
g.setColor(Color.RED);
g.fillRoundRect(width - infoWidth, height - infoHeight, infoWidth, infoHeight, 5, 5);
g.setColor(Color.BLACK);
g.drawString("Line 1", width - infoWidth + 5, height - infoHeight + 20);
g.drawString("Line 2", width - infoWidth + 5, height - infoHeight + 40);
g.drawString("Line 3", width - infoWidth + 5, height - infoHeight + 60);
}
public void setBackGroundImage(String path) {
try {
boolean file = new File(path).isFile();
if (file) {
img = javax.imageio.ImageIO.read(new FileInputStream(path));
}
} catch (IOException e) {
e.printStackTrace();
}
this.repaint();
}
private AlphaComposite makeComposite(final float alpha) {
final int type = AlphaComposite.SRC_OVER;
return (AlphaComposite.getInstance(type, alpha));
}
}

Rotate image without clear background

i have read about a lot of articles of drawing images, but i cant get those to work when i need to keep the background. I'm trying to rotate an image which is over another image after click on a JButton. The background image is generated on a JPanel by:
public void paintComponent(Graphics g){
int index = 0;
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g);
try {
image = ImageIO.read(url1);
image2 = ImageIO.read(url2);
image3 = ImageIO.read(url3);
} catch (IOException e) {
}
g.drawImage(image, 0, 0, null);
g.drawImage(image3, 0, 0, null);
if(scaleDrawnFlag == 0){
for(index = 0; index < 60; index ++){
tx = AffineTransform.getRotateInstance(Math.toRadians(6*index), this.getHeight()/2, this.getWidth()/2);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(image3, null), 0, 0, null);
}
scaleDrawnFlag = 1;
}
g.drawImage(image2, 0, 0, null);
}
Which is into a JPanel named panel and draw a image only one time to keep the refresh performance, only for the animated image. This draws a scale for a tachometer, by a total of 60 lines, where each line is a copy of image3
The animated image, is generated by pressing a JButton, and is made by:
public void paintComponent(Graphics g){
super.paintComponent(g);
BufferedImage img = new BufferedImage(370, 370, BufferedImage.TRANSLUCENT);
Graphics2D g2d = img.createGraphics();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
Graphics2D temp = (Graphics2D) g;
tx = AffineTransform.getRotateInstance(Math.toRadians(degrees), this.getHeight()/2, this.getWidth()/2);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
temp.drawImage(op.filter(image2, null), 0, 0, null);
temp.dispose();
}
Which is into another JPanel named overPanel, which is over the initial JPanel.
But, when i call the methods:
public void up(){
degrees ++;
if(degrees == 360) degrees = 0;
repaint();
}
public void down(){
degrees --;
if(degrees == -360) degrees = 0;
repaint();
}
Which are on the overPanel class, the JPanel is entirely cleared. The animation is working well but, the Background disappear.
What must i do to keep the Background?
I also tried another solution, by drawing the 60 lines again on every up() and down() call. The background is repainted, but takes too much time to complete, so, the animation to rotate the tachometer's indicator lags.
Never dispose of a Graphics object given to you by the JVM. You're doing this:
// temp **is** the same object as g and is the Graphics object given by the JVM
Graphics2D temp = (Graphics2D) g;
//....
temp.dispose();
and shouldn't do it since it completely breaks the painting chain. You should instead be disposing of the g2d object, one you created.
Also, this would be OK
Graphics2D temp = (Graphics2D) g.create(); // temp **is** a new object
//....
temp.dispose(); // this is OK
Other issues:
I also wouldn't be creating my BufferedImage inside of paintComponent but rather would make it a field of the class, and display it inside paintComponent.
Your top code shows ignored critical exceptions -- you don't want to do this.
It also shows reading in of image files within a painting method, something that will unnecessarily slow down graphics. Again, don't do this, read in the images once outside of any painting method, store the results, and use them in the painting method.
The paintComponent method is protected, not public. Avoid increasing its visibility unnecessarily.
In your minimal example program, your scaleDrawnFlag variable and its associated if-block appear to be messing you up. What is the purpose of that variable and the if block? If you get rid of the variable and the if block, your background would persist. Myself, I'd do things differently by creating a stable background image and drawing it every time in the paintComponent(...) method. I would not override update(...) either as that's an AWT kludge and not for Swing graphics. I also try to avoid null layouts and setBounds(...) like the plague since that leads to inflexible, rigid GUI's that are very difficult to debug, maintain and enhance. For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyMainPanel extends JPanel {
private MyDrawingPanel myDrawingPanel;
public MyMainPanel() {
try {
myDrawingPanel = new MyDrawingPanel();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new GridLayout(0, 1, 5, 5));
rightPanel.add(new JButton(new MyUpAction("Up", KeyEvent.VK_U)));
rightPanel.add(new JButton(new MyDownAction("Down", KeyEvent.VK_D)));
JPanel rightWrapPanel = new JPanel(new BorderLayout());
rightWrapPanel.add(rightPanel, BorderLayout.PAGE_START);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout());
add(myDrawingPanel, BorderLayout.CENTER);
add(rightWrapPanel, BorderLayout.LINE_END);
}
private class MyUpAction extends AbstractAction {
public MyUpAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
myDrawingPanel.up();
}
}
private class MyDownAction extends AbstractAction {
public MyDownAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
myDrawingPanel.down();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("MyMainPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class MyDrawingPanel extends JPanel {
private static final String NEEDLE_IMG_PATH = "http://1.bp.blogspot.com/"
+ "-fq-oPGBSLp4/Ttoj7DoAMWI/AAAAAAAABtc/t7gKJlfRQuo/s400/secondHand.png";
private static final String ORANGE_DISK_IMG_PATH = "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Circle_Fulvous_Solid.svg/200px-Circle_Fulvous_Solid.svg.png";
private static final String GREEN_LINE_IMG_PATH = "http://www.xtremeskater.com/math/images/circle_radius.png";
private static final int MAX_DEGREES = 360;
private int imgWidth = 0;
private int imgHeight = 0;
private BufferedImage needleImg = null;
private BufferedImage orangeDiskImg = null;
private BufferedImage greenLineImg = null;
private BufferedImage backgroundImg = null;
private int degrees;
public MyDrawingPanel() throws IOException {
URL needleUrl = new URL(NEEDLE_IMG_PATH);
URL orangeDiskUrl = new URL(ORANGE_DISK_IMG_PATH);
URL greenLineUrl = new URL(GREEN_LINE_IMG_PATH);
needleImg = ImageIO.read(needleUrl);
orangeDiskImg = ImageIO.read(orangeDiskUrl);
greenLineImg = ImageIO.read(greenLineUrl);
imgWidth = Math.max(orangeDiskImg.getWidth(),
greenLineImg.getWidth());
imgHeight = Math.max(orangeDiskImg.getHeight(),
greenLineImg.getHeight());
backgroundImg = new BufferedImage(imgWidth, imgHeight,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = backgroundImg.createGraphics();
drawBackground(g2, imgWidth, imgHeight);
g2.dispose();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(imgWidth, imgHeight);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, null);
}
AffineTransform tx = AffineTransform.getRotateInstance(Math.toRadians(degrees),
this.getHeight() / 2, this.getWidth() / 2);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(needleImg, null), 0, 0, null);
}
public void up() {
degrees++;
degrees %= MAX_DEGREES;
repaint();
}
public void down() {
degrees--;
degrees += MAX_DEGREES;
degrees %= MAX_DEGREES;
repaint();
}
public int getDregrees() {
return degrees;
}
private void drawBackground(Graphics2D g2, int biWidth, int biHeight) {
int index;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(orangeDiskImg, 0, 0, null);
g2.drawImage(greenLineImg, 0, 0, null);
AffineTransform tx = AffineTransform.getRotateInstance(Math.toRadians(6),
biWidth / 2, biHeight / 2);
for (index = 0; index < 60; index++) {
g2.transform(tx);
g2.drawImage(greenLineImg, 0, 0, null);
}
}
}
i have found the way to make the Background permanent, by first creating it into a Buffered image, then on each action, repaint that image, without redraw all the primitive forms or the image rotations. I mean, first, i create the Background rotating a basic image multiple times. This is created using a Buffered image. Then, on the paintComponent() method, i redraw the buffered image:
public MyPanel(){
try {
image = ImageIO.read(url1);
image2 = ImageIO.read(url2);
image3 = ImageIO.read(url3);
} catch (IOException e) {
}
img = createImage();
}
private Image createImage(){
double index = 0;
BufferedImage bufferedImage = new BufferedImage(370,370,BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
for(index = 0; index <= scale; index = index + count){
tx = AffineTransform.getRotateInstance(Math.toRadians(deg2), 185, 185);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(image3, null), 0, 0, null);
deg2 = deg2 + (270.0/(scale/count));
}
return bufferedImage;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 0, 0, null); //Indicator drawing
g.drawImage(img, 0, 0, null); //Scale drawing
//Indicator rotation
tx = AffineTransform.getRotateInstance(Math.toRadians(degrees), this.getHeight()/2, this.getWidth()/2);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(image2, null), 0, 0, null);
}
Here the complete code for a basic example:
package rotateOnImage;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.AbstractAction;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.swing.Action;
public class MainFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private MyPanel panel = new MyPanel();
private final Action upAction = new upAction();
private final Action dnAction = new dnAction();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 345, 227);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnNewButton = new JButton("UP");
btnNewButton.setAction(upAction);
btnNewButton.setBounds(212, 12, 117, 25);
contentPane.add(btnNewButton);
JButton button = new JButton("DN");
button.setAction(dnAction);
button.setBounds(212, 49, 117, 25);
contentPane.add(button);
panel.setBounds(0, 0, 200, 200);
contentPane.add(panel);
}
private class upAction extends AbstractAction {
/**
*
*/
private static final long serialVersionUID = 1L;
public upAction() {
putValue(NAME, "UP");
}
public void actionPerformed(ActionEvent e) {
panel.up();
}
}
private class dnAction extends AbstractAction {
/**
*
*/
private static final long serialVersionUID = 1L;
public dnAction() {
putValue(NAME, "DN");
}
public void actionPerformed(ActionEvent e) {
panel.down();
}
}
}
class MyPanel extends JPanel{
private static final long serialVersionUID = 1L;
/**
*
*/
private int degrees = 0;
private AffineTransform tx = null;
private AffineTransformOp op = null;
private BufferedImage image1 = null;
private BufferedImage image2 = null;
private BufferedImage image3 = null;
Image img = null;
public static final String IMAGE_PATH1 = "http://1.bp.blogspot.com/"+"-fq-oPGBSLp4/Ttoj7DoAMWI/AAAAAAAABtc/t7gKJlfRQuo/s400/secondHand.png";
public static final String IMAGE_PATH2 = "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Circle_Fulvous_Solid.svg/200px-Circle_Fulvous_Solid.svg.png";
public static final String IMAGE_PATH3 ="http://www.xtremeskater.com/math/images/circle_radius.png";
public MyPanel(){
try {
URL url1 = new URL(IMAGE_PATH1);
URL url2 = new URL(IMAGE_PATH2);
URL url3 = new URL(IMAGE_PATH3);
image1 = ImageIO.read(url1);
image2 = ImageIO.read(url2);
image3 = ImageIO.read(url3);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
img = createImage();
}
public void up(){
degrees ++;
if(degrees == 360) degrees = 0;
repaint();
}
public void down(){
degrees --;
if(degrees == -360) degrees = 0;
repaint();
}
public int getDregrees(){
return degrees;
}
private Image createImage(){
double index = 0.0;
BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
for(index = 0.0; index <= 36; index ++){
tx = AffineTransform.getRotateInstance(Math.toRadians(index*10), 100, 100);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(image3, null), 0, 0, null);
}
return bufferedImage;
}
public void update(Graphics g){
paint(g);
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image2, 0, 0, null); //Dibujado de la manecilla
g.drawImage(img, 0, 0, null); //Dibujado de la escala
//RotaciĆ³n de la manecilla
tx = AffineTransform.getRotateInstance(Math.toRadians(degrees), this.getHeight()/2, this.getWidth()/2);
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
g.drawImage(op.filter(image1, null), 0, 0, null);
}
}

Categories