问题
I am trying to create a form. there is a button that when clicking the button, a photo which is specified would appear. my problem is, when I click the button, the picture pops up and if the cursor passes the form boundary, the image disappears. here is my code:
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SeamCarving extends JFrame
{
public static void main(String[] args) throws IOException {
final BufferedImage input = ImageIO.read(new File("path"));
final BufferedImage[] toPaint = new BufferedImage[]{input};
final Frame frame = new Frame("Seams") {
@Override
public void update(Graphics g) {
final BufferedImage im = toPaint[0];
if (im != null) {
g.clearRect(0, 0, getWidth(), getHeight());
g.drawImage(im, 0, 0, this);
}
}
};
frame.setSize(input.getWidth(), input.getHeight());
frame.setVisible(true);
frame.add(startButton);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
out = deleteVerticalSeam(out);
toPaint[0] = out;
frame.repaint();
System.out.println("Do Something Clicked");
}
});
}
}
回答1:
Don't override update
, this isn't how painting is achieved in Swing. Attempting to paint directly to a top level container like JFrame
is problematic at best.
Instead, start with a JPanel
and use it's paintComponent
method instead. Make sure you call super.paintComponent
as well.
In fact, you could probably just use a JLabel
to display the image instead.
Take a look at;
- Performing Custom Painting
- How to use labels
For more details
Updated with example
I still think a JLabel
would be simpler solution, but what do I know.


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SeamCarving {
public static void main(String[] args) {
new SeamCarving();
}
public SeamCarving() {
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 input;
private BufferedImage[] toPaint;
public TestPane() {
try {
input = ImageIO.read(new File("C:\\hold\\thumbnails\\2005-09-29-3957.jpeg"));
toPaint = new BufferedImage[1];
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
JButton startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
BufferedImage out = input;
out = input; //deleteVerticalSeam(out);
toPaint[0] = out;
repaint();
System.out.println("Do Something Clicked");
}
});
add(startButton);
}
@Override
public Dimension getPreferredSize() {
return input == null ? new Dimension(400, 400) : new Dimension(input.getWidth(), input.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (toPaint[0] != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(input, 0, 0, this);
g2d.dispose();
}
}
}
}
The problem with overriding update
is the paint
subsystem can choose to avoid calling and end up calling paint
directly, circumventing your painting.
Painting also involves painting child components (like your button) and borders, which you've conveniently discarded by not calling super.update
.
来源:https://stackoverflow.com/questions/21036624/jbutton-acction-listener