问题
So I'm just doing some studying for finals here, and I'm having trouble getting this to work. What I have always done previously is call paintComponent(Graphics g) and things have worked just peachy. But now I'm getting a "paintComponent has protected access in JComponent" error when I go to compile. The only way I could get it to compile was to tell it to call paint. But even if it compiles, paint never gets called in the applet window. What am I not seeing here?
public class LineDraw extends JComponent
{
private final Point p1;
private final Point p2;
private final JApplet callingWindow;
private final ArrayList<Line2D.Double> lines;
public LineDraw(JApplet callingWindow)
{
this.p1 = new Point();
this.p2 = new Point();
this.callingWindow = callingWindow;
this.lines = new ArrayList<Line2D.Double>();
MouseListener mouse = new MouseHandler();
callingWindow.addMouseListener(mouse);
}
public class MouseHandler extends MouseAdapter
{
private boolean firstClick;
public MouseHandler()
{
firstClick = true;
}
public void mouseClicked(MouseEvent e)
{
if(firstClick)
{
p1.setLocation(e.getPoint());
firstClick = false;
}
else
{
p2.setLocation(e.getPoint());
lines.add(new Line2D.Double(p1, p2));
p2.setLocation(p1.getLocation());
callingWindow.repaint();
}
}
public void paintComponent(Graphics2D g2)
{
for(Line2D.Double e: lines)
{
g2.draw(e);
}
}
}
}
And the applet class itself
public class AppletWin extends JApplet
{
private LineDraw lineDrawer;
public void init()
{
setBackground(Color.white);
lineDrawer = new LineDraw(this);
}
public void paint(Graphics h)
{
Graphics2D g = (Graphics2D)h;
//Clear background
g.setColor(getBackground());
g.fillRect(1, 1, getWidth(), getHeight());
lineDrawer.paintComponent(g);
}
}
回答1:
LineDrawer
is a component, you should add it to you applet and it will painted automatically.
You seem to have fallen into a naming clash problem.
JComponent
defines two methods for painting (actually it defines a few more, but lets keep it simple), paint
and paintComponent
.
The problem you are having is to do with the fact that you've inherited from a JComponent
but seem to be performing your own painting. This fine when you want to develop you own "painter" classes, but falls foul of Swing components. There is more to a Swing component then simply painting it.
The other problem you're have is you've defined a "paint" method in side MouseHandler
method and seem to be assuming that it is callable from LineDraw
class. The problem is, you're actually calliing the JComponent
's paint
method, not the one you want/think you are.
Try removing the extends JComponent
and moving the paint
method into the LineDraw
class.
As MouseEvent has stated, under most circumstances, you should never call paint
or paintComponent
directly.
You may find:
- Painting in AWT and Swing
- Performing Custom Painting
Helpful
UPDATED
Painting as a Swing Component
public class AppletWin extends JApplet {
private LineDraw lineDrawer;
public void init() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
setBackground(Color.white);
lineDrawer = new LineDraw(AppletWin.this);
setLayout(new BorderLayout());
add(lineDrawer);
}
});
}
public class LineDraw extends JComponent {
private final Point p1;
private final Point p2;
private final JApplet callingWindow;
private final ArrayList<Line2D.Double> lines;
public LineDraw(JApplet callingWindow) {
this.p1 = new Point();
this.p2 = new Point();
this.callingWindow = callingWindow;
this.lines = new ArrayList<Line2D.Double>();
MouseListener mouse = new MouseHandler();
addMouseListener(mouse);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
for (Line2D.Double e : lines) {
g2.draw(e);
}
}
public class MouseHandler extends MouseAdapter {
private boolean firstClick;
public MouseHandler() {
firstClick = true;
}
public void mouseClicked(MouseEvent e) {
if (firstClick) {
p1.setLocation(e.getPoint());
firstClick = false;
} else {
p2.setLocation(e.getPoint());
lines.add(new Line2D.Double(p1, p2));
p2.setLocation(p1.getLocation());
}
repaint();
}
}
}
}
As Painter
public class AppletWin extends JApplet {
private LineDraw lineDrawer;
public void init() {
setBackground(Color.white);
lineDrawer = new LineDraw(this);
}
public void paint(Graphics h) {
// The the applet clear the background
super.paint(h);
Graphics2D g = (Graphics2D) h;
lineDrawer.paintComponent(g);
}
public class LineDraw {
private final Point p1;
private final Point p2;
private final JApplet callingWindow;
private final ArrayList<Line2D.Double> lines;
public LineDraw(JApplet callingWindow) {
this.p1 = new Point();
this.p2 = new Point();
this.callingWindow = callingWindow;
this.lines = new ArrayList<Line2D.Double>();
MouseListener mouse = new MouseHandler();
callingWindow.addMouseListener(mouse);
}
public void paintComponent(Graphics2D g2) {
System.out.println("...");
for (Line2D.Double e : lines) {
g2.draw(e);
}
}
public class MouseHandler extends MouseAdapter {
private boolean firstClick;
public MouseHandler() {
firstClick = true;
}
public void mouseClicked(MouseEvent e) {
if (firstClick) {
p1.setLocation(e.getPoint());
firstClick = false;
} else {
p2.setLocation(e.getPoint());
lines.add(new Line2D.Double(p1, p2));
p2.setLocation(p1.getLocation());
}
callingWindow.repaint();
}
}
}
}
You really should avoid overriding the paint
method of top level containers. The paint
method is a very complex method and circumventing it is just going to cause you problems in the long run, besides, it's not double buffered ;)
回答2:
Problem with this code is that the paintComponent method in LineDraw is inside the inner class MouseHandler.
来源:https://stackoverflow.com/questions/13716900/trouble-with-japplets-and-calling-paint-paintcomponent