我有一个应用程序,用户可以在其中绘制线条。有一个JButton btnClear,当用户单击时,它必须清除图形,以便用户可以重新绘制。我在btnClear上使用ActionListener来了解它何时被点击。我设置了一个布尔值Clear,以便在paintComponent()中执行正确的IF语句。然而,布尔型Clear在paintComponent()中保留了一个False值,尽管我在重新绘制()之前将其设置为True。为什么会这样?
注意:我尝试将框架的背景设置为红色,只是为了测试paintComponent()中的布尔值。
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;
public class Clipping extends JPanel implements MouseListener, ActionListener
{
static JFrame frame;
static JComboBox cboDraw;
static JButton btnClear;
static JButton btnClip;
double x1, y1, x2, y2;
boolean FirstPoint;
boolean Clear = false;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
CreateFrame();
}
});
}
private static void CreateFrame()
{
frame = new JFrame("Clipping");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Clipping());
frame.setSize(500,500);
frame.setVisible(true);
}
public Clipping()
{
setLayout(new BorderLayout());
JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
PopulateToolBar(toolbar);
add(toolbar, BorderLayout.WEST);
addMouseListener(this);
cboDraw.addMouseListener(this);
btnClip.addActionListener(this);
btnClear.addActionListener(this);
}
private static void PopulateToolBar(JToolBar toolbar)
{
String[] cboList = {"Line", "Polygon"};
cboDraw = new JComboBox(cboList);
cboDraw.setMaximumSize(new Dimension(70,30));
btnClip = new JButton("Set clip area");
btnClear = new JButton("Clear");
toolbar.add(cboDraw);
toolbar.addSeparator();
toolbar.add(btnClip);
toolbar.addSeparator();
toolbar.add(btnClear);
cboDraw.setAlignmentX(Component.CENTER_ALIGNMENT);
btnClip.setAlignmentX(Component.CENTER_ALIGNMENT);
btnClear.setAlignmentX(Component.CENTER_ALIGNMENT);
toolbar.setMargin(new Insets(10,10,10,10));
toolbar.setFloatable(false);
toolbar.setBackground(Color.black);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
if (cboDraw.getSelectedIndex() == 0) //draw line
{
g2.draw(new Line2D.Double(x1, y1, x2, y2));
}
else if (Clear == true)
{
frame.setBackground(Color.red); //ONLY FOR TESTING PURPOSE
}
}
public void mousePressed(MouseEvent e)
{
if (e.getSource() != cboDraw) //to prevent line coordinates from being saved when selecting from combobox
{
if (cboDraw.getSelectedIndex() == 0) //user wants to draw line
{
if (FirstPoint == false) //first coordinates
{
x1 = e.getX();
y1 = e.getY();
FirstPoint = true;
}
else //second coordinates
{
x2 = e.getX();
y2 = e.getY();
repaint();
FirstPoint = false;
}
}
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == btnClear)
{
Clear = true;
repaint();
Clear = false;
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
您应该只执行setBackground(Color.red);
在JPanel上调用它,而不是在JFrame 上调用它
我认为您的actionPerformed
和mousePressed
都是同时执行的。在mousePressed
中,如果btnClear()
是源,则也满足mousePressed
中的if
条件。所以无论如何都会调用repaint
方法,并且您看不到任何更改。
您没有在paintComponent方法覆盖中调用super.paintComponent(g)
方法。先打这个电话,否则,清除是行不通的。
请注意,在当前代码中,这将不适用于您,因为您的绘制不正确,因为您没有指定、迭代并绘制所有需要在paintComponent方法中绘制的线。解决这一问题的方法是通过以下两种方法之一:
- 创建一个
List<Line2D>
(如ArrayList<Line2D>
),将其填充到MouseListener/MouseMotionListener代码中,然后在paintComponent方法中迭代该List,绘制每一行。如果您这样做,那么清除按钮的操作将是通过clear()
清除列表并调用repaint()
。不需要布尔值 - 或者,您可以在BufferedImage上绘制线条,然后通过
g.drawImage(...)
方法在paintComponent方法中绘制BufferedImage。如果执行此操作,请在绘制之前始终检查图像是否为null
。然后在你的鼠标监听代码中,你会画到这张图片上。在清除按钮操作中,您需要创建一个新的BufferedImage,或者清除当前的BufferedImage
还要从paintComponent中去掉setBackground(...)
调用,因为它们真的不应该在那里。
例如使用行的ArrayList:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class DrawPanelViaArrayList extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private static final Color LINES_COLOR = Color.black;
private static final Color DRAW_LINE_COLOR = Color.pink;
private static final Stroke STROKE = new BasicStroke(3f);
private List<Line2D> lineList = new ArrayList<>();
private int x1 = 0;
private int y1 = 0;
private int x2 = 0;
private int y2 = 0;
public DrawPanelViaArrayList() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
add(new JButton(new ClearAction("Clear")));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// for smooth graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// first draw the temporary line to show the user
// where he's drawing
if (x1 != x2 && y1 != y2) {
g2.setColor(DRAW_LINE_COLOR);
g2.drawLine(x1, y1, x2, y2);
}
// then draw all the lines held in the linesList.
Stroke oldStroke = g2.getStroke();
g2.setColor(LINES_COLOR);
g2.setStroke(STROKE); // draw thicker lines
for (Line2D line2d : lineList) {
g2.draw(line2d);
}
g2.setStroke(oldStroke); // reset stroke
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getPoint().x;
y1 = e.getPoint().y;
}
@Override
public void mouseReleased(MouseEvent e) {
x2 = e.getPoint().x;
y2 = e.getPoint().y;
Line2D line = new Line2D.Double(x1, y1, x2, y2);
// add line to ArrayList
lineList.add(line);
x1 = x2 = y1 = y2 = 0;
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
x2 = e.getPoint().x;
y2 = e.getPoint().y;
// draw temporary line
repaint();
}
}
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
lineList.clear();
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawPanelViaArrayList());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
见鬼,一个BufferedImage版本的
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
@SuppressWarnings("serial")
public class DrawPanelViaBufferedImage extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private static final Color LINES_COLOR = Color.black;
private static final Color DRAW_LINE_COLOR = Color.pink;
public static final Color CLEAR_COLOR = new Color(0, 0, 0, 0);
public static final Stroke STROKE = new BasicStroke(3f);
private int x1 = 0;
private int y1 = 0;
private int x2 = 0;
private int y2 = 0;
private BufferedImage img = new BufferedImage(PREF_W, PREF_W, BufferedImage.TYPE_INT_ARGB);
public DrawPanelViaBufferedImage() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
add(new JButton(new ClearAction("Clear")));
// if the GUI is to be re-sizeable, then consider adding a
// ComponentListener here, and resizing the BufferedImage in it
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// for smooth graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// first draw the temporary line to show the user
// where he's drawing
if (x1 != x2 && y1 != y2) {
g2.setColor(DRAW_LINE_COLOR);
g2.drawLine(x1, y1, x2, y2);
}
// then draw the BufferedImage if not null
if (img != null) {
g2.drawImage(img, 0, 0, null);
}
}
// size of our GUI
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
x1 = e.getPoint().x;
y1 = e.getPoint().y;
}
@Override
public void mouseReleased(MouseEvent e) {
x2 = e.getPoint().x;
y2 = e.getPoint().y;
Line2D line = new Line2D.Double(x1, y1, x2, y2);
// draw to the BufferedImage
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(STROKE);
g2.setColor(LINES_COLOR);
g2.draw(line);
g2.dispose();
x1 = x2 = y1 = y2 = 0;
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
x2 = e.getPoint().x;
y2 = e.getPoint().y;
repaint();
}
}
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
Graphics2D g2 = img.createGraphics();
g2.setBackground(CLEAR_COLOR);
g2.clearRect(0, 0, getWidth(), getHeight());
g2.dispose();
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawPanelViaBufferedImage());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}