How can I create a 'cooldown rectangle' effect in Java? [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Edit: In order to make this a little more specific, I wanted to know how to create the timeout effect as seen in the image. I know about painting an image and such, but I did not understand the logic behind the timeout effect, hence the question.
I've been doing some research on this 'cooldown rectangle' effect and it seems to be doable in many other languages, but so far I haven't seen many solutions in regards to Java. Essentially I would like to create a function that does an effect like this over an image.
I already know the basics of overlaying an image, and I've come across a class which does something like this but in the more commonly known 'circular' version.
I did find this tutorial which explained how to create the effect above using GameMaker. But I'm not sure how to transfer that knowledge to Java.
Any help would be appreciated, thanks.

So, what you need is...
Some way to load an image
Some way to paint the image
Some way to paint a timeout effect over the image
Some way to update the UI at a regular interval based, calculating the amount of time remaining and updating the UI
Maybe start with:
Reading/Loading an Image
Painting in AWT and Swing and Performing Custom Painting
2D Graphics
Concurrency in Swing and How to use Swing Timers
For example...
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.RenderingHints;
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 Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TimeOutPane tp = new TimeOutPane();
tp.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
tp.executeTimeout();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TimeOutPane extends JPanel {
private BufferedImage background;
private float progress = 0;
private long startedAt;
private int timeout = 5000;
private Timer timer;
public TimeOutPane() throws IOException {
background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/Ponies/url.png"));
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
public void setProgress(float progress) {
this.progress = progress;
repaint();
}
public float getProgress() {
return progress;
}
public void executeTimeout() {
if (timer == null) {
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long diff = System.currentTimeMillis() - startedAt;
float progress = diff / (float) timeout;
if (diff >= timeout) {
progress = 1f;
timer.stop();
}
setProgress(progress);
}
});
} else if (timer.isRunning()) {
timer.stop();
}
startedAt = System.currentTimeMillis();
timer.start();
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
applyQualityRenderingHints(g2d);
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.setColor(Color.BLACK);
int radius = Math.max(getWidth(), getHeight()) / 2;
g2d.fillArc(-radius, -radius, radius * 4, radius * 4, 90, (int) (360f * (1f - progress)));
g2d.dispose();
}
}
public void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
}
}

Related

Java analogue clock

