Okay, I'm using code from a book about Java, which displays 4 PNG's and 1 JPG under some text. They provide me with code and the images are downloadable from the site, which i downloaded. To upload the images to eclipse, I made a source folder in my project to keep the images. I then uploaded my images to the "images" source folder by doing New>File>2DGraphicsTest>LinkToFileSystem> and then i selected my image. But for some reason, when i run the following code i just get the text that goes above my pictures....
My question is, how do i upload the images properly so that the loadImage(image) thing gets it?
Code:
import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class ImageTest extends JFrame {
public static void main(String[] args) {
DisplayMode displayMode;
if (args.length == 3) {
displayMode = new DisplayMode(
Integer.parseInt(args[0]),
Integer.parseInt(args[1]),
Integer.parseInt(args[2]),
DisplayMode.REFRESH_RATE_UNKNOWN);
}
else {
displayMode = new DisplayMode(800, 600, 16,
DisplayMode.REFRESH_RATE_UNKNOWN);
}
ImageTest test = new ImageTest();
test.run(displayMode);
}
private static final int FONT_SIZE = 24;
private static final long DEMO_TIME = 10000;
private SimpleScreenManager screen;
private Image bgImage;
private Image opaqueImage;
private Image transparentImage;
private Image translucentImage;
private Image antiAliasedImage;
private boolean imagesLoaded;
public void run(DisplayMode displayMode) {
setBackground(Color.blue);
setForeground(Color.black);
setFont(new Font("Consolas", Font.PLAIN, FONT_SIZE));
imagesLoaded = false;
screen = new SimpleScreenManager();
try {
screen.setFullScreen(displayMode, this);
loadImages();
try {
Thread.sleep(DEMO_TIME);
}
catch (InterruptedException ex) { }
}
finally {
screen.restoreScreen();
}
}
public void loadImages() {
bgImage = loadImage("images/background.jpg");
opaqueImage = loadImage("images/opaque.png");
transparentImage = loadImage("images/transparent.png");
translucentImage = loadImage("images/translucent.png");
antiAliasedImage = loadImage("images/antialiased.png");
imagesLoaded = true;
// signal to AWT to repaint this window
repaint();
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
public void paint(Graphics g) {
// set text anti-aliasing
if (g instanceof Graphics2D) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
// draw images
if (imagesLoaded) {
g.drawImage(bgImage, 0, 0, null);
drawImage(g, opaqueImage, 0, 0, "Opaque");
drawImage(g, transparentImage, 320, 0, "Transparent");
drawImage(g, translucentImage, 0, 300, "Translucent");
drawImage(g, antiAliasedImage, 320, 300,
"Translucent (Anti-Aliased)");
}
else {
g.drawString("Loading Images...", 5, FONT_SIZE);
}
}
public void drawImage(Graphics g, Image image, int x, int y,
String caption)
{
g.drawImage(image, x, y, null);
g.drawString(caption, x + 5, y + FONT_SIZE +
image.getHeight(null));
}
}
Related
I've decided on making a HUD with the picture above, but I don't know what command in Java I need to use so as I can fill the top half and the bottom half separately.
I only know how to use the g.fillRect(); command, and it will take around twenty of these commands to fill said half.
public class HUD {
private Player player;
private BufferedImage image;
private Font font;
private Font font2;
private int Phealth = Player.getHealth();
public HUD(Player p) {
player = p;
try {
image = ImageIO.read(getClass().getResourceAsStream("/HUD/HUD_TEST.gif"));
font = new Font("Arial", Font.PLAIN, 10);
font2 = new Font("SANS_SERIF", Font.BOLD, 10);
}
catch(Exception e) {
e.printStackTrace();
}
}
public void draw(Graphics2D g) {
g.drawImage(image, 0, 10, null);
g.setFont(font2);
g.setColor(Color.black);
g.drawString("Health:", 30, 22);
g.drawString("Mana:", 25, 47);
g.setFont(font);
g.drawString(Player.getHealth() + "/" + player.getMaxHealth(), 64, 22);
g.drawString(player.getCubes() / 100 + "/" + player.getMaxCubes() / 100, 55, 47);
g.setColor(Color.red);
g.fillRect(1, 25, Phealth * 25, 4);
g.setColor(Color.blue);
g.fillRect(1, 31, player.getCubes() / 33, 4);
}
}
This is the code for the HUD so far.
Any help in filling the shape will help.
Removed Idea #1! (It didn't seem to work.)
Okay, Idea #2:
Image1
Image2
Image3
So, there are 3 .png images.
Draw Image1 first, followed by drawing Image2 and Image3 directly on top of it.
To fill up either the red/blue bars, clip Image2 and Image3 accordingly (i.e. cut away their left sides)
Take a look at this on clipping.
This will require some minor calculations on how much to clip, based on the HP/Mana of the Player, but it should be good enough.
This is what it should look like (Clipping and overlaying done in Paint)
UPDATE (Problem solved, using Idea #2!):
Code:
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
#SuppressWarnings("serial")
public class TestGraphics extends JFrame implements ActionListener
{
JPanel utilBar = new JPanel();
JButton hpUpBtn = new JButton("HP++");
JButton hpDownBtn = new JButton("HP--");
JButton mpUpBtn = new JButton("MP++");
JButton mpDownBtn = new JButton("MP--");
GraphicsPanel drawingArea = new GraphicsPanel();
TestGraphics()
{
setSize(600, 500);
setLayout(new BorderLayout());
add(utilBar, BorderLayout.NORTH);
utilBar.setLayout(new GridLayout(1, 4));
utilBar.add(hpUpBtn);
utilBar.add(hpDownBtn);
utilBar.add(mpUpBtn);
utilBar.add(mpDownBtn);
add(drawingArea, BorderLayout.CENTER);
hpUpBtn.addActionListener(this);
hpDownBtn.addActionListener(this);
mpUpBtn.addActionListener(this);
mpDownBtn.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == hpUpBtn) {
drawingArea.incHp();
}
else if (e.getSource() == hpDownBtn) {
drawingArea.decHp();
}
else if (e.getSource() == mpUpBtn) {
drawingArea.incMp();
}
else if (e.getSource() == mpDownBtn) {
drawingArea.decMp();
}
System.out.println("Player HP: " + drawingArea.getHp() +
" Player MP: " + drawingArea.getMp());
drawingArea.revalidate();
drawingArea.repaint();
}
public static void main(String[]agrs)
{
new TestGraphics();
}
}
#SuppressWarnings("serial")
class GraphicsPanel extends JPanel {
private static int baseX = 150;
private static int baseY = 150;
private static final int BAR_FULL = 287;
private static final int BAR_EMPTY = 8;
private BufferedImage image1 = null;
private BufferedImage image2 = null;
private BufferedImage image3 = null;
private int playerHp = 100;
private int playerMp = 100;
public GraphicsPanel() {
try {
// All 3 images are the same as those posted in answer
image1 = ImageIO.read(
getClass().getResourceAsStream("/Image1.png"));
image2 = ImageIO.read(
getClass().getResourceAsStream("/Image2.png"));
image3 = ImageIO.read(
getClass().getResourceAsStream("/Image3.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void incHp() { playerHp += (playerHp < 100) ? 5 : 0; }
public void decHp() { playerHp -= (playerHp > 0) ? 5 : 0; }
public void incMp() { playerMp += (playerMp < 100) ? 5 : 0; }
public void decMp() { playerMp -= (playerMp > 0) ? 5 : 0; }
public int getHp() { return playerHp; }
public int getMp() { return playerMp; }
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Clear the graphics
g.setClip(null);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 600, 600);
g.drawImage(image1, baseX, baseY, null);
int hpPerc = (int) ((BAR_FULL - BAR_EMPTY) * (playerHp / 100.0));
g.setClip(baseX + BAR_EMPTY + hpPerc, 0, 600, 500);
g.drawImage(image2, baseX, baseY, null);
g.setClip(null);
int mpPerc = (int) ((BAR_FULL - BAR_EMPTY) * (playerMp / 100.0));
g.setClip(baseX + BAR_EMPTY + mpPerc, 0, 600, 500);
g.drawImage(image3, baseX, baseY + 78, null);
g.setClip(null);
}
}
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);
}
}
I'm kinda doing a GUI where when you press the "NEXT" button, it shows one by one the images at some directory.
My question is: How can I fit the size of the IMGs with the JPanles dimensions, I'm working with 6 or more MP images and I need to see the entire image.
Here is the code that gives me the imageIcon and where I add it to the JPanel.
JButton btnNextImg = new JButton("Next IMG");
btnNextImg.setBounds(96, 179, 110, 23);
btnNextImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (i == nImg)
i = 0;
try {
selectedImage = ImageIO.read(new File("C:\\IMAGES\\"+ String.valueOf(i+1) + ".jpg"));
iSelect = new ImageIcon(selectedImage);
originalImage.setIcon(iSelect);
} catch (IOException e1) {
e1.printStackTrace();
}
i++;
}
});
contentPane.add(btnNextImg);
And where I add it.
JPanel panel = new JPanel();
originalImage = new JLabel();
panel.add(originalImage);
panel.setBounds(5, 226, 309, 280);
contentPane.add(panel);
Thank you so much.
here's an image panel i found somewhere on the internet when i had the same problem:
public class ImagePanel extends JPanel {
private java.awt.Image image;
private boolean stretched = true;
private int xCoordinate;
private int yCoordinate;
public ImagePanel() {
}
public ImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
if (isStretched()) {
g.drawImage(image, xCoordinate, yCoordinate, getWidth(), getHeight(), this);
} else {
g.drawImage(image, xCoordinate, yCoordinate, this);
}
}
}
public java.awt.Image getImage() {
return image;
}
public void setImage(java.awt.Image image) {
this.image = image;
repaint();
}
public boolean isStretched() {
return stretched;
}
public void setStretched(boolean stretched) {
this.stretched = stretched;
repaint();
}
public int getXCoordinate() {
return xCoordinate;
}
public void setXCoodinate(int xCoordinate) {
this.xCoordinate = xCoordinate;
}
public int getYCoordinate() {
return xCoordinate;
}
public void setYCoordinate(int yCoordinate) {
this.yCoordinate = yCoordinate;
repaint();
}
}
to add an image to the panel use something like this:
ImagePanel imagePanel = new ImagePanel();
BufferedImage image = ImageIO.read(new File("C:\\IMAGES\\"+ String.valueOf(i+1) + ".jpg"));
imagePanel.setImage(image);
Here is the code that gives me the imageIcon and where I add it to the JPanel.
Check out Darryl's Stretch Icon. It will allow the Icon to fill the entire space available to the JLabel.
package main;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class ImageTest extends JFrame {
public static void main(String[] args) {
DisplayMode displayMode;
if (args.length == 3) {
displayMode = new DisplayMode(Integer.parseInt(args[0]),
Integer.parseInt(args[1]), Integer.parseInt(args[2]),
DisplayMode.REFRESH_RATE_UNKNOWN);
} else {
displayMode = new DisplayMode(800, 600, 16,
DisplayMode.REFRESH_RATE_UNKNOWN);
}
ImageTest test = new ImageTest();
test.run(displayMode);
}
private SimpleScreenManager screen;
private boolean imagesLoaded;
private Image bgImage;
private Image opaqueImage;
private Image transparentImage;
private Image translucentImage;
private Image antiAliasedImage;
private void run(DisplayMode displayMode) {
setBackground(Color.blue);
setForeground(Color.white);
setFont(new Font("Dialog", Font.PLAIN, 24));
imagesLoaded = false;
screen = new SimpleScreenManager();
try {
screen.setFullScreen(displayMode, this);
loadImages();
try {
Thread.sleep(10000);
} catch (Exception e) {
}
} catch (Exception e) {
} finally {
screen.restoreScreen();
}
}
private void loadImages() {
bgImage = loadImage("/images/background.png");
opaqueImage = loadImage("/images/opaque.png");
transparentImage = loadImage("/images/transparent.png");
translucentImage = loadImage("/images/translucent.png");
antiAliasedImage = loadImage("/images/antialiased.png");
imagesLoaded = true;
repaint();
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
public void paint(Graphics g) {
if (g instanceof Graphics2D) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
g.drawImage(opaqueImage, 0, 0, this);
if (imagesLoaded) {
g.drawImage(bgImage, 0, 0, null);
drawImage(g, opaqueImage, 0, 0, "Opaque");
drawImage(g, transparentImage, 320, 0, "Transparent");
drawImage(g, translucentImage, 0, 300, "Translucent");
drawImage(g, antiAliasedImage, 320, 300,
"Translucent (Anti-Aliased)");
} else {
g.drawString("Loading Images...", 5, 24);
}
}
public void drawImage(Graphics g, Image image, int x, int y, String caption) {
g.drawImage(image, x, y, this);
g.drawString(caption, x + 5, y + 24 + image.getHeight(null));
}
}
There are no errors!, the program runs, it displays the text, but not the images. Which means that loadImages() works, it must be a mistake in my paint method. What am I doing wrong!?!?
I don't see what is wrong with my path:
If you take a look at the ImageIcon source you will notice that the ImageIcon(String) constructor calls another constructor
ImageIcon(String filename, String description) {
image = Toolkit.getDefaultToolkit().getImage(filename);
if (image == null) {
return;
}
this.filename = filename;
this.description = description;
loadImage(image);
}
and .getImage()
public Image getImage() {
return image;
}
If it fails to load an image that image will simply be null without throwing any errors. Your code fails (silently) to load the image (check this with a System.out.println(image) most likely because of an incorrect filepath.
Edit to your comments: I prefer ImageIO to load my files feeding it an inputstream. It is more verbose and has the added benefit of letting me load files from within jars. Change
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
to
private Image loadImage(String fileName) {
return ImageIO.read(getClass().getResourceAsStream(fileName));
}
I am trying to scale a screenshot taken by:
robot.createScreenCapture(SCREEN_RECT);
Im trying to get it down to an image that is 600X400 and fits into a JFrame that is 600X400
My program is using a swing worker to create an video out of each picture, or frames. The frames have a delay of 200ms per each. the image when told to rescale just shows the original image at the original dimensions. Does anyone know how to fix this, or should I just give up on the resize-ing?
#SuppressWarnings("serial")
public class temporaryShit extends JPanel
{
private static final int width = 600;
private static final int height = 400;
private JLabel displayedLabel = new JLabel();
public temporaryShit()
{
setLayout(new BorderLayout());
add(displayedLabel);
try {
MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.execute();
} catch (AWTException e) {
}
}
public void setLabelIcon(Icon icon) {
displayedLabel.setIcon(icon);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
private class MySwingWorker extends SwingWorker<Void, Icon>
{
private final Rectangle SCREEN_RECT = new Rectangle(0, 0, width, height);
private long delay = 200;
private Robot robot = null;
public MySwingWorker() throws AWTException
{
robot = new Robot();
}
#Override
protected Void doInBackground() throws Exception
{
Timer utilTimer = new Timer();
TimerTask task = new TimerTask()
{
#Override
public void run()
{
BufferedImage capturedImage = captureScreen();
publish(new ImageIcon(capturedImage));
}
};
utilTimer.scheduleAtFixedRate(task, delay, delay);
return null;
}
#Override
protected void process(List<Icon> chunks)
{
for (Icon icon : chunks)
{
setLabelIcon(icon);
}
}
private BufferedImage captureScreen()
{
BufferedImage img = robot.createScreenCapture(SCREEN_RECT);
return createResizedImage(img, width, height);
}
public BufferedImage createResizedImage(Image original, int width, int height)
{
BufferedImage scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaledBI.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(original, 0, 0, width, height, null);
g.dispose();
return scaledBI;
}
}
private static void createAndShowGui()
{
temporaryShit mainPanel = new temporaryShit();
JFrame frame = new JFrame("SwingWorker Eg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGui();
}
});
}
}
You already have a new image with specified size - scaled, which you can use for rendering.
Here is a simple example:
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
class TestBrightness {
public static void main(String args[]) {
try {
URL imageUrl = new URL(
"http://duke.kenai.com/comfyChair/ComfyChairRadSmall.jpg");
BufferedImage ioImage = ImageIO.read(imageUrl);
JPanel panel = new JPanel();
Image scaledImg = ioImage.getScaledInstance(ioImage.getWidth() / 2,
ioImage.getHeight() / 2, Image.SCALE_SMOOTH);
panel.add(new JLabel(new ImageIcon(ioImage)));
panel.add(new JLabel(new ImageIcon(scaledImg)));
JOptionPane.showMessageDialog(null, panel, "100% vs 50%",
JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
}
As a side note, there are many ways to scale an image and Image.getScaledInstance() may not be the best. You may be interested to take a look at The Perils of Image.getScaledInstance() for some details on Image.getScaledInstance()
EDIT: question update
Last question update removed all the details regarding getScaledInstance and invalidated this answer. getScaledInstance is a very slow method and it is also asynchronous. Try this method to get a resized image:
public static BufferedImage createResizedImage(Image original, int width,
int height) {
BufferedImage scaledBI = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = scaledBI.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(original, 0, 0, width, height, null);
g.dispose();
return scaledBI;
}
You may want to change rendering hints for better quality.
For a nicer and more complete image scaler take a look at getFasterScaledInstance() from Filthy Rich Clients book.
EDIT : last question update with posted code and SwingWorker
The implementation of SwingWorker is not correct. doInBackground() schedules java.Utils.Timer. This timer handles all updates, while the actual SwingWorker worker thread ends. All updates from the timer are fired not on Event Dispatch Thread. It may not be safe to allocate ImageIcon not on EDT. And for sure it is not safe to update UI, ie calling setLabelIcon() not on EDT. See Concurrency in Swing tutorial for details.
You can add while loop and Thread.sleep in doInBackground() and remove the timer. Alternatively, Swing timer may be more suitable for this case. Here is an example:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class DemoRobotPanel extends JPanel{
private static final long serialVersionUID = 1L;
private Image image;
private Robot robot;
private Rectangle CAPTURE_RECT;
private int TIMER_DELAY = 1000;
private int desiredWidth = 600;
private int desiredHeight = 400;
public DemoRobotPanel() {
CAPTURE_RECT = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
robot = new Robot();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
BufferedImage img = robot.createScreenCapture(CAPTURE_RECT);
setImage(img);
} catch (HeadlessException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer(TIMER_DELAY, taskPerformer);
timer.start();
} catch (AWTException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(desiredWidth, desiredHeight);
}
public void setImage(Image image) {
this.image = image;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
private static void createAndShowGui() {
final DemoRobotPanel panel = new DemoRobotPanel();
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Try this:
public BufferedImage resize(BufferedImage bufferedImage, int resizeWidth, int resizeHeight) {
// Create new (blank) image of required (scaled) size
BufferedImage scaledImage = new BufferedImage(resizeWidth, resizeHeight, BufferedImage.TYPE_INT_ARGB);
// Paint scaled version of image to new image
Graphics2D graphics2D = scaledImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(bufferedImage, 0, 0, resizeWidth, resizeHeight, null);
graphics2D.dispose();
return scaledImage;
}
You may want to try different RenderingHints.