I need 2 separate JPanels (or any lightweight components) on top of each-other and ultimately embedded within a JPanel, either directly or through something like a JLayeredPane. Thus, no heavy-weight components or glass pane. The lower JPanel (named BackgroundPanel) paints a background image or plays a video while maintaining aspect ratio and using an alpha. The upper panel (called CompassPanel) has icons on it and allows the user to add icons, delete them, and move them around (like a diagramming library, this functionality is not directly relevant to this post though). I cannot add many external dependencies due to bandwidth constraints with my JNLP app and deployment environment. However, if someone knows of a lightweight diagramming library that can handle alpha & aspect-ratio maintained background images and videos, I'm game. Otherwise, I cannot for the life of me figure out why this space is being allocated after a resize:
I have read the JAVA tutorial on going without a layout manager (not something I ever wanted to do, where are you GBL!?), but for these scaling requirements and having icons stay over the same portion of the image during resize, etc. I can't think of another way to do this.
Here is the code, I am using Java 1.7. Also, this is my first stackoverflow, don't be gentle ;-)
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
public class Panel extends JPanel {
private static final Logger logger = Logger.getLogger(Panel.class.getName());
public Panel() throws IOException {
final BufferedImage backgroundImage = ImageIO.read(new URL(
"http://www.windpoweringamerica.gov/images/windmaps/us_windmap_80meters_820w.jpg"));
final Dimension backgroundImageSize = new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
logger.log(Level.INFO, "Image dimensions: {0}", backgroundImageSize);
setToolTipText("This is the panel");
final JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setBorder(BorderFactory.createLineBorder(Color.RED, 10));
layeredPane.setToolTipText("This is the layered pane!");
layeredPane.getInsets().set(0, 0, 0, 0);
final BackgroundPanel backgroundImagePanel = new BackgroundPanel(backgroundImage);
final CompassPanel compassPanel = new CompassPanel();
backgroundImagePanel.setToolTipText("You'll probably never see me, I'm in the background, forever beneath the compass panel");
compassPanel.setToolTipText("I'm the compass panel");
// Per http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html, for every container w/o a layout manager, I must:
// 1) Set the container's layout manager to null by calling setLayout(null). -- I do this here
// 2) Call the Component class's setbounds method for each of the container's children. --- I do this when resizing
// 3) Call the Component class's repaint method. --- I do this when resizing
setLayout(null);
add(layeredPane);
layeredPane.add(backgroundImagePanel, JLayeredPane.DEFAULT_LAYER);
layeredPane.add(compassPanel, JLayeredPane.PALETTE_LAYER);
// Whenever this panel gets resized, make sure the layered pane gets resized to preserve the aspect ratio of the background image
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent evt) {
Dimension availableSize = calculateAvailableSize(Panel.this);
Rectangle contentBounds = calculateBoundsToFitImage(availableSize, backgroundImageSize);
// Ok, this is a big deal. Now I know how big everything has to be, lets force it all to be the right size & repaint.
layeredPane.setBounds(contentBounds);
backgroundImagePanel.setBounds(contentBounds);
compassPanel.setBounds(contentBounds);
Panel.this.repaint();
logger.info(String.format("Panel size: %s. Available size: %s. Content Bounds: %s", getSize(), availableSize, contentBounds));
}
});
}
/**
* Paints the constant fitted aspect-ratio background image with an alpha of 0.5
*/
private static class BackgroundPanel extends JPanel {
private static final Logger logger = Logger.getLogger(BackgroundPanel.class.getName());
private final AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f);
private final BufferedImage backgroundImage;
BackgroundPanel(BufferedImage backgroundImage) {
setLayout(null);
this.backgroundImage = backgroundImage;
}
private Dimension lastPaintedDimensions = null;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Dimension size = getSize();
if (lastPaintedDimensions == null || !size.equals(lastPaintedDimensions)) {
logger.log(Level.INFO, String.format("Painting background on %d x %d", size.width, size.height));
}
final Image paintMe = backgroundImage.getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);
final Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(paintMe, 0, 0, this);
g2.setColor(Color.BLUE);
g2.dispose();
lastPaintedDimensions = size;
}
};
private static class CompassPanel extends JPanel {
final List<Compass> compassLabels = new ArrayList<>();
CompassPanel() {
setLayout(null);
setOpaque(false);
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
}
private static class Compass extends JLabel {
private static final BufferedImage compassImage;
static {
try {
compassImage = ImageIO.read(new URL("http://cdn1.iconfinder.com/data/icons/gur-project-1/32/1_7.png"));
} catch (IOException ex) {
throw new RuntimeException("Failed to read compass image", ex);
}
}
final float xPercent, yPercent;
public Compass(float xPercent, float yPercent) {
this.xPercent = xPercent;
this.yPercent = yPercent;
setIcon(new ImageIcon(compassImage));
setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
setOpaque(true);
setCursor(Cursor.getDefaultCursor());
}
}
public static void main(String[] args) throws IOException {
final JFrame frame = new JFrame("Hello Stackoverflowwwwwww! Here is a Dynamic Layered Pane Question.");
frame.setLayout(null);
frame.setContentPane(new Panel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
}
private static Dimension calculateAvailableSize(final JComponent component) {
int availableHeight = component.getSize().height;
int availableWidth = component.getSize().width;
final Insets insets = component.getInsets();
availableHeight -= insets.top;
availableHeight -= insets.bottom;
availableWidth -= insets.left;
availableWidth -= insets.right;
if (component.getBorder() != null) {
Insets borderInsets = component.getBorder().getBorderInsets(component);
if (borderInsets != null) {
availableHeight -= borderInsets.top;
availableHeight -= borderInsets.bottom;
availableWidth -= borderInsets.left;
availableWidth -= borderInsets.right;
}
}
return new Dimension(availableWidth, availableHeight);
}
private static Rectangle calculateBoundsToFitImage(Dimension parentSize, Dimension imageSize) {
final double scaleFactor;
final int xOffset, yOffset, scaledHeight, scaledWidth;
{
final double xScaleFactor = (double) parentSize.width / imageSize.width;
final double yScaleFactor = (double) parentSize.height / imageSize.height;
scaleFactor = xScaleFactor > yScaleFactor ? yScaleFactor : xScaleFactor;
scaledHeight = (int) Math.round(scaleFactor * imageSize.height);
scaledWidth = (int) Math.round(scaleFactor * imageSize.width);
}
xOffset = (int) ((parentSize.width - scaledWidth) / 2.0);
yOffset = (int) ((parentSize.height - scaledHeight) / 2.0);
return new Rectangle(xOffset, yOffset, scaledWidth, scaledHeight);
}
}
Doh. I just answered my own question. Calling #setBounds is relative to your parent container, so the x & y offsets need to be properly accounted for, so this fixes that:
backgroundImagePanel.setBounds(0, 0, contentBounds.width, contentBounds.height);
compassPanel.setBounds(0, 0, contentBounds.width, contentBounds.height);
Related
I am using this class to make an image have different states. At first, the image is dark grey (so you can't see it). I want the image to be clickable and once clicked a math equation will appear. Once the equation is answered the full image will appear. Also, I have another class that splits an image into separate pieces. So basically all of those separate pieces inherit this method. So it's a picture that has been divided into separate images (let's say 4 images, so that means 4 math problems). How would I go about doing this. I've tried multiple methods (that I haven't included in this because it looked like a rats nest), but haven't been able to get it work. I've tried implementing mouseListener and OverlayLayout, but haven't gotten it to work.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Makes the image have different states
*/
public class GPanel extends JPanel {
private Image img;
private boolean answered;
private boolean working;
private int w;
private int h;
/**
*
*/
private static final long serialVersionUID = 1L;
public GPanel(Image img) {
this.img = img;
w = img.getWidth(this);
h = img.getHeight(this);
setPreferredSize(new Dimension(w, h));
answered = false;
working = false;
}
public void setAnswered() {
answered = true;
}
public boolean getAnswered() {
return answered;
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
if (!answered) {
if (working){
System.out.println("Run third");
g2.setColor(Color.lightGray);
g2.fillRect(0, 0, w, h);
g2.setPaint(Color.yellow);
g2.setFont(new Font("Sans-serif", Font.BOLD, 20));
g2.drawString("Testing, one, two, three.", w/3, h/2);
((JFrame)SwingUtilities.getRoot(this)).setTitle("Testing, one, two, three.");
}
else{
System.out.println("Run first");
g2.setColor(Color.darkGray);
g2.fillRect(0, 0, w, h);
}
working = !working; // toggles on and off
} else {
System.out.println("Run second");
g2.drawImage(img, 0, 0, this);
((JFrame)SwingUtilities.getRoot(this)).setTitle("Testing GPanel");
}
answered = !answered; // toggles on and off
}
}
If all you need to do is to swap images, then the easiest way to do that is to display the images as ImageIcons within a JLabel. To swap the JLabel's icon, all one has to do is simply call setIcon(newIcon) on the JLabel. So for instance, say we had four images within an ArrayList of Icons (ArrayList<Icon>) and that this ArrayList variable was called icons, and say your program had an int variable called iconIndex that holds the index number of the current image being displayed, then it's simple to swap images by incrementing the index variable, and using it to get the next icon in the list. Something like:
iconIndex++; // increment the index variable
iconIndex %= icons.size(); // if larger than size of list, set to 0
Icon icon = icons.get(iconIndex); // get icon from list
imageLabel.setIcon(icon); // set the JLabel's icon with it
This code could be within a MouseListener, one added to the JLabel, and then you're done. Note that the logic code is in the MouseListener. So if the user has to do anything else before an image is switched, it is checked within the same MouseListener
For example:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class DifferentImages extends JPanel {
private static final int IMG_W = 400;
private static final int IMG_H = IMG_W;
private static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 40);
private JLabel imageLabel = new JLabel();
private List<Icon> icons = new ArrayList<>();
private int iconIndex = 0;
public DifferentImages() {
// create images and icons
Icon icon = getIcon(Color.DARK_GRAY, Color.LIGHT_GRAY, "First Image");
icons.add(icon);
icon = getIcon(Color.BLUE, new Color(137, 207, 240), "Second Image");
icons.add(icon);
icon = getIcon(Color.RED, Color.PINK, "Third Image");
icons.add(icon);
icon = getIcon(Color.YELLOW, Color.ORANGE, "Fourth Image");
icons.add(icon);
imageLabel.setIcon(icons.get(iconIndex));
add(imageLabel);
imageLabel.addMouseListener(new MyMouse());
}
// MouseListener that is added to JLabel
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
// code here to check if it is OK to swap images
// and if so, then swap them:
iconIndex++; // increment the index variable
iconIndex %= icons.size(); // if larger than size of list, set to 0
Icon icon = icons.get(iconIndex); // get icon from list
imageLabel.setIcon(icon); // set the JLabel's icon with it
}
}
// just creates an image icon for demo purposes, one with color and text
private Icon getIcon(Color bg, Color fb, String text) {
BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setColor(bg); // first a dark image
g2.fillRect(0, 0, IMG_W, IMG_H);
g2.setColor(fb);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setFont(TEXT_FONT);
FontMetrics fontMetrics = g2.getFontMetrics(TEXT_FONT);
int textWidth = fontMetrics.stringWidth(text);
int x = (IMG_W - textWidth) / 2;
int y = (IMG_H) / 2;
g2.drawString(text, x, y);
g2.dispose();
Icon icon = new ImageIcon(img);
return icon;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DifferentImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DifferentImages());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I wan to make the text big then become small again after few second and it will keep repeating become big then small. How should i code it?
//DUMMY POST nfinity Blade is a fighting game developed by Chair Entertainment and Epic Games and released through the App Store on December 9, 2010. It is the first iOS video game to run on the Unreal Engine. In the game, the unnamed player character fights a series of one-on-one battles in a derelict castle to face the immortal God King. When in battle, players swipe the screen to attack and parry, and tap the screen to dodge and block enemy attacks. Upon victory or defeat, the player restarts the game as the character's descendant with the same items and experience level. Developed by a team of twelve people, the game was intended to demonstrate the new iOS version of the Unreal Engine. Four free expansions added new equipment, endings, and game modes. The game made US$1.6 million in the//DUMMYPOST
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FontSizeAnimation extends JPanel implements ActionListener {
Timer timer;
int x = 1;
float alpha = 1;
public FontSizeAnimation() {
timer = new Timer(4, this);
timer.setInitialDelay(500);
timer.start();
}
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Font font = new Font("Dialog", Font.PLAIN, x);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String s = "Java";
int w = (int) getSize().getWidth();
int h = (int) getSize().getHeight();
int stringWidth = fm.stringWidth(s);
g2d.drawString(s, (w - stringWidth) / 2, h / 2);
}
public static void main(String[] args) {
JFrame frame = new JFrame("FontSizeAnimation");
frame.add(new FontSizeAnimation());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
x += 1;
alpha -= 0.0001;
repaint();
}
}
Of course there are multiple ways of achieving this, but you could create a variable that holds wheter the size of the font should get bigger or smaller. Update that variable in the actionPerformed() method and then change the font size according to what the variable's value is. Here's an example with your code (click here for a preview, would be too distracting in the post):
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FontSizeAnimation extends JPanel implements ActionListener {
Timer timer;
int x = 1;
int lastX = 1;
float alpha = 1;
boolean bigger;
public FontSizeAnimation() {
timer = new Timer(4, this);
timer.setInitialDelay(500);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Font font = new Font("Dialog", Font.PLAIN, x);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String s = "Java";
int w = (int) getSize().getWidth();
int h = (int) getSize().getHeight();
int stringWidth = fm.stringWidth(s);
g2d.drawString(s, (w - stringWidth) / 2, h / 2);
}
public static void main(String[] args) {
JFrame frame = new JFrame("FontSizeAnimation");
frame.add(new FontSizeAnimation());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (x > 50) {
bigger = false;
} else if (x < 2) {
bigger = true;
}
if (bigger) {
x++;
} else {
x--;
}
alpha -= 0.0001;
repaint();
}
}
This question already has an answer here:
netBeans gui problem
(1 answer)
Closed 8 years ago.
I'm trying to use canvas in java. I'm using netbeans GUI builder to add several canvases to the window but I'm not sure how to for example draw the line or rectangle on them. I read several manuals how to do that but I'm still beginner in Java and I didn't quite understand what am I supposed to do. The constructor of the class looks like this:
public Classname() {
initComponents();
canvas1.setBackground(Color.red); // That works.
// Now I want to (for example) draw a line on the canvas1 (or some other canvas)
}
Could somebody please explain me what code should I write and where to put it? Thanks in advance. (Sorry for my english.)
Assuming your mean java.awt.Canvas, I'd recommend that you shouldn't be using it. Two main reasons, one, it's a heavy weight component, which introduces a list of issues when mixed with Swing/lightweight components and two, it's not double buffered, which just adds additional overheads you're going to have to deal with.
The preferred means by which to perform custom painting is to generally create a new class that extends from JPanel and the override it's paintComponent method for example
public class PaintPane extends JPanel {
public PaintPane () {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
g2d.dispose();
}
}
This will draw a simple line across the middle of the panel.
You can then drag the class from the "Projects" tab into the form editor (and onto an existing form container), like you would with components from the palette
Take a look at Performing Custom Painting and 2D Graphics for more details
Updated with example based on comments
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawExample {
public static void main(String[] args) {
new DrawExample();
}
private DrawPane drawPane;
public DrawExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
drawPane = new DrawPane();
JButton addRect = new JButton("Add Rectangle");
addRect.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int width = drawPane.getWidth() - 1;
int height = drawPane.getHeight() - 1;
int x = (int)(Math.random() * (width - 5));
int y = (int)(Math.random() * (height - 5));
width -= x;
height -= y;
int rectWidth = (int)(Math.random() * width);
int rectHeight = (int)(Math.random() * height / 2);
drawPane.addRect(x, y, rectWidth, rectHeight);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(drawPane);
frame.add(addRect, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawPane extends JPanel {
private List<Shape> shapes;
public DrawPane() {
shapes = new ArrayList<Shape>(25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Shape shape : shapes) {
g2d.draw(shape);
}
g2d.dispose();
}
public void addRect(int x, int y, int width, int height) {
shapes.add(new Rectangle(x, y, width, height));
repaint();
}
}
}
So Im drawing a BufferedImage 'bird' but I want to rotate it according to the angle that it is falling. I have a bird object which contains the BufferedImage and a render() method which draw it rotated.
public void render(Graphics2D g, ImageObserver io) {
double theta = Math.tan((height - pastHeight) / .875);
System.out.println(theta);
Graphics2D g2 = (Graphics2D) bird.getGraphics();
g2.drawImage(bird, 100, (int) height, null);
g2.rotate(theta);
g2.drawImage(bird, 100, (int) height, io);
}
I call this as such
bird.render(g2, ???);
in my paintcomponent method in my jcomponent.
only problem is I dont know what to use as my ImageObserver... I've tried passing in my JFrame and my JComponent but the image no longer appears when I do that... what would I pass in for the image to appear in my window and/or how else would I achieve this rotation?
Assuming that you are doing this in something that extends JComponent, you should use
bird.render(g2, this);
As JComponent implements ImageObserver
The problem with the image disappearing isn't an issue with the ImageObserver but the point around which the rotation is occurring, which I believe is the top/left corner of the Graphics context.
Try using Graphics2D#rotate(double, int, int) which will allow you to specify the origin points of the rotation (pivot point).
Don't forget to reset your translations, as they will effect everything that is painted after your supply them and may be re-used in subsequent paint cycles.
Updated with simple example
This is a basic example that demonstrates the different uses of rotate.
First, I simply used Graphics#rotate(double)
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RotateImage {
public static void main(String[] args) {
new RotateImage();
}
public RotateImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
private double angel = 0d;
public TestPane() {
try {
img = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angel += 5;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.rotate(Math.toRadians(angel));
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
Then I replaced g2d.rotate(Math.toRadians(angel)); with g2d.rotate(Math.toRadians(angel), getWidth() / 2, getHeight() / 2);, which used the center position of the component (or the Graphics context) as the anchor point around which the rotation would occur...
Now, because you only want to rotate your image, you're going to need to calculate the anchor point around the current position of the image's center position (assuming you want it to rotate around the middle)
I m making App in netbeans platform using java swing Technology.I want to do image processing oncaptured image.This image is capture by X-Ray Gun.after that i want to increase/decrease brightness of image using JSlider.I done this using paintComponent(Graphics g) method. but i want to do direct effect of increased/decreased brightnees of image without using paintComponenet(Graphics g) method.so how can i do that? My code is shown below. In my code i use PlanarImage and BufferedImage class of JAI library for load .tiff imge and after that i use statechange event of JSlider object for increase/decrease brightness of image.
enter code here
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main extends JPanel implements ChangeListener {
RescaleOp op;
PlanarImage image = JAI.create("fileload", "F:\\java\\aimages\\teeth1.tiff");
BufferedImage bufferedImage = image.getAsBufferedImage();
BufferedImage bImage;
int x1 = bufferedImage.getWidth();
int y1 = bufferedImage.getHeight();
JSlider slider = new JSlider(-10, 10);
public Main() {
bImage=bufferedImage;
slider.addChangeListener(this);
this.add(slider, BorderLayout.class);
// this.add(new JLabel(new ImageIcon(bufferedImage)), BorderLayout.NORTH);
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(bufferedImage, 0, 0, x1, y1, null);
}
public static void main(String[] argv) throws Exception {
JFrame jFrame = new JFrame();
jFrame.add(new Main());
jFrame.setVisible(true);
jFrame.setSize(200, 200);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void stateChanged(ChangeEvent e) {
JSlider slid = (JSlider) e.getSource();
float value = (float) slid.getValue();
setValue(value);
}
private void setValue(float value) {
bufferedImage=bImage;
float scaleFactor = (float) (1.0 + (value / 10.0));
op = new RescaleOp(scaleFactor, 0, null);
bufferedImage = op.filter(bufferedImage, null);
repaint();
}
}
It's not clear why you want to avoid paintComponent(), but you can always alter the BufferedImage in a JLabel's ImageIcon using RescaleOp.
Addendum: I sounds like you don't want to overwrite the original image, so naturally it makes sense to alter a copy. Unfortunately, your example merely copies a reference to the original. Instead, use two copies, passing the original as src and the copy as dst, as shown the example below. See also AlphaTest.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* #see https://stackoverflow.com/q/10208255/230513
* #see https://stackoverflow.com/questions/5838842
* #see https://stackoverflow.com/questions/5864490
*/
public class RescaleTest extends JPanel implements ChangeListener {
private static final String NAME = "image.jpg";
private BufferedImage image, copy;
private JSlider slider = new JSlider();
public RescaleTest() {
PlanarImage pi = JAI.create("fileload", NAME);
image = pi.getAsBufferedImage();
copy = pi.getAsBufferedImage();
this.setLayout(new BorderLayout());
this.add(new JLabel(new ImageIcon(copy)));
this.add(slider, BorderLayout.SOUTH);
slider.setValue(slider.getMaximum() / 2);
slider.addChangeListener(this);
}
#Override
public void stateChanged(ChangeEvent e) {
float value = (float) slider.getValue();
float scaleFactor = 2 * value / slider.getMaximum();
RescaleOp op = new RescaleOp(scaleFactor, 0, null);
copy = op.filter(image, copy);
repaint();
}
private void display() {
JFrame f = new JFrame("RescaleTest");
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 RescaleTest().display();
}
});
}
}