I am trying to implement a simple analogue clock in java. My clock successfully displays the time when I first run the program, however upon opening the time remains the same and none of the drawing updates and it freezes. I don't understand why it is not working and I have looked through the forum trying to find someone with a similar problem and cannot. If anyone can find where I am going wrong I would greatly appreciate it, thanks
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing. JPanel;
public class ClockFace extends JPanel {
Date date = new Date();
private BufferedImage clockFace;
public ClockFace() {
this.init();
this.startClock();
}
private void init() {
JFrame window = new JFrame("Clock");
window.setContentPane(this);
this.setPreferredSize(new Dimension(600,600));
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setLocationRelativeTo(null);
}
//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
public void startClock() {
while(true) {
int seconds = date.getSeconds();
int minutes = date.getMinutes();
int hours = date.getHours();
clockFace = new BufferedImage(600,600,BufferedImage.TYPE_INT_ARGB);
Graphics2D twoD = clockFace.createGraphics();
twoD.setColor(Color.BLACK);
twoD.fillRect(0, 0, 600, 600);
twoD.setColor(Color.WHITE);
twoD.translate(300,300);
//Drawing the hour markers
for(int i=0; i<12; i++) {
twoD.drawLine(0, -260, 0, -300);
twoD.rotate(Math.PI/6);
}
twoD.rotate(seconds*Math.PI/30);
twoD.drawLine(0, 0, 0, -290);
twoD.rotate(2*Math.PI-seconds*Math.PI/30);
twoD.rotate(minutes*Math.PI/30);
twoD.setStroke(new BasicStroke(3));
twoD.drawLine(0, 0, 0, -250);
twoD.rotate(2*Math.PI-minutes*Math.PI/30);
twoD.rotate(hours*Math.PI/6);
twoD.setStroke(new BasicStroke(6));
twoD.drawLine(0, 0, 0, -200);
repaint();
//Pausing until the next "tick"
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You're blocking the Event Dispatching Thread, preventing it from processing any new input events or processing any new paint events
See Concurrency in Swing for more details.
So instead of...
public void startClock() {
while(true) {
//...
}
}
You should be using something more like...
public void startClock() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//... Update time and schedule repaint
}
}
}
See How to Use Swing Timers for more details
You will also find that this...
//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
Gives you issues (paint artefacts). It should be..
//Draws the image to the ClockFace panel
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
Updated...
There's been (too) much discussion over weather the core issue is to do with the potential blocking of the Event Dispatching Thread or the non-mutable nature of the Date class.
The fact is, is probably both.
java.util.Date is a snapshot of a point in time (when it's created), it doesn't change and is not updated. So, based on your example, you'd have to update the date instance on each iteration of the loop.
A better solution would probably be to use java.time.LocalTime, apart from been more up-to-date, it's generally simpler to use (IMHO)
For example...
import java.awt.BasicStroke;
import java.awt.Color;
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.time.LocalTime;
import java.time.temporal.TemporalField;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ClockFace());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ClockFace extends JPanel {
public ClockFace() {
this.startClock();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
LocalTime now = LocalTime.now();
int seconds = now.getSecond();
int minutes = now.getMinute();
int hours = now.getHour();
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, 600, 600);
g2d.setColor(Color.WHITE);
g2d.translate(300, 300);
//Drawing the hour markers
for (int i = 0; i < 12; i++) {
g2d.drawLine(0, -260, 0, -300);
g2d.rotate(Math.PI / 6);
}
g2d.rotate(seconds * Math.PI / 30);
g2d.drawLine(0, 0, 0, -290);
g2d.rotate(2 * Math.PI - seconds * Math.PI / 30);
g2d.rotate(minutes * Math.PI / 30);
g2d.setStroke(new BasicStroke(3));
g2d.drawLine(0, 0, 0, -250);
g2d.rotate(2 * Math.PI - minutes * Math.PI / 30);
g2d.rotate(hours * Math.PI / 6);
g2d.setStroke(new BasicStroke(6));
g2d.drawLine(0, 0, 0, -200);
g2d.dispose();
}
public void startClock() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
}
}
Insert the computation of date right after while(true).
That's not the way to write a program doing a task scheduled at time increments. It only fixes your immediate problem. See other answers.

Java Swing -- Key Input with JPanel added to JOptionpane

