Add visibility effect to images in Java JFrame - java

I'm using Java's JFrame to show a .jpeg image. I need to start horizontal sliding effect to an image when a checkbox is selected. So basically when the checkbox is selected, the image will start sliding from left to right, taking a few seconds and when finished, start again forever until the checkbox is unchecked. How can I add I this feature?
EDIT: Actually I do not mean the picture itself is moving; I mean the picture is stable and static, but the image will start to get visible with a horizontal sliding effect, from left to right and restart. I hope it is clear enough.
Assume here is my code to show images and checkboxes (got from Java tutorial):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*
* CheckBoxDemo.java requires 16 image files in the images/geek
* directory:
* geek-----.gif, geek-c---.gif, geek--g--.gif, geek---h-.gif, geek----t.gif,
* geek-cg--.gif, ..., geek-cght.gif.
*/
public class CheckBoxDemo extends JPanel
implements ItemListener {
JCheckBox chinButton;
JCheckBox glassesButton;
JCheckBox hairButton;
JCheckBox teethButton;
/*
* Four accessory choices provide for 16 different
* combinations. The image for each combination is
* contained in a separate image file whose name indicates
* the accessories. The filenames are "geek-XXXX.gif"
* where XXXX can be one of the following 16 choices.
* The "choices" StringBuffer contains the string that
* indicates the current selection and is used to generate
* the file name of the image to display.
---- //zero accessories
c--- //one accessory
-g--
--h-
---t
cg-- //two accessories
c-h-
c--t
-gh-
-g-t
--ht
-ght //three accessories
c-ht
cg-t
cgh-
cght //all accessories
*/
StringBuffer choices;
JLabel pictureLabel;
public CheckBoxDemo() {
super(new BorderLayout());
//Create the check boxes.
chinButton = new JCheckBox("Chin");
chinButton.setMnemonic(KeyEvent.VK_C);
chinButton.setSelected(true);
glassesButton = new JCheckBox("Glasses");
glassesButton.setMnemonic(KeyEvent.VK_G);
glassesButton.setSelected(true);
hairButton = new JCheckBox("Hair");
hairButton.setMnemonic(KeyEvent.VK_H);
hairButton.setSelected(true);
teethButton = new JCheckBox("Teeth");
teethButton.setMnemonic(KeyEvent.VK_T);
teethButton.setSelected(true);
//Register a listener for the check boxes.
chinButton.addItemListener(this);
glassesButton.addItemListener(this);
hairButton.addItemListener(this);
teethButton.addItemListener(this);
//Indicates what's on the geek.
choices = new StringBuffer("cght");
//Set up the picture label
pictureLabel = new JLabel();
pictureLabel.setFont(pictureLabel.getFont().deriveFont(Font.ITALIC));
updatePicture();
//Put the check boxes in a column in a panel
JPanel checkPanel = new JPanel(new GridLayout(0, 1));
checkPanel.add(chinButton);
checkPanel.add(glassesButton);
checkPanel.add(hairButton);
checkPanel.add(teethButton);
add(checkPanel, BorderLayout.LINE_START);
add(pictureLabel, BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
/** Listens to the check boxes. */
public void itemStateChanged(ItemEvent e) {
int index = 0;
char c = '-';
Object source = e.getItemSelectable();
if (source == chinButton) {
index = 0;
c = 'c';
} else if (source == glassesButton) {
index = 1;
c = 'g';
} else if (source == hairButton) {
index = 2;
c = 'h';
} else if (source == teethButton) {
index = 3;
c = 't';
}
//Now that we know which button was pushed, find out
//whether it was selected or deselected.
if (e.getStateChange() == ItemEvent.DESELECTED) {
c = '-';
}
//Apply the change to the string.
choices.setCharAt(index, c);
updatePicture();
}
protected void updatePicture() {
//Get the icon corresponding to the image.
ImageIcon icon = createImageIcon(
"images/geek/geek-"
+ choices.toString()
+ ".gif");
pictureLabel.setIcon(icon);
pictureLabel.setToolTipText(choices.toString());
if (icon == null) {
pictureLabel.setText("Missing Image");
} else {
pictureLabel.setText(null);
}
}
/** Returns an ImageIcon, or null if the path was invalid. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = CheckBoxDemo.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CheckBoxDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new CheckBoxDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

The simplest solution would be to roll your own using something like a javax.swing.Timer, for example...
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.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 SlidingAnimation {
public static void main(String[] args) {
new SlidingAnimation();
}
public SlidingAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
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 int x = 0;
private Timer timer;
private long startTime = -1;
private int playTime = 4000;
public TestPane() {
try {
img = ImageIO.read(new File("..."));
} catch (IOException ex) {
ex.printStackTrace();
}
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
float progress = 0f;
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {
long currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
if (diff >= playTime) {
diff = 0;
startTime = -1;
}
progress = diff / (float)playTime;
}
x = (int)((getWidth() - img.getWidth()) * progress);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth() * 2, img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
This is a two second loop, which calculates the current position based on the difference between a start time and the current time and the total area that the animation needs to move. This does make it flexible, but it is a straight linear animation, it does not have the nice ease-in and ease-out which gives animation a more realistic movement...
For more advanced animation effects, I would strongly encourage you have a look at
The Timing Framework. Provides good access to the core to do unusual things, but also has the ability to change an objects properties over time
Trident. Provides the ability to change the properties of objects over time
Universal Tween Engine which I haven't used but looks really good.
You might also want to take a look at Performing Custom Painting for more details about how custom painting is done in Swing
Updated
So, if I understand your comments, you want to do a cross fade effect. Now there are a few ways to do this, you could use BufferedImage#subImage to get a "cropped" version of the original image and show that, but that, IMHO, doesn't produce such a nice effect...
Instead, you could use a masking technique which allows you to produce a fading effect...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
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 SlidingAnimation {
public static void main(String[] args) {
new SlidingAnimation();
}
public SlidingAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
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 Timer timer;
private long startTime = -1;
private int playTime = 4000;
private float progress;
public TestPane() {
try {
img = ImageIO.read(new File("..."));
} catch (IOException ex) {
ex.printStackTrace();
}
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {
long currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
if (diff >= playTime) {
diff = 0;
startTime = -1;
}
progress = diff / (float) playTime;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
protected BufferedImage generateImage() {
BufferedImage buffer = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
g2d.setBackground(new Color(0, 0, 0, 0));
g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
g2d.drawImage(img, 0, 0, this);
float startAt = progress - 0.05f;
float endAt = progress + 0.05f;
if (endAt <= 0.1f) {
startAt = 0;
endAt = Math.max(0.1f, progress);
} else if (endAt >= 1f) {
endAt = 1f;
startAt = progress;
}
LinearGradientPaint lgp = new LinearGradientPaint(
new Point2D.Float(0, 0),
new Point2D.Float(img.getWidth(), 0),
new float[]{startAt, endAt},
new Color[]{new Color(0, 0, 0, 0), Color.RED});
g2d.setPaint(lgp);
g2d.setComposite(AlphaComposite.DstOut.derive(1f));
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
g2d.dispose();
return buffer;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int y = (getHeight() - img.getHeight()) / 2;
int x = (getWidth() - img.getWidth()) / 2;
g2d.drawImage(generateImage(), x, y, this);
g2d.dispose();
}
}
}
}

Related

Jframe Splash screen wont display an image

I cant seem to add an image to the JFRAME when run, it opens the Splash screen and displays the loading bar and the text, but no image, the image is in the same location as the code. The image path is fine as none needed and when hovered over, it displays the image in my IDE, Any assistance would be amazing.
import javax.swing.*;
import java.awt.*;
public class SplashScreen {
public static void main(String[] args) {
new SplashScreen();
new MenuGui();
}
JFrame f;
JLabel image = new JLabel(new ImageIcon("Calc.png"));
JLabel text = new JLabel("Loading...");
JProgressBar progressBar = new JProgressBar();
JLabel message = new JLabel();
SplashScreen() {
CreateGui();
addImage();
addText();
addProgressBar();
addMessage();
runningPBar();
f.add(image);
f.add(progressBar);
f.add(message);
f.add(text);
}
public void CreateGui() {
f = new JFrame();
f.getContentPane().setLayout(null);
f.setUndecorated(true);
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.getContentPane().setBackground(Color.CYAN);
f.setVisible(true);
}
public void addText(){
text.setFont(new Font("arial",Font.BOLD,30));
text.setBounds(170,220,600,40);
text.setForeground(Color.black);
f.add(text);
}
public void addImage(){
image.setBounds(20,30,200,300);
image.setSize(600,200);
}
public void addMessage(){
message.setBounds(100, 280, 400, 30);
message.setForeground(Color.BLACK);
message.setFont(new Font("arial", Font.BOLD, 15));
f.add(message);
}
public void addProgressBar(){
progressBar.setBounds(100,280,400,30);
progressBar.setBorderPainted(true);
progressBar.setStringPainted(true);
progressBar.setForeground(Color.black);
progressBar.setBackground(Color.WHITE);
progressBar.setValue(0);
f.add(progressBar);
}
public void runningPBar(){
int i = 0;
while (i <=100){
try {
Thread.sleep(50);
progressBar.setValue(i);
message.setText("LOADING" + Integer.toString(i) + "%");
i++;
if(i == 100)
f.dispose();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
So, the immediate issue I can see is the fact that you don't actually add image to your frame.
You also need to beware of the limitations of ImageIcon. In your case, it's expecting to find a image named Calc.png within the current working directory, the problem with that is, the working directory can change.
A better solution is to "embed" these resources. How this is done typically comes down to the IDE and build system your are using, but the intention is that the image will end up within the class path of the running app, typically included in the JAR.
But there are a litany of other issues which aren't going to help you.
Swing is not thread safe and is single threaded. This means you shouldn't update the UI (or any state the UI relies on) from outside the context of the Event Dispatching Thread and you shouldn't perform any long running operations from within the context of the Event Dispatching Thread either.
See Concurrency in Swing for more details.
This leaves you with a problem. How do you do work, without blocking the UI, and keep the the UI up-to-date? Well, see Worker Threads and SwingWorker for the most common solution.
While you can use Java's inbuilt splash screen support, see How to Create a Splash Screen for more details, I tend to avoid it (personally). While it is most certainly faster, it's also ... clunky (IMHO)
Personally, I like to make use of undecorated window and just do what I need to do, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.setUndecorated(true);
SplashPane splashPane = new SplashPane();
splashPane.setSplashListener(new SplashListener() {
#Override
public void didCompleteLoading(SplashPane source) {
frame.dispose();
}
});
frame.add(splashPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public interface SplashListener {
public void didCompleteLoading(SplashPane source);
}
public class SplashPane extends JPanel {
private BufferedImage coloredImage;
private BufferedImage grayscaleImage;
private JLabel loadingLabel;
private JLabel tagLine;
private LoadingWorker loadingWorker;
private double progress = 0;
private SplashListener splashListener;
public SplashPane() throws IOException {
coloredImage = ImageIO.read(getClass().getResource("/images/SplashScreen.jpeg"));
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
grayscaleImage = op.filter(coloredImage, null);
loadingLabel = new JLabel("Loading Sith OS");
tagLine = new JLabel("Your lack of faith is disturbing");
Font font = loadingLabel.getFont();
Font extraLargeFont = font.deriveFont(Font.BOLD, font.getSize() * 4);
Font largeFont = font.deriveFont(Font.BOLD, font.getSize() * 2);
loadingLabel.setFont(extraLargeFont);
loadingLabel.setForeground(Color.WHITE);
tagLine.setFont(largeFont);
tagLine.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(20, 20, 20, 20);
gbc.anchor = GridBagConstraints.NORTH;
gbc.weightx = 1;
gbc.weighty = 0.5;
add(loadingLabel, gbc);
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTH;
add(tagLine, gbc);
configureLoadingWorker();
}
public void setSplashListener(SplashListener listener) {
splashListener = listener;
}
protected void configureLoadingWorker() {
loadingWorker = new LoadingWorker();
loadingWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (loadingWorker.getState() == SwingWorker.StateValue.DONE) {
progress = 1.0;
repaint();
// Because it's nice to see that last little bit of progress
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (splashListener != null) {
splashListener.didCompleteLoading(SplashPane.this);
}
}
});
timer.setRepeats(false);
timer.start();
} else if ("progress".equals(evt.getPropertyName())) {
progress = loadingWorker.getProgress() / 100.0;
repaint();
}
}
});
}
#Override
public void addNotify() {
super.addNotify();
loadingWorker.execute();
}
#Override
public void removeNotify() {
super.removeNotify();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(coloredImage.getWidth(), coloredImage.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xPos = (getWidth() - coloredImage.getWidth()) / 2;
int yPos = (getHeight() - coloredImage.getHeight()) / 2;
g2d.drawImage(grayscaleImage, xPos, yPos, this);
int targetHeight = (int) (coloredImage.getHeight() * progress);
if (targetHeight > 0) {
BufferedImage subimage = coloredImage.getSubimage(0, coloredImage.getHeight() - targetHeight, coloredImage.getWidth(), targetHeight);
xPos = (getWidth() - coloredImage.getWidth()) / 2;
yPos = ((getHeight() - coloredImage.getHeight()) / 2) + (coloredImage.getHeight() - targetHeight);
g2d.drawImage(subimage, xPos, yPos, this);
}
g2d.dispose();
}
protected class LoadingWorker extends SwingWorker<Void, Void> {
#Override
protected Void doInBackground() throws Exception {
Random rnd = new Random();
int progress = 0;
Thread.sleep(2);
do {
int delta = rnd.nextInt(9) + 1;
progress += delta;
setProgress(progress);
Thread.sleep(500);
} while (progress < 100);
setProgress(100);
return null;
}
}
}
}

How do I implement Java swing GUI start screen for a game with drawString and drawImage?

I'm not sure how I would fix the errors in my program and how I would highlight the option the user is hovering on. I want it to highlight the code for each position, i.e position 1 would be highlighted(as a different color) to start game,etc. and up/down would change position and I would change the position with up ,down, left, right. This is what I have so far. At the moment its bugged and when compiled with my window it comes out as:
Which works for the main game and altered for this titleboard, what am I doing wrong and how do I fix it?
TitleBoard class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
//sound + file opening
import java.io.*;
import javax.sound.sampled.*;
public class TitleBoard extends JPanel implements ActionListener{
private ArrayList<String> OptionList;
private Image background;
private ImageIcon bgImageIcon;
private String cheatString;
private int position;
private Timer timer;
public TitleBoard(){
setFocusable(true);
addKeyListener(new TAdapter());
bgImageIcon = new ImageIcon("");
background = bgImageIcon.getImage();
String[] options = {"Start Game","Options","Quit"};
OptionList = new ArrayList<String>();
optionSetup(options);
position = 1;
timer = new Timer(8, this);
timer.start();
/*
1 mod 3 =>1 highlight on start
2 mod 3 =>2 highlight on options
3 mod 3 =>0 highlight on quit
*/
try{
Font numFont = Font.createFont(Font.TRUETYPE_FONT,new File("TwistedStallions.ttf"));
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(numFont);
setFont(numFont.deriveFont(24f)); //adjusthislater
}catch(IOException|FontFormatException e){
e.printStackTrace();
}
}
private void optionSetup(String[] s){
for(int i=0; i<s.length;i++) {
OptionList.add(s[i]);
}
}
public void paint(Graphics g){
super.paint(g);
Graphics g2d = (Graphics2D)g;
g2d.drawImage(background,0,0,this);
for (int i=0;i<OptionList.size();i++){
g2d.drawString(OptionList.get(i),200,120+120*i);
}/*
g2d.drawString(OptionList.get(1),400,240);
g2d.drawString(OptionList.get(2),400,360);
//instructions on start screen maybe??
//800x500
//highlighting*/
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e){
repaint();
}
public class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP||
e.getKeyCode() == KeyEvent.VK_RIGHT){
position++;
}
if(e.getKeyCode() == KeyEvent.VK_DOWN||
e.getKeyCode() == KeyEvent.VK_LEFT){
position--;
}
}
}
}
Window Class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Window extends JFrame{
public Window(){
int width = 800, height = 600;
//TO DO: make a panel in TITLE MODE
///////////////////////////////////
//panel in GAME MODE.
add(new TitleBoard());
//set default close
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width,height);
//centers window
setLocationRelativeTo(null);
setTitle("Title");
setResizable(false);
setVisible(true);
}
public static void main(String[] args){
new Window();
}
}
There are any number of ways you might achieve this, for example, you could use some kind of delegation model.
That is, rather then trying to mange of each element in a single method (or methods), you could devise a delegate which provide a simple interface method that the paint method would call and it would know how to do the rest.
For example, Swing uses this type of concept with it's cell renderers for JList, JTable and JTree.
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MyAwesomeMenu {
public static void main(String[] args) {
new MyAwesomeMenu();
}
public MyAwesomeMenu() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
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 List<String> menuItems;
private String selectMenuItem;
private String focusedItem;
private MenuItemPainter painter;
private Map<String, Rectangle> menuBounds;
public TestPane() {
setBackground(Color.BLACK);
painter = new SimpleMenuItemPainter();
menuItems = new ArrayList<>(25);
menuItems.add("Start Game");
menuItems.add("Options");
menuItems.add("Exit");
selectMenuItem = menuItems.get(0);
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
String newItem = null;
for (String text : menuItems) {
Rectangle bounds = menuBounds.get(text);
if (bounds.contains(e.getPoint())) {
newItem = text;
break;
}
}
if (newItem != null && !newItem.equals(selectMenuItem)) {
selectMenuItem = newItem;
repaint();
}
}
#Override
public void mouseMoved(MouseEvent e) {
focusedItem = null;
for (String text : menuItems) {
Rectangle bounds = menuBounds.get(text);
if (bounds.contains(e.getPoint())) {
focusedItem = text;
repaint();
break;
}
}
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "arrowDown");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "arrowUp");
am.put("arrowDown", new MenuAction(1));
am.put("arrowUp", new MenuAction(-1));
}
#Override
public void invalidate() {
menuBounds = null;
super.invalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (menuBounds == null) {
menuBounds = new HashMap<>(menuItems.size());
int width = 0;
int height = 0;
for (String text : menuItems) {
Dimension dim = painter.getPreferredSize(g2d, text);
width = Math.max(width, dim.width);
height = Math.max(height, dim.height);
}
int x = (getWidth() - (width + 10)) / 2;
int totalHeight = (height + 10) * menuItems.size();
totalHeight += 5 * (menuItems.size() - 1);
int y = (getHeight() - totalHeight) / 2;
for (String text : menuItems) {
menuBounds.put(text, new Rectangle(x, y, width + 10, height + 10));
y += height + 10 + 5;
}
}
for (String text : menuItems) {
Rectangle bounds = menuBounds.get(text);
boolean isSelected = text.equals(selectMenuItem);
boolean isFocused = text.equals(focusedItem);
painter.paint(g2d, text, bounds, isSelected, isFocused);
}
g2d.dispose();
}
public class MenuAction extends AbstractAction {
private final int delta;
public MenuAction(int delta) {
this.delta = delta;
}
#Override
public void actionPerformed(ActionEvent e) {
int index = menuItems.indexOf(selectMenuItem);
if (index < 0) {
selectMenuItem = menuItems.get(0);
}
index += delta;
if (index < 0) {
selectMenuItem = menuItems.get(menuItems.size() - 1);
} else if (index >= menuItems.size()) {
selectMenuItem = menuItems.get(0);
} else {
selectMenuItem = menuItems.get(index);
}
repaint();
}
}
}
public interface MenuItemPainter {
public void paint(Graphics2D g2d, String text, Rectangle bounds, boolean isSelected, boolean isFocused);
public Dimension getPreferredSize(Graphics2D g2d, String text);
}
public class SimpleMenuItemPainter implements MenuItemPainter {
public Dimension getPreferredSize(Graphics2D g2d, String text) {
return g2d.getFontMetrics().getStringBounds(text, g2d).getBounds().getSize();
}
#Override
public void paint(Graphics2D g2d, String text, Rectangle bounds, boolean isSelected, boolean isFocused) {
FontMetrics fm = g2d.getFontMetrics();
if (isSelected) {
paintBackground(g2d, bounds, Color.BLUE, Color.WHITE);
} else if (isFocused) {
paintBackground(g2d, bounds, Color.MAGENTA, Color.BLACK);
} else {
paintBackground(g2d, bounds, Color.DARK_GRAY, Color.LIGHT_GRAY);
}
int x = bounds.x + ((bounds.width - fm.stringWidth(text)) / 2);
int y = bounds.y + ((bounds.height - fm.getHeight()) / 2) + fm.getAscent();
g2d.setColor(isSelected ? Color.WHITE : Color.LIGHT_GRAY);
g2d.drawString(text, x, y);
}
protected void paintBackground(Graphics2D g2d, Rectangle bounds, Color background, Color foreground) {
g2d.setColor(background);
g2d.fill(bounds);
g2d.setColor(foreground);
g2d.draw(bounds);
}
}
}
For here, you could add ActionListener
When a GUI needs a button, use a JButton! The JButton API allows the possibility to add icons for many different circumstances. This example shows different icons for the standard icon, the hover icon, and the pressed icon. Your GUI would obviously use icons with text on them for the required effect.
The icons are pulled directly (hot-linked) from Example images for code and mark-up Q&As.
Standard
Hover over triangle
Press triangle
Code
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
public class IconHoverFocusIndication {
// the GUI as seen by the user (without frame)
// swap the 1 and 0 for single column
JPanel gui = new JPanel(new GridLayout(1,0,50,50));
public static final int GREEN = 0, YELLOW = 1, RED = 2;
String[][] urls = {
{
"http://i.stack.imgur.com/T5uTa.png",
"http://i.stack.imgur.com/IHARa.png",
"http://i.stack.imgur.com/wCF8S.png"
},
{
"http://i.stack.imgur.com/gYxHm.png",
"http://i.stack.imgur.com/8BGfi.png",
"http://i.stack.imgur.com/5v2TX.png"
},
{
"http://i.stack.imgur.com/1lgtq.png",
"http://i.stack.imgur.com/6ZXhi.png",
"http://i.stack.imgur.com/F0JHK.png"
}
};
IconHoverFocusIndication() throws Exception {
// adjust to requirement..
gui.setBorder(new EmptyBorder(15, 30, 15, 30));
gui.setBackground(Color.BLACK);
Insets zeroMargin = new Insets(0,0,0,0);
for (int ii = 0; ii < 3; ii++) {
JButton b = new JButton();
b.setBorderPainted(false);
b.setMargin(zeroMargin);
b.setContentAreaFilled(false);
gui.add(b);
URL url1 = new URL(urls[ii][GREEN]);
BufferedImage bi1 = ImageIO.read(url1);
b.setIcon(new ImageIcon(bi1));
URL url2 = new URL(urls[ii][YELLOW]);
BufferedImage bi2 = ImageIO.read(url2);
b.setRolloverIcon(new ImageIcon(bi2));
URL url3 = new URL(urls[ii][RED]);
BufferedImage bi3 = ImageIO.read(url3);
b.setPressedIcon(new ImageIcon(bi3));
}
}
public JComponent getGUI() {
return gui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
IconHoverFocusIndication ihfi =
new IconHoverFocusIndication();
JFrame f = new JFrame("Button Icons");
f.add(ihfi.getGUI());
// Ensures JVM closes after frame(s) closed and
// all non-daemon threads are finished
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See https://stackoverflow.com/a/7143398/418556 for demo.
f.setLocationByPlatform(true);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}

Java fade in and out of images

I am trying to learn how to fade in and out images into another image or from another image. So, if I have 2 images, and 1 is being displayed at the moment, I want to display another image in the background and fade the first image out into the 2nd image. OR, I want to set the focus on the new image and slowly fade it in over the 1st image, then stop displaying the 1st one.
I'm not sure how:
to set focus, if even needed.
I can fade in if I change the alpha to 0 and increment up and only draw one image, however I cannot get it to fade out either with any variation of this code. (i.e. commenting out one image to draw).
Edit: Really, all I'm worried about is being able to have 2 images and make the image currently being displayed slowly disappear into the 2nd image. How that is accomplished doesn't need to be with this.
Here is a code sample I'm messing with:
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class FadeIn extends JPanel implements ActionListener {
private Image imagem;
private Image image2;
private Timer timer;
private float alpha = 1f;
public FadeIn() {
imagem = (new ImageIcon(getClass().getResource(
"/resources/1stImage.jpg"))).getImage();
image2 = (new ImageIcon(getClass().getResource(
"/resources/2ndImage.jpg"))).getImage();
timer = new Timer(20, this);
timer.start();
}
// here you define alpha 0f to 1f
public FadeIn(float alpha) {
imagem = (new ImageIcon(getClass().getResource(
"/resources/1stImage.jpg"))).getImage();
this.alpha = alpha;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(imagem, 0, 0, 400, 300, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
alpha));
g2d.drawImage(image2, 0, 0, 400, 300, null);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Fade out");
frame.add(new FadeIn());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(420, 330);
// frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
alpha += -0.01f;
if (alpha <= 0) {
alpha = 0;
timer.stop();
}
repaint();
}
}
Basically, what this does is use the same alpha value, fading in from 0-1 and then using the same alpha, going from 1-0, allowing the two images to cross fade over each other...
The magic basically, happens in the paintComponent, where the image coming in using the alpha value and the outgoing image uses 1f - alpha.
Switching between the two images is actually a the same process, expect the inImage is swapped for the outImage
The timing is little different. Instead of a straight move from 0-1 using a standard delta (ie 0.01 for example), this uses a time based algorithm.
That is, I use a timer which ticks every 40 milliseconds or so, it then does a calculation based on the amount of time the timer has being running and calculates the alpha value accordingly...
This allows you to change the amount of time the animation will take, but also provides a slightly better algorithm that takes into account the passive nature of Swings rendering engine...
import java.awt.AlphaComposite;
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 FadeImage {
public static void main(String[] args) {
new FadeImage();
}
public FadeImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public static final long RUNNING_TIME = 2000;
private BufferedImage inImage;
private BufferedImage outImage;
private float alpha = 0f;
private long startTime = -1;
public TestPane() {
try {
inImage = ImageIO.read(new File("/path/to/inImage"));
outImage = ImageIO.read(new File("/path/to/outImage"));
} catch (IOException exp) {
exp.printStackTrace();
}
final Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
} else {
long time = System.currentTimeMillis();
long duration = time - startTime;
if (duration >= RUNNING_TIME) {
startTime = -1;
((Timer) e.getSource()).stop();
alpha = 0f;
} else {
alpha = 1f - ((float) duration / (float) RUNNING_TIME);
}
repaint();
}
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
alpha = 0f;
BufferedImage tmp = inImage;
inImage = outImage;
outImage = tmp;
timer.start();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(
Math.max(inImage.getWidth(), outImage.getWidth()),
Math.max(inImage.getHeight(), outImage.getHeight()));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
int x = (getWidth() - inImage.getWidth()) / 2;
int y = (getHeight() - inImage.getHeight()) / 2;
g2d.drawImage(inImage, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(1f - alpha));
x = (getWidth() - outImage.getWidth()) / 2;
y = (getHeight() - outImage.getHeight()) / 2;
g2d.drawImage(outImage, x, y, this);
g2d.dispose();
}
}
}
This is a easy and short most developers using java code for image fade.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
*
* #author ADMIN
*/
public class ImageFade extends JFrame {
ImageFade() {
setLayout(null);
JLabel l = new JLabel();
l.setBounds(0, 0, 100, 96);
add(l);
Thread tp = new Thread() {
#Override
public void run() {
for (int amp = 0; amp <= 500; amp++) {
try {
sleep(1);
try {
BufferedImage bim = ImageIO.read(new File("src/image/fade/image.png"));
BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D createGraphics = nbim.createGraphics();
createGraphics.drawImage(bim, null, 0, 0);
RescaleOp r = new RescaleOp(new float[]{1f, 1f, 1f, (float) amp / 500}, new float[]{0, 0, 0, 0}, null);
BufferedImage filter = r.filter(nbim, null);
l.setIcon(new ImageIcon(filter));
} catch (Exception ex) {
System.err.println(ex);
}
} catch (InterruptedException ex) {
}
}
}
};
tp.start();
setUndecorated(true);
setBackground(new Color(0, 0, 0, 0));
setSize(100, 96);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setAlwaysOnTop(true);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
ImageFade fr = new ImageFade();
}
}
in this code you can see a thread code. in the thread this image will fade in.
the used image is stack overflow web page's logo image.
only by shown code the image will fade in.
Thread tp = new Thread() {
#Override
public void run() {
for (int amp = 0; amp <= 500; amp++) {
try {
sleep(1);
try {
BufferedImage bim = ImageIO.read(new File("src/image/fade/image.png"));
BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D createGraphics = nbim.createGraphics();
createGraphics.drawImage(bim, null, 0, 0);
RescaleOp r = new RescaleOp(new float[]{1f, 1f, 1f, (float) amp / 500}, new float[]{0, 0, 0, 0}, null);
BufferedImage filter = r.filter(nbim, null);
l.setIcon(new ImageIcon(filter));
} catch (Exception ex) {
System.err.println(ex);
}
} catch (InterruptedException ex) {
}
}
}
};
tp.start();
This code is very simple to use.
This is not from any book, internet or etc. It is developed by me.
A normal image is not able to change alpha. By code : BufferedImage nbim = new BufferedImage(bim.getWidth(), bim.getHeight(), BufferedImage.TYPE_INT_ARGB); the image will convert to ARGB - Alpha, Red, Green, Blue (R,G,B,A) image.
So you can change the alpha of a image.

