I want to take a print screen of what is behind the JFrame, without the JFrame itself. The way I tried was to close the window, wait for a while so it fully closes, then take the print screen and then open it again. The current method is not good for what I need since I need to do it more frequently and waiting for the window to close is too much time. Also, I don't want to close the window for that.
Here is my current code:
public class Offscreen {
private static BufferedImage img;
public static void main(String[] main)
throws AWTException, InterruptedException {
JFrame frame = new JFrame() {
#Override
public void paint(Graphics g) {
if (img != null)
// draw print screen
g.drawImage(img, 0, 0, null);
}
};
frame.setSize(500, 500);
frame.setLocation(700, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setVisible(false);
Thread.sleep(200);
// take the picture
Robot r = new Robot();
img = r.createScreenCapture(frame.getBounds());
// show the source again
frame.setVisible(true);
// print on destiny
frame.repaint();
}
}
"Assuming" you only want to capture the area behind the active frame (and as you say, without the frame), then something like..
import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintScreen01 {
public static void main(String[] args) {
new PrintScreen01();
}
private Timer timer;
public PrintScreen01() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
final PrintPane printPane = new PrintPane();
final JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(printPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentMoved(ComponentEvent e) {
timer.restart();
}
#Override
public void componentResized(ComponentEvent e) {
timer.restart();
}
});
timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (frame.isVisible()) {
takeSnapShot(frame, printPane);
}
}
});
timer.setRepeats(false);
frame.setVisible(true);
// takeSnapShot(frame, printPane);
}
});
}
public void takeSnapShot(JFrame frame, PrintPane pane) {
Rectangle bounds = new Rectangle(pane.getLocationOnScreen(), pane.getSize());
frame.setVisible(false);
new SnapShotWorker(frame, pane, bounds).execute();
}
public class SnapShotWorker extends SwingWorker<BufferedImage, BufferedImage> {
private JFrame frame;
private PrintPane pane;
private Rectangle captureBounds;
public SnapShotWorker(JFrame frame, PrintPane pane, Rectangle bounds) {
this.frame = frame;
this.pane = pane;
captureBounds = bounds;
}
#Override
protected BufferedImage doInBackground() throws Exception {
Thread.sleep(125);
BufferedImage snapShot = null;
try {
Robot bot = new Robot();
snapShot = bot.createScreenCapture(captureBounds);
} catch (AWTException ex) {
ex.printStackTrace();
}
Thread.sleep(125);
return snapShot;
}
#Override
protected void done() {
try {
BufferedImage snapShot = get();
pane.setSnapShot(snapShot);
frame.setVisible(true);
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
}
}
public class PrintPane extends JPanel {
private BufferedImage background;
public PrintPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void setSnapShot(BufferedImage img) {
background = img;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
}
}
May help...
Now, I had some issues with the timing of Robot, it would seem that part of the operation is threaded in some way, meaning that unless you got the timing of the frame changing between invisible and visible "just" right, you would actually recapture the frame...annoying...
To try and fix this, and reduce the amount of times I tried capturing the screen, I employed a javax.swing.Timer (to reduce the capture attempts) and a SwingWorker to control the actual snapshot process, taking it out of the Event Dispatching Thread, there by ensuring (to some degree) that the window will be invisible.
I also added some additional lag to ensure that the frame was off the screen long enough to prevent it been capture by the snapshot...
Related
In my first program repaint work corectly, but in the second program i have a problem with it.
import java.awt.Graphics;
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;
public class repaint1 {
public static void main(String[] args) {
JFrame win = new JFrame("");
test1 content = new test1();
win.setContentPane(content);
win.setSize(600, 400);
win.setLocation(100, 100);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setResizable(false);
win.setVisible(true);
content.function();
}
}
class test1 extends JPanel {
private BufferedImage img;
public int x = 50;
public int y = 50;
public test1() {
}
public void function() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
for (int i = 50; i < 150; i++) {
x = i;
y = i;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
try {
img = ImageIO.read(new File("images.jpg"));
g.drawImage(img, x, y, null);
} catch (IOException ex) {
// handle exception...
}
}
}
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class repaint2 {
public static void main(String[] args) {
JFrame f = new JFrame("JFrame");
test2 content = new test2();
f.setContentPane(content);
f.setSize(600, 400);
f.setLocation(100, 100);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.setVisible(true);
}
}
class test2 extends JPanel {
private BufferedImage img;
public int x = 50;
public int y = 50;
public test2() {
JButton button = new JButton("Start !");
button.setBounds(458, 24, 122, 23);
button.setVisible(true);
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Execute when button is pressed
function();
}
});
}
public void function() {
for (int i = 50; i < 150; i++) {
x = i;
y = i;
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
try {
img = ImageIO.read(new File("images.jpg"));
g.drawImage(img, x, y, null);
} catch (IOException ex) {
// handle exception...
}
}
}
In the first case the function() method is invoked from the main Thread, so when you invoke sleep() this Thread sleeps, which does not affect painting of the GUI.
In the second case your function() method is invoked from the ActionListener. All code executed from a listener is invoked on the Event Dispatch Thread (EDT), which is responsible for repainting the GUI. When you tell the Thread to sleep() the EDT sleeps, so it can't repaint the GUI until the loop finishes executing.
In your ActionListener code you need to start a separate Thread. One way to do this is to use a SwingWorker.
Read the section from the Swing tutorial on Concurrency for more information.
To move your image every time you need to use implements Runnable in your JPanel class. Here this class (MyJPanleClass) will behave like both as JPanel and Thread.
public class MyJPanleClass extends JPanel implements Runnable{
public MyJPanleClass(){
//constractor
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//do your staff with g
}
#Override
public void run(){
repaint();
}
}
To execute it from main class just write this code:
MyJPnaleClass jp=new MyJPanelClass();
Thread t1=new Thread(jp);
t1.start();//this will call run class
try{
t1.join();//running the thread until it finish.
}catch(Exception ex){}
If you don't have any idea about thread just follow the link to learn it: Thread in java tutorial
I have a for loop that iterates within an actionPerformed method. Basically, I have a car game. I have a panel where car images travel from side to side in a JPanel. I am trying to have the cars stop at the finish line (I am doing that by sleeping when the image reaches a certain x value) display the race results, leave the screen and race again. I need to do that four times until we have a winner.
private class RaceDisplay extends JPanel implements ActionListener{
private Image img1,img2;
private int velX1,velX2;
private int x1,x2;
private Timer tm;
private JTextArea text1 = new JTextArea();
public RaceDisplay(){
tm = new Timer(30,this);
x1=0;
x2=0;
velX1=2;
velX2 =2;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
ImageIcon car1 = new ImageIcon("...");
ImageIcon car2 = new ImageIcon("...");
img1 = car1.getImage();
img2 = car2.getImage();
g.drawImage(img1,x1,100,null);
g.drawImage(img2,x2,200,null);
tm.start();
}
public void actionPerformed(ActionEvent e) {
x1=x1+velX1;
velX2= x2+velX2;
repaint();
for(int count = 0;count<=4;count++){//<-----loop with issues.
if(count == 1){
text1.setText(result());
}
if(x1>=650 && x2>=650){ //does this when both cars reach the line
velX1=0;
velX2=0;
try {
Thread.sleep(2500);
} catch (InterruptedException ex) {
Logger.getLogger(Display.class.getName()).log(Level.SEVERE, null, ex);
}
x1=0;
x2=0;
repaint();
velX1= x1+velX1;
velX2= x2+velX2;
}
}
repaint();
}
I created the for loop that should check the if statements when it reaches the last counter it displays the winner(method for winner in the code). I was expecting the images to travel from side to four times and display the results four times.
But it only display anything if i set the if(counter==1) to (counter==0).
Can anyone help?
Thanks.
Don't call tm.start(); from within the paintComponent method, this is just asking for trouble. Painting may occur for any number of reasons, many of which you don't control or have knowledge about
Don't call Thread.sleep from within the context of the Event Dispatching Thread. This isn't stopping the Timer, but is prevent the EDT from processing the Event Queue, which includes things like repaint events and timer events...
Instead, once you've detected that a car has passed the finish line, you can either, stop updating that car's position and/or stop the Timer
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 {
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 Map<BufferedImage, Rectangle> carBounds;
private BufferedImage blueCar;
private BufferedImage redCar;
public TestPane() {
carBounds = new HashMap<>(25);
try {
blueCar = ImageIO.read(getClass().getResource("/BlueCar.png"));
redCar = ImageIO.read(getClass().getResource("/RedCar.png"));
int x = 0;
int y = (200 / 2 ) - blueCar.getHeight();
carBounds.put(blueCar, new Rectangle(x, y, blueCar.getWidth(), blueCar.getHeight()));
y = (200 / 2);
carBounds.put(redCar, new Rectangle(x, y, redCar.getWidth(), redCar.getHeight()));
} catch (IOException ex) {
ex.printStackTrace();
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (BufferedImage img : carBounds.keySet()) {
Rectangle bounds = carBounds.get(img);
int xDelta = (int)Math.round((Math.random() * 7) + 1);
bounds.x += xDelta;
if (bounds.x + bounds.width > getWidth()) {
bounds.x = getWidth() - bounds.width;
((Timer)e.getSource()).stop();
}
}
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (BufferedImage img : carBounds.keySet()) {
Rectangle bounds = carBounds.get(img);
g2d.drawImage(img, bounds.x, bounds.y, this);
}
g2d.dispose();
}
}
}
Take a closer look at Concurrency in Swing for more details
I'm fairly new to java, so i don't think I have this fairly close to right, but I can seem to find any other help with this. Basically, I'm trying to animate a jPanel's background color so that it's hue (I'm using an hsb color model) changes. sort of like this: https://kahoot.it/#/ notice how the color kinda floats from one to another. Here is my code that I have so far:
public void animate(){
for(float i=.001f;i<1f;i+=.001f){
jPanel1.setBackground(Color.getHSBColor(i, .53f, .97f));
try{
Thread.sleep(5L);
}catch(InterruptedException ex){
}
System.out.println(i);
}
}
now i know this probably isn't right, but the loop works fine, the only problem is that the jPanel doesn't "update" until the loop is finished. Sorry all for being a huge noob at stuff like this, and thanks for any responses
The problem is that you are blocking the event dispatch thread, so no drawing can happen. Use a swing Timer instead of sleeping. A running example of changing HSB colors:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ColorCycle {
private static class ColorPanel extends JPanel {
private final float stepSize;
private final Timer timer;
private int index;
ColorPanel(final int steps, int fps) {
stepSize = 1f / steps;
timer = new Timer(1000 / fps, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
index++;
if (index > steps) {
index = 0;
}
repaint();
}
});
}
void start() {
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.getHSBColor(index * stepSize, 1f, 1f));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Colors");
ColorPanel panel = new ColorPanel(300, 20);
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
panel.start();
}
});
}
}
Works for me...
import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class HsbBackground {
public static void main(String[] args) throws Exception {
new HsbBackground();
}
private JPanel jPanel1 = new JPanel();
public HsbBackground() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
JFrame jFrame = new JFrame();
jFrame.setContentPane(jPanel1);
jFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
jFrame.setSize(400, 300);
jFrame.setVisible(true);
}
});
animate();
}
public void animate() {
for (float i = .001f; i < 1f; i += .001f) {
final float j = i;
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jPanel1.setBackground(Color.getHSBColor(j, .53f, .97f));
}
});
try {
Thread.sleep(5L);
} catch (InterruptedException ex) {
}
System.out.println(i);
}
}
}
Make sure, that you call setVisible of your frame before you start your loop.
PS: I updated the code, so that GUI changes are all made from the event dispatching thread. The code still works fine.
I have the following code.I want to display the images in my chick array on the screen after some time delay.The coordinates have to be shifted by 10px each x direction when the new
image is loaded.I would like to know what additional code snippets can i add in this code to have an animation on my Frame with the two images i have .Below is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
public class Chicken extends Frame implements Runnable{
Thread animation;
long frameDelay = 3000;
Image chick[] = new Image[2];
int numFrames = chick.length;
Toolkit tk = getToolkit();
public Chicken()
{
setSize(new Dimension(300,300));
setVisible(true);
setBackground(Color.BLACK);
animation = new Thread(this);
chick[0] = tk.createImage("stand.png");
chick[1] = tk.createImage("walk.png");
animation.start();
//setVisible(false);
}
public void paint(Graphics g)
{
g.drawImage(chick[0],100,100,null );
}
#Override
public void run() {
// TODO Auto-generated method stub
repaint();
try {
Thread.sleep(frameDelay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String args[])
{
Chicken instance = new Chicken();
}
}
So, the first problem you have is a resource issue.
Resources stored "within" the application (typically known as embedded resources) can't be loaded like external resources.
chick[0] = tk.createImage("stand.png");
Is expecting a file "./stand.png" which doesn't exist. Instead, you need to load the resource through the Class#getResource API...
chick[0] = tk.createImage(getClass().getResource("/stand.png"));
The second problem you will face is the fact that you are overriding paint of a top level container. This really shouldn't be done. Let's start with the fact it's not double buffered and end with the fact that frames have decorations which sit inside the viewable area. This means that the decorations will overlap what ever you paint to the surface...not pretty...
The third problem is you are not telling the image where it should move to. It's static.
You need some kind of x/y value that tells the image where it should be painted. You would modify these values by a given x/y delta within you thread before you called repaint...
The forth problem you might have is the fact that you are using AWT...which is kind of dated. Swing would solve your double buffering issue for you...IMHO, would make a better choice - there's a lot more documentation and examples on Swing laying around now days ;)
While I'm on my hobble horse...I would, personally, recommend ImageIO over Toolkit#createImage or ImageIcon, mostly because it supports more formats, but also because it will throw an Exception when the image can't be read for some reason...
I have a simple example if Swing, but I won't post it, because I'll get in trouble for running of topic...let me know if you would like to see it
Updated with Swing example
This uses a embedded image in the default package...
import java.awt.BorderLayout;
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.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
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 ChickenDance {
public static void main(String[] args) {
new ChickenDance();
}
public ChickenDance() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage chicken;
private int xPos;
private int yPos;
private int xDelta = 4;
public TestPane() {
try {
chicken = ImageIO.read(getClass().getResource("/Chicken.png"));
} catch (IOException ex) {
Logger.getLogger(ChickenDance.class.getName()).log(Level.SEVERE, null, ex);
}
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
if (xPos + chicken.getWidth() > getWidth()) {
xPos = getWidth() - chicken.getWidth();
xDelta *= -1;
} else if (xPos < 0) {
xPos = 0;
xDelta *= -1;
}
yPos = (getHeight() - chicken.getHeight()) / 2;
repaint();
}
});
if (chicken != null) {
timer.start();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (chicken != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(chicken, xPos, yPos, this);
g2d.dispose();
}
}
}
}
I have a dialog where additional controls cause the dialog to resize when they appear. One day I will probably find a way to animate that, but for now I'm content with it just resizing. Problem is, it flickers.
I reduced the problem to a test:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* Shows flickering when resizing a dialog.
*/
public class FlickerTest extends FakeJDialog
{
public FlickerTest()
{
super((Window) null, "Flicker Test");
JButton button = new JButton("Bigger!");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
Window window = SwingUtilities.getWindowAncestor((Component) event.getSource());
window.setSize(window.getWidth(), window.getHeight() + 20);
}
});
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
contentPane.add(button, BorderLayout.PAGE_START);
JRootPane rootPane = new JRootPane();
rootPane.setContentPane(contentPane);
add(rootPane);
setResizable(false);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) throws Exception
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new FlickerTest().setVisible(true);
}
});
}
}
Each time I click the button, the window changes size. For a noticeable amount of time, the bottom of the dialog goes black. By recording my screen, I was able to get a screenshot demonstrating it:
How can I avoid this?
Further investigation:
The following subclass of Dialog exhibits the same flickering as JDialog:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Window;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import javax.swing.RootPaneContainer;
/**
* Minimal subclass of Dialog required to cause the flickering.
* If you comment out "implements RootPaneContainer", the flickering goes away.
*/
public class FakeJDialog extends Dialog implements RootPaneContainer
{
public FakeJDialog(Window owner, String title)
{
super(owner, title, Dialog.ModalityType.MODELESS);
}
public JRootPane getRootPane()
{
throw new UnsupportedOperationException();
}
public Container getContentPane()
{
throw new UnsupportedOperationException();
}
public void setContentPane(Container contentPane)
{
throw new UnsupportedOperationException();
}
public JLayeredPane getLayeredPane()
{
throw new UnsupportedOperationException();
}
public void setLayeredPane(JLayeredPane layeredPane)
{
throw new UnsupportedOperationException();
}
public Component getGlassPane()
{
throw new UnsupportedOperationException();
}
public void setGlassPane(Component glassPane)
{
throw new UnsupportedOperationException();
}
}
I find this kind of interesting, because merely commenting out the implements RootPaneContainer is somehow enough to completely change the behaviour. Something in Swing or AWT is obviously looking for this interface and treating those components specially. So this suggests that no subclass of JDialog would avoid the issue.
I don't believe there is a way around this with JDialog. However, java.awt.Dialog doesn't have this issue.
Try this, i have made an example which removes flickering almost completely
in addition u will get well-marked resize corner
/*
* resizing swing trick in Win7+Aero demo
* #author: s1w_
*/
import java.awt.event.*;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.*;
class ResizeHookDemo extends JDialog {
private final static int width = 580, height = 350;
private final JFileChooser fc;
private java.awt.geom.GeneralPath gp;
public ResizeHookDemo() {
super((JDialog)null, "Choose File", true);
fc = new JFileChooser() {
#Override
public void paint(Graphics g) {
super.paint(g);
int w = getWidth();
int h = getHeight();
g.setColor(new Color(150, 150, 150, 200));
g.drawLine(w-7, h, w, h-7);
g.drawLine(w-11, h, w, h-11);
g.drawLine(w-15, h, w, h-15);
gp = new java.awt.geom.GeneralPath();
gp.moveTo(w-17, h);
gp.lineTo(w, h-17);
gp.lineTo(w, h);
gp.closePath();
}
};
fc.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("CancelSelection")) {
setVisible(false);
// action...
}
else if (e.getActionCommand().equals("ApproveSelection")) {
setVisible(false);
// action...
}
}
});
MouseInputListener resizeHook = new MouseInputAdapter() {
private Point startPos = null;
public void mousePressed(MouseEvent e) {
if (gp.contains(e.getPoint()))
startPos = new Point(getWidth()-e.getX(), getHeight()-e.getY());
}
public void mouseReleased(MouseEvent mouseEvent) {
startPos = null;
}
public void mouseMoved(MouseEvent e) {
if (gp.contains(e.getPoint()))
setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
else
setCursor(Cursor.getDefaultCursor());
}
public void mouseDragged(MouseEvent e) {
if (startPos != null) {
int dx = e.getX() + startPos.x;
int dy = e.getY() + startPos.y;
setSize(dx, dy);
repaint();
}
}
};
fc.addMouseMotionListener(resizeHook);
fc.addMouseListener(resizeHook);
fc.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 20));
add(fc);
setResizable(false);
setMinimumSize(new Dimension(width, height));
setDefaultCloseOperation(HIDE_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String args[]) {
System.out.println("Starting demo...");
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ResizeHookDemo().setVisible(true);
}
});
}
}