When I run the code, the added Example1 class to the JOptionPane (in Frame) should get keyInput and then change the y value of the player instance (in example1), but it doesn't work. Also, how would I be able to rotate the ship on its axis and then move in the direction its facing? Currently it moves in the direction its rotated towards, but it rotates on what seems the coordinates 0,0.
Frame
import javax.swing.*;
import java.awt.*;
/**
* Created by griffin on 12/7/2015.
*/
public class Frame extends JFrame {
public Frame() {
initUI();
}
private void initUI() {
JTabbedPane jtp = new JTabbedPane();
Example1 e1 = new Example1();
Example2 e2 = new Example2();
getContentPane().add(jtp);
jtp.add(e1);
jtp.add(e2);
jtp.addTab("Example 1", e1);
jtp.addTab("Example 2", e2);
setResizable(false);
pack();
setTitle("NLTP");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new Frame();
frame.setVisible(true);
}
});
}
}
Example1
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
/**
* Created by griffin on 12/7/2015.
*/
public class Example1 extends JPanel implements Runnable {
private final int B_WIDTH = 640;
private final int B_HEIGHT = 480;
private int DELAY = 25;
private Thread thread;
Ship player = new Ship(320, 240);
public Example1() {
initScreen();
}
private void initScreen() {
JButton explanation = new JButton("Explanation");
explanation.setBounds(0, 0, 150, 30);
this.setLayout(null);
add(explanation);
addKeyListener(new keyInput());
setFocusable(true);
setBackground(Color.BLACK);
setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
setDoubleBuffered(true);
}
#Override
public void addNotify() {
super.addNotify();
thread = new Thread(this);
thread.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
AffineTransform old = g2d.getTransform();
g2d.rotate(Math.toRadians(player.angle));
g2d.drawImage(player.ship, player.x, player.y, null);
g2d.setTransform(old);
Toolkit.getDefaultToolkit().sync();
}
public void cycle() {
player.y += player.vY;
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}
public class keyInput extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W) {
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_W) {
player.vY -= 1;
}
if(key == KeyEvent.VK_A) {
player.angle++;
}
if(key == KeyEvent.VK_D) {
player.angle--;
}
}
}
}
KeyListener is well known for having focus related issues. Not only does the component need to be focusable, but it has to have keyboard focus before it will register key events. This is an issue as it's all to easy for your component to lose focus for any number of reasons.
The solution is to use the key bindings API which was designed to help solve this issue. See How to Use Key Bindings for more details.
Swing uses a passive rendering approach. That is, updates occur when ever the API decides something needs to be updated. See Painting in AWT and Swing for more details
What you really need is some kind of active rendering approach, where updates are made on a regular bases. This can be accomplished in a verity of ways, the simplest would be to use a Swing Timer, as it's safe to update the UI (or values that the UI relies on) without the risk of introducing race conditions. See How to use Swing Timers for more details
So, this example basically abstracts the input into four basic movements, rotate left/right and up/down. The code doesn't care how those inputs are generated, only that they can be.
It then uses the key bindings API to register actions for the inputs. This is all done with a single Action class, which just adds the Input to a Set, which the Timer uses to determine what actions should be applied before requesting the UI be repainted.
The rotation is accomplished through the use of a AffineTransform. First we translate the origin to the sprites current x/y position, then rotate it around the center of the sprite. This reduces a lot of the complexity/issues related to rotating things (me simple)
AffineTransform at = AffineTransform.getTranslateInstance(xPos, yPos);
at.rotate(Math.toRadians(angle), sprite.getWidth() / 2, sprite.getHeight() / 2);
g2d.setTransform(at);
g2d.drawImage(sprite, 0, 0, this);
Just beware, a Graphics context is a shared resource, before making these type of changes, you need to make a copy of it (and dispose of it when you are finished)
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.imageio.ImageIO;
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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FlyingPoniesWithGuns {
public static void main(String[] args) {
new FlyingPoniesWithGuns();
}
public FlyingPoniesWithGuns() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
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);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public enum Input {
ROTATE_LEFT,
ROTATE_RIGHT,
UP,
DOWN
}
public class TestPane extends JPanel {
private BufferedImage sprite;
private double angle;
private int xPos, yPos;
private double xDelta, yDelta;
private Set<Input> inputs;
public TestPane() throws IOException {
inputs = new HashSet<>(25);
sprite = ImageIO.read(getClass().getResource("/Pony.png"));
xPos = (400 - sprite.getWidth()) / 2;
yPos = (400 - sprite.getHeight()) / 2;
addKeyBinding("rotate-left", KeyEvent.VK_A, Input.ROTATE_LEFT);
addKeyBinding("rotate-right", KeyEvent.VK_D, Input.ROTATE_RIGHT);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (inputs.contains(Input.ROTATE_LEFT)) {
angle -= 5;
} else if (inputs.contains(Input.ROTATE_RIGHT)) {
angle += 5;
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
AffineTransform at = AffineTransform.getTranslateInstance(xPos, yPos);
at.rotate(Math.toRadians(angle), sprite.getWidth() / 2, sprite.getHeight() / 2);
g2d.setTransform(at);
g2d.drawImage(sprite, 0, 0, this);
g2d.dispose();
}
protected void addKeyBinding(String name, int keyCode, Input input) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), name + ".pressed");
actionMap.put(name + ".pressed", new InputAction(input, true));
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, true), name + ".released");
actionMap.put(name + ".released", new InputAction(input, false));
}
protected class InputAction extends AbstractAction {
private Input input;
private boolean pressed;
public InputAction(Input input, boolean pressed) {
this.input = input;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
inputs.add(input);
} else {
inputs.remove(input);
}
}
}
}
}
Okay, what about movement? You could have a look at How do I make an entity move in a direction? and How can I move a sprite in the direction it is facing? for more ideas on how you might be able to achieve that

How to pop up a text box(or tooltip) via script in Java

