我想通过一个ArrayList的行;对于每一行,我检查它是否在某个区域之外。它可以在这里工作。然后,如果该行在指定区域之外,我想将该行添加到另一个ArrayList(linesOutside),然后调用repaint()以重绘另一种颜色的那些行。这是似乎不起作用的部分。 if (Clip == true)
中paintComponent()
内的代码根本没有执行(我使用消息框测试过)。我在actionPerformed中调用repaint()之前将Clip设置为True。为什么Clip在输入paintComponent()时不保持这个值?
SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
public class testClipping extends JPanel implements MouseListener, ActionListener, MouseMotionListener
{
//JComponents
static JFrame frame;
static JPanel drawingPanel;
static JButton btnSetClip;
static JButton btnClip;
//used to draw lines
double x1, y1, x2, y2;
boolean FirstPoint;
ArrayList<Line2D.Double> lines;
ArrayList<Line2D.Double> linesOutside;
//used to draw rectangle for clipping
Point startDrag, endDrag;
Rectangle2D rectangle;
boolean SetClip;
//used to clip
boolean Clip;
double X1, Y1, X2, Y2;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
CreateFrame();
}
});
}
private static void CreateFrame()
{
frame = new JFrame("Interface");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.add(new testClipping());
}
public testClipping()
{
setLayout(new BorderLayout());
CreateToolBar();
CreateDrawingPanel();
repaint(); //draw graph
lines = new ArrayList<Line2D.Double>();
btnSetClip.addActionListener(this);
btnClip.addActionListener(this);
}
//create tool bar which contains commands to drawing functions
private void CreateToolBar()
{
JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
btnSetClip = new JButton("Set clip area");
btnClip = new JButton("Clip");
toolbar.add(btnSetClip);
toolbar.addSeparator();
toolbar.add(btnClip);
btnSetClip.setAlignmentX(Component.CENTER_ALIGNMENT);
btnClip.setAlignmentX(Component.CENTER_ALIGNMENT);
toolbar.setMargin(new Insets(10,10,10,10));
toolbar.setFloatable(false);
toolbar.setBackground(Color.black);
add(toolbar, BorderLayout.WEST);
}
//create area where to draw
private void CreateDrawingPanel()
{
drawingPanel = new JPanel()
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Line2D.Double line : lines)
{
g2.drawLine((int)line.getX1(), (int)line.getY1(), (int)line.getX2(), (int)line.getY2());
}
if (SetClip == true) //draw rectangle to specify clipping area
{
if (startDrag != null && endDrag != null)
{
rectangle = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(rectangle);
}
}
if (Clip == true) //redraw, in blue, lines outside clipping area
{
JOptionPane.showMessageDialog(frame, "blue"); //FOR TESTING PURPOSE; DOES NOT EVEN EXECUTE; MEANING CLIP != TRUE
g2.setColor(Color.blue);
for (Line2D.Double lineOut : linesOutside)
{
g2.drawLine((int)lineOut.getX1(), (int)lineOut.getY1(), (int)lineOut.getX2(), (int)lineOut.getY2());
}
}
}
};
add(drawingPanel, BorderLayout.CENTER);
drawingPanel.setBackground(Color.white);
drawingPanel.addMouseListener(this);
drawingPanel.addMouseMotionListener(this);
}
public void mousePressed(MouseEvent e)
{
if (SetClip == true) //save starting points for rectangle
{
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
if (FirstPoint == false) //save coordinates of first point
{
x1 = e.getX();
y1 = e.getY();
FirstPoint = true;
}
else //save coordinates of second point, add first and second points to array and draw line
{
x2 = e.getX();
y2 = e.getY();
Line2D.Double line = new Line2D.Double(x1, y1, x2, y2);
lines.add(line);
repaint();
FirstPoint = false;
}
}
public void mouseDragged(MouseEvent e)
{
endDrag = new Point(e.getX(), e.getY());
repaint();
}
public void mouseReleased(MouseEvent e)
{
rectangle = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
repaint();
}
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2)
{
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnSetClip) //user wants to set clip area
{
SetClip = true; //flag for paintComponent to know that rectangle has to be drawn
}
else if (e.getSource() == btnClip) //user wants to perform clipping
{
//find x and y values of boundary lines of clipping area
double Xmin, Xmax, Ymin, Ymax;
Xmin = rectangle.getMinX();
Xmax = rectangle.getMaxX();
//interchange Ymin and Ymax because of Java coordinate system
Ymin = rectangle.getMaxY();
Ymax = rectangle.getMinY();
for (Line2D.Double line : lines) //for each line in drawing panel...
{
//determine if first point inside clipping area
X1 = line.getX1();
Y1 = line.getY1();
//save bit codes
String bit1 = ""; //first point
String bit2 = ""; //second point
bit1 = CalculateBit(Ymax - Y1); //first bit
bit1 = bit1 + CalculateBit(Y1 - Ymin);//second bit
bit1 = bit1 + CalculateBit(X1 - Xmax);//third bit
bit1 = bit1 + CalculateBit(Xmin - X1);//fourth bit
//determine if second point inside clipping area
X2 = line.getX2();
Y2 = line.getY2();
bit2 = CalculateBit(Ymax - Y2); //first bit
bit2 = bit2 + CalculateBit(Y2 - Ymin);//second bit
bit2 = bit2 + CalculateBit(X2 - Xmax);//third bit
bit2 = bit2 + CalculateBit(Xmin - X2);//fourth bit
//perform logical AND on bit codes
int b1 = Character.getNumericValue(bit1.charAt(0)) * Character.getNumericValue(bit2.charAt(0));
int b2 = Character.getNumericValue(bit1.charAt(1)) * Character.getNumericValue(bit2.charAt(1));
int b3 = Character.getNumericValue(bit1.charAt(2)) * Character.getNumericValue(bit2.charAt(2));
int b4 = Character.getNumericValue(bit1.charAt(3)) * Character.getNumericValue(bit2.charAt(3));
String LogicalAND;
LogicalAND = Integer.toString(b1) + Integer.toString(b2) + Integer.toString(b3) + Integer.toString(b4);
if ((bit1.equals("0000")) && (bit2.equals("0000"))) //both points within clip area
{
//no clipping to perform
}
else if (!(LogicalAND.equals("0000")))
{
Clip = true;
Line2D.Double lineOut = new Line2D.Double(X1, Y1, X2, Y2);
linesOutside.add(lineOut);
}
}
repaint();
}
}
//find whether bit is 0 or 1 to know position of point relative to clipping area
public String CalculateBit (double a)
{
if (a > 0)
{
return "1";
}
else
{
return "0";
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
}