Zoom box for area around mouse location on screen [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
Is there any way to create a dynamic Zoom Box in Java which will include e. g. 20x20pix area around the cursor (but even when cursor will move beyond the Frame of app) and which will be shown for example in a small JPanel?
I'm asking in context of a Color Chooser program. The last functionality need to be implemented is just that Zoom Box.
I'm sure there are a number of different ways that this could be achieved.
This basically uses a separate component, which acts as the "zoom box". You supply it a component that you want to "zoom" on. It adds a mouse listener so it can monitor mouse motion events and enter and exit events.
These are used to determine when the "popup" window should be shown, where the popup window should be shown and the area that should be "painted".
This uses the "component to be zoomed" paint method to paint a region to of it to a backing buffer, which is then scaled and painted to the "zoom box"...simple
I've not played around with the zoom factor, so there may still be some quirks, but you should get the basic idea...
While I've presented a image to act as the background, this should work on any component
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.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ZoomBoxWindow {
public static void main(String[] args) {
new ZoomBoxWindow();
}
public ZoomBoxWindow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane pane = new TestPane();
ZoomPane zoomPane = new ZoomPane(pane);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class ZoomPane extends JPanel {
protected static final int ZOOM_AREA = 40;
private JComponent parent;
private JWindow popup;
private BufferedImage buffer;
private float zoomLevel = 2f;
public ZoomPane(JComponent parent) {
this.parent = parent;
popup = new JWindow();
popup.setLayout(new BorderLayout());
popup.add(this);
popup.pack();
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
Point pos = e.getLocationOnScreen();
updateBuffer(p);
popup.setLocation(pos.x + 16, pos.y + 16);
repaint();
}
#Override
public void mouseEntered(MouseEvent e) {
popup.setVisible(true);
}
#Override
public void mouseExited(MouseEvent e) {
popup.setVisible(false);
}
};
parent.addMouseListener(ma);
parent.addMouseMotionListener(ma);
}
protected void updateBuffer(Point p) {
int width = Math.round(ZOOM_AREA);
int height = Math.round(ZOOM_AREA);
buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
AffineTransform at = new AffineTransform();
int xPos = (ZOOM_AREA / 2) - p.x;
int yPos = (ZOOM_AREA / 2) - p.y;
if (xPos > 0) {
xPos = 0;
}
if (yPos > 0) {
yPos = 0;
}
if ((xPos * -1) + ZOOM_AREA > parent.getWidth()) {
xPos = (parent.getWidth() - ZOOM_AREA) * -1;
}
if ((yPos * -1) + ZOOM_AREA > parent.getHeight()) {
yPos = (parent.getHeight()- ZOOM_AREA) * -1;
}
at.translate(xPos, yPos);
g2d.setTransform(at);
parent.paint(g2d);
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (buffer != null) {
AffineTransform at = g2d.getTransform();
g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel));
g2d.drawImage(buffer, 0, 0, this);
g2d.setTransform(at);
}
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
public class TestPane extends JPanel {
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(new File("/path/to/your/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
Updated with "screen" version
This version will allow you to display a "zoom window" any where on the screen.
This has a minor issue in the fact that you need to hide the zoom window before you capture the screen, then re-show it.
I might be tempted to change the process so that when the updateBuffer method detected that the mouse position hadn't changed, it updated the buffer and showed the zoom window. When the mouse position changes, it would hide the window again...but that's me ;)
import java.awt.AWTException;
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.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.Action;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA;
public class GlobalZoomBox {
public static void main(String[] args) {
new GlobalZoomBox();
}
public GlobalZoomBox() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Zoomer zoomer = new Zoomer();
zoomer.setZoomWinodwVisible(true);
}
});
}
public class Zoomer extends JPanel {
protected static final int ZOOM_AREA = 40;
private JWindow popup;
private BufferedImage buffer;
private Robot bot;
private float zoomLevel = 2f;
private Point lastPoint;
private final Timer timer;
public Zoomer() {
popup = new JWindow();
popup.setLayout(new BorderLayout());
popup.add(this);
popup.pack();
try {
bot = new Robot();
} catch (AWTException ex) {
ex.printStackTrace();
}
timer = new Timer(125, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateBuffer();
}
});
timer.setCoalesce(true);
timer.setInitialDelay(0);
}
public void setZoomWinodwVisible(boolean value) {
if (value && !popup.isVisible()) {
timer.start();
popup.setVisible(true);
} else {
timer.stop();
popup.setVisible(false);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel));
}
protected void updateBuffer() {
if (bot != null) {
PointerInfo info = MouseInfo.getPointerInfo();
Point p = info.getLocation();
if (lastPoint == null || !lastPoint.equals(p)) {
int x = p.x - (ZOOM_AREA / 2);
int y = p.y - (ZOOM_AREA / 2);
popup.setLocation(p.x + 16, p.y + 16);
popup.setVisible(false);
buffer = bot.createScreenCapture(new Rectangle(x, y, ZOOM_AREA, ZOOM_AREA));
popup.setVisible(true);
lastPoint = p;
repaint();
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (buffer != null) {
AffineTransform at = g2d.getTransform();
g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel));
g2d.drawImage(buffer, 0, 0, this);
g2d.setTransform(at);
}
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
}
Updated with "tooltip" style popup
The main problems with the second example is the fact that you need to hide the popup in order to grab a screen shoot. This is done to prevent the popup from begin captured as well. This makes the popup "flash" every time the mouse is moved.
You "could" get around this ensuring the popup is positioned out side the range of the capture, but as you increase the capture area, the popup will move further away from the cursor.
This would, of course, be a great solution for fixed position display (ie, you had a panel fixed on a JFrame instead of a floating box)
This is an additional update that uses a second timer to display the zoom box after the user has stopped moving the mouse.
import java.awt.AWTException;
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.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.Action;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static zoomboxwindow.ZoomBoxWindow.ZoomPane.ZOOM_AREA;
public class GlobalZoomBox {
public static void main(String[] args) {
new GlobalZoomBox();
}
public GlobalZoomBox() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Zoomer zoomer = new Zoomer();
zoomer.setZoomWinodwVisible(true);
}
});
}
public class Zoomer extends JPanel {
protected static final int ZOOM_AREA = 80;
private JWindow popup;
private BufferedImage buffer;
private Robot bot;
private float zoomLevel = 2f;
private Point lastPoint;
private final Timer timer;
private final Timer popupTimer;
public Zoomer() {
popup = new JWindow();
popup.setLayout(new BorderLayout());
popup.add(this);
popup.pack();
try {
bot = new Robot();
} catch (AWTException ex) {
ex.printStackTrace();
}
timer = new Timer(125, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateBuffer();
}
});
timer.setCoalesce(true);
timer.setInitialDelay(0);
popupTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (lastPoint != null) {
System.out.println("lastPoint = " + lastPoint);
popup.setVisible(false);
Point p = lastPoint;
int x = p.x - (ZOOM_AREA / 2);
int y = p.y - (ZOOM_AREA / 2);
popup.setLocation(p.x + 16, p.y + 16);
buffer = bot.createScreenCapture(new Rectangle(x, y, ZOOM_AREA, ZOOM_AREA));
repaint();
popup.setVisible(true);
}
}
});
popupTimer.setRepeats(false);
}
public void setZoomWinodwVisible(boolean value) {
if (value && !popup.isVisible()) {
timer.start();
popup.setVisible(true);
} else {
timer.stop();
popup.setVisible(false);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(Math.round(ZOOM_AREA * zoomLevel), Math.round(ZOOM_AREA * zoomLevel));
}
protected void updateBuffer() {
if (bot != null) {
PointerInfo info = MouseInfo.getPointerInfo();
Point p = info.getLocation();
if (lastPoint == null || !lastPoint.equals(p)) {
lastPoint = p;
popupTimer.stop();
popup.setVisible(false);
} else {
if (!popup.isVisible()) {
popupTimer.start();
}
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (buffer != null) {
AffineTransform at = g2d.getTransform();
g2d.setTransform(AffineTransform.getScaleInstance(zoomLevel, zoomLevel));
g2d.drawImage(buffer, 0, 0, this);
g2d.setTransform(at);
}
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;
class ZoomOnMouse {
public static void main(String[] args) throws AWTException {
final Robot robot = new Robot();
Runnable r = new Runnable() {
#Override
public void run() {
final int size = 256;
final BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_RGB);
final JLabel gui = new JLabel(new ImageIcon(bi));
ActionListener zoomListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
BufferedImage temp = robot.createScreenCapture(
new Rectangle(p.x-(size/4), p.y-(size/4),
(size/2), (size/2)));
Graphics g = bi.getGraphics();
g.drawImage(temp, 0, 0, size, size, null);
g.dispose();
gui.repaint();
}
};
Timer t = new Timer(40, zoomListener);
t.start();
JOptionPane.showMessageDialog(null, gui);
t.stop();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}

Simple way of creating an animated JScrollPane in Java?

I currently have a JScrollPane that holds what is basically a list of items. This JScrollPane is to be displayed on an information screen.
What I'm looking for is some way of making it automatically scroll to the bottom of the list at a given interval, then back to the top. I recognise this is probably not achievable using a JScrollPane, so any suggestions for alternatives would also be great!
Normally I would use the TimingFramework or you could use something like Trident or the Unviversal Tween Engine as a bases for any animation. The main reason is, apart from doing most of the work for you, they also provide variable speed, which will make the animation look more natural.
But you can achieve the basic concept using a javax.swing.Timer.
This example will allow you to scroll to the bottom of an image and back again.
The animation will take 5 seconds (as supplied by the runningTiming variable), allowing it to be variable (the larger the image, the faster the movement, the smaller the image, the slower).
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.JScrollPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AutoScroller {
public static void main(String[] args) {
new AutoScroller();
}
private long startTime = -1;
private int range = 0;
private int runningTime = 5000;
private int direction = 1;
public AutoScroller() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final JScrollPane scrollPane = new JScrollPane(new TestPane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(scrollPane);
// frame.pack();
frame.setSize(scrollPane.getPreferredSize().width, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
range = scrollPane.getViewport().getView().getPreferredSize().height - scrollPane.getHeight();
}
long duration = System.currentTimeMillis() - startTime;
float progress = 1f;
if (duration >= runningTime) {
startTime = -1;
direction *= -1;
// Make the progress equal the maximum range for the new direction
// This will prevent it from "bouncing"
if (direction < 0) {
progress = 1f;
} else {
progress = 0f;
}
} else {
progress = (float) duration / (float) runningTime;
if (direction < 0) {
progress = 1f - progress;
}
}
int yPos = (int) (range * progress);
scrollPane.getViewport().setViewPosition(new Point(0, yPos));
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
});
}
public class TestPane extends JPanel {
private BufferedImage image;
public TestPane() {
try {
image = ImageIO.read(new File("Path/to/your/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2d.drawImage(image, x, y, this);
g2d.dispose();
}
}
}
}
Have you looked into using a timer to send scroll instructions to the JScrollPane at intervals? Just the first thing that comes to mind...

Categories