I have a very specific question:
I want to be able to, via a method call, popup a tooltip with text(it could say anything) in a given location on the screen for a certain amount of time on method call(say the logic is in a talk method) and fades away. How could I go about that? Is there a way to do it via JTooltip? Or would I have to dive into JNA to get what I want?
I should mention I want the tooltip to popup with text in a given location without the cue of a mouse over, like a popup.
Also, in case a tooltip is not the right way to go about what I want (which I hope I made clear), is there a more effective alternative?
There are few ways this might be achieved. One possible way is through the use of a transparent JWindow and a Swing Timer
Basically, what this does is creates a JWindow, set's it's background color to fully transparent, making a transparent window. It then uses simple BackgroundPane (to render a nice background) and MessagePane to hold the actual message. You can do this in one panel, but I like the flexibility this affords me.
Now, personally, I would create a simpler API which could build the popup window and create a Timer with a variable delay, but you get the idea
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class PopupMessageWindow {
public static void main(String[] args) {
new PopupMessageWindow();
}
public PopupMessageWindow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final JWindow frame = new JWindow();
frame.setBackground(new Color(0, 0, 0, 0));
BackgroundPane pane = new BackgroundPane();
pane.setMessage("Boo, This is a popup...");
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
Timer timer = new Timer(10000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
System.exit(0);
}
});
timer.setRepeats(false);
timer.start();
}
});
}
public class BackgroundPane extends JPanel {
private MessagePane messagePane;
public BackgroundPane() {
setBorder(new EmptyBorder(40, 40, 40, 40));
messagePane = new MessagePane();
setLayout(new BorderLayout());
add(messagePane);
setOpaque(false);
}
public void setMessage(String msg) {
messagePane.setMessage(msg);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
LinearGradientPaint glp = new LinearGradientPaint(
new Point(0, 0),
new Point(0, getHeight()),
new float[]{0f, 1f},
new Color[]{Color.GRAY, Color.BLACK});
RoundRectangle2D frame = new RoundRectangle2D.Float(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
g2d.setPaint(glp);
g2d.fill(frame);
g2d.setColor(Color.WHITE);
g2d.draw(frame);
}
}
public class MessagePane extends JPanel {
private JLabel label;
public MessagePane() {
setOpaque(false);
label = new JLabel();
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
add(label);
}
public void setMessage(String msg) {
label.setText(msg);
}
}
}
You could play with a AlphaComposite on the background panel to create a semi transparent background
Popup window using a 50% AlphaComposite
Updated
You could use a factory or builder pattern to provide a simple API, for example...
new PopupBuilder().at(new Point(100, 100)).withMessage("Hello").withDelay(5000).show();
The builder would collect the properties you want to specify, provide defaults where you didn't set them and then would show the final popup.
The basic idea is when you call show, it would collect the properties and build the window similar to how the constructor works right now...
Updated with a fading popup window
This is (a somewhat over the top) example of how you might be able to produce a fading in/out effect. The example guarantees that the message will be on the screen (full) for at specified delay period
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class PopupMessageExample {
public static void main(String[] args) {
new PopupMessageExample();
}
public PopupMessageExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new PopupMessageBuilder().withDelay(10000).withMessage("Hello, this is a fading message").show();
}
});
}
public class PopupMessageBuilder {
private int delay;
private Point location;
private String message;
private long startTime;
private Timer fadeTimer;
public PopupMessageBuilder at(Point p) {
this.location = p;
return this;
}
public PopupMessageBuilder withDelay(int delay) {
this.delay = delay;
return this;
}
public PopupMessageBuilder withMessage(String msg) {
this.message = msg;
return this;
}
public PopupMessageBuilder show() {
final JWindow frame = new JWindow();
frame.setOpacity(0f);
frame.setBackground(new Color(0, 0, 0, 0));
BackgroundPane pane = new BackgroundPane();
pane.setMessage(message);
frame.add(pane);
frame.pack();
if (location == null) {
frame.setLocationRelativeTo(null);
} else {
frame.setLocation(location);
}
frame.setVisible(true);
frame.setAlwaysOnTop(true);
new FadeTimer(frame, 1000, 0f, 1f, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new FadeTimer(frame, 1000, 1f, 0f, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
}).start();
}
});
timer.setRepeats(false);
timer.start();
}
}).start();
return this;
}
public class FadeTimer extends Timer implements ActionListener {
private final float startAt;
private final float endAt;
private final int duration;
private long startTimer;
private ActionListener endListener;
private Window window;
public FadeTimer(Window window, int duration, float startAt, float endAt, ActionListener endListener) {
super(5, null);
addActionListener(this);
this.duration = duration;
this.startAt = startAt;
this.endAt = endAt;
this.window = window;
this.endListener = endListener;
}
#Override
public void start() {
startTime = System.currentTimeMillis();
super.start();
}
#Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long lapsed = now - startTime;
float opacity = startAt;
if (lapsed >= duration) {
opacity = endAt;
((Timer) e.getSource()).stop();
if (endListener != null) {
endListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "stopped"));
}
} else {
float progress = (float) lapsed / (float) duration;
float distance = endAt - startAt;
opacity = (float) (distance * progress);
opacity += startAt;
}
window.setOpacity(opacity);
}
}
public class BackgroundPane extends JPanel {
private MessagePane messagePane;
public BackgroundPane() {
setBorder(new EmptyBorder(40, 40, 40, 40));
messagePane = new MessagePane();
setLayout(new BorderLayout());
add(messagePane);
setOpaque(false);
}
public void setMessage(String msg) {
messagePane.setMessage(msg);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
LinearGradientPaint glp = new LinearGradientPaint(
new Point(0, 0),
new Point(0, getHeight()),
new float[]{0f, 1f},
new Color[]{Color.GRAY, Color.BLACK});
RoundRectangle2D frame = new RoundRectangle2D.Float(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
g2d.setPaint(glp);
g2d.fill(frame);
g2d.setColor(Color.WHITE);
g2d.draw(frame);
}
}
public class MessagePane extends JPanel {
private JLabel label;
public MessagePane() {
setOpaque(false);
label = new JLabel();
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
add(label);
}
public void setMessage(String msg) {
label.setText(msg);
}
}
}
}
Now, you probably also do this by changing the maximum opacity level of the frame, but, if you change the paintComponent of the BackgroundPane
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.75f);
g2d.setComposite(alpha);
you can also effect the over opacity of the popup message. This method will only effect the background, not the message text...

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);
}
}

Drawing slices of a circle in java?

I want to represent a timer by having a filled circle which is fully drawn over the course of the timer by segment. I.e. If the circle is filled in every 1 second for a timer of 4 seconds the first will show a quarter of a circle then a half then three-quarters and finally a full circle.
Is there a way to draw these slices of a circle in java? I've looked into arbitrary shapes in the graphics API but not sure if this is the right way to go or if there is something written into the language which can easily produce these type of shapes?
Any help much appreciated.
Yes, it's possible. Yes, Graphics2D has the ability to do this for you
Take a look at Drawing Geometric Primitives (look for the Arc2D section).
To "animate" the progress, it would probably be easiest to use a javax.swing.Timer, but your requirements might require you to use a SwingWorker instead. Have a look at Currency in Swing and How to use Swing Timers for more information.
The following example is relatively simple. It assumes a progress of 0-100% and generates a arc as required. It would be a simple matter of changing the color of the Graphics2D context and using draw(Shape) to draw an out line of the circle should you want one.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ArcProgress {
public static void main(String[] args) {
new ArcProgress();
}
private float progress;
public ArcProgress() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final ArcProgressPane p1 = new ArcProgressPane();
p1.setForeground(Color.RED);
final ArcProgressPane p2 = new ArcProgressPane();
p2.setForeground(Color.BLUE);
p2.setFillProgress(true);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(p1);
frame.add(p2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
progress += 0.01f;
if (progress >= 1f) {
progress = 1f;
((Timer) e.getSource()).stop();
}
p1.setProgress(progress);
p2.setProgress(progress);
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
});
}
public class ArcProgressPane extends JPanel {
private boolean fillProgress = false;
private float progress;
public ArcProgressPane() {
}
public void setFillProgress(boolean value) {
if (fillProgress != value) {
this.fillProgress = value;
firePropertyChange("fillProgress", !fillProgress, fillProgress);
}
}
public boolean isFillProgress() {
return fillProgress;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
public void setProgress(float value) {
if (progress != value) {
float old = progress;
this.progress = value;
firePropertyChange("progress", old, progress);
repaint();
}
}
public float getProgress() {
return progress;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.bottom + insets.top);
int raidus = Math.min(width, height);
int x = insets.left + ((width - raidus) / 2);
int y = insets.right + ((height - raidus) / 2);
double extent = 360d * progress;
g2d.setColor(getForeground());
Arc2D arc = null;
if (isFillProgress()) {
arc = new Arc2D.Double(x, y, raidus, raidus, 90, -extent, Arc2D.PIE);
} else {
extent = 360 - extent;
arc = new Arc2D.Double(x, y, raidus, raidus, 90, extent, Arc2D.PIE);
}
g2d.fill(arc);
g2d.dispose();
}
}
}

Categories