从另一个类调用时,Java重绘方法不起作用

时间:2010-11-26 02:31:22

标签: java swing methods repaint

我已经用Netbeans编写了大约一年的Java代码,并编写了大量的数据操作代码,用于在屏幕上绘制图形。我通常在主窗口中植入一个JPanel对象,编写自定义绘图代码,并根据需要调用repaint()方法。

但是今天,我第一次试图从一个类(对象)调用一个面板上的重绘,而不是包含该面板的类。虽然编译器发现没有任何问题,并且在调试模式下,它单步执行到外部调用重绘,实际上没有重绘,并且代码实际上没有进入重绘方法。

我写了一个简约程序来演示这个问题,如下所示(Main省略,因为它只包含设置两个屏幕面板的代码。)

---类的描述,首先包含绘图表面,其他重绘调用---

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Panel1 extends JComponent
{
   GraphPnl graphPnl;
   boolean colorFlag;

   public Panel1()
   {
     setLayout(null);
     colorFlag = true;

     graphPnl = new GraphPnl();
     graphPnl.setBounds(10, 10, 110, 110);
     graphPnl.setBackground(Color.black);
     add(graphPnl);

}//Panel1()

public class GraphPnl extends JPanel
{
  //just draws a line segment, toggling color

  @Override
  public void paint(Graphics g)
  {
      super.paint(g);
      Graphics2D g2 = (Graphics2D) g;
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);

      if (colorFlag) {g2.setColor(Color.red);} else {g2.setColor(Color.green);}
      g2.drawLine(10, 10, 50, 50);
   }//paint
 }//GraphPnl
}//Panel1

import javax.swing.*;
import java.awt.event.*;

public class Panel2 extends JComponent
{
   JButton testBtn;
   TestAction testAction;
   Panel1 p1;

   public Panel2()
   {
      p1 = new Panel1();
      testBtn = new JButton("Click");
      testBtn.setBounds(10, 10, 80, 30);
      add(testBtn);
      testAction = new TestAction();
      testBtn.addActionListener(testAction);
   }//Panel2()


   public class TestAction implements ActionListener
   {
     public void actionPerformed(ActionEvent evt)
     {
       p1.colorFlag = ! p1.colorFlag;
       p1.graphPnl.repaint();
     }
   }//TestAction
}//Panel2

如果有人对此有任何见解,或者知道某种解决方法,我会很高兴听到 来自你

提前感谢任何见解。

John Doner

3 个答案:

答案 0 :(得分:1)

“Swing程序应该覆盖paintComponent(),而不是覆盖paint()。” - Painting in AWT and Swing: The Paint Methods

  省略了

main,因为它只包含设置两个屏幕面板的代码。

验证您是否在EDT上构建GUI,如文章Initial Threads所示。

附录:这是一个显示两个原则的例子:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/questions/4282159 */
public class GraphPanel extends JPanel {

    private boolean colorFlag;

    public GraphPanel() {
        this.setPreferredSize(new Dimension(640, 480));
    }

    public void toggle() {
        colorFlag = !colorFlag;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        if (colorFlag) {
            g2.setColor(Color.red);
        } else {
            g2.setColor(Color.blue);
        }
        g2.drawLine(0, 0, getWidth(), getHeight());
    }

    private void display() {
        JFrame f = new JFrame("GraphPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this, BorderLayout.CENTER);
        f.add(new ControlPanel(this), BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GraphPanel().display();
            }
        });
    }
}

class ControlPanel extends JPanel {

    public ControlPanel(final GraphPanel gp) {
        this.add(new JButton(new AbstractAction("Click") {

            @Override
            public void actionPerformed(ActionEvent e) {
                gp.toggle();
                gp.repaint();
            }
        }));
    }
}

附录:如@ camickr的评论中所述,A Visual Guide to Layout Managers可能有助于指导您的布局选择。

答案 1 :(得分:1)

  

Main is ommitted,因为它只包含设置两个屏幕面板的代码。)

嗯,根据定义,当您遇到问题时,在问题解决之前您不知道代码是什么或不相关。因此,应发布完整的SSCCE

作为一个疯狂的猜测,我会说你的组件的大小为0,所以没有什么可画的。

  

我通常在主窗口中植入一个JPanel对象,编写自定义绘图代码,并根据需要调用repaint()方法

您可能很幸运,因为您将面板添加到BorderLayout的中心,该面板自动为面板提供框架可用的所有空间。

trashgod的示例显示了一种设置自定义组件的首选大小的方法。另一种方法是覆盖getPreferredSize()方法以返回正确的值。

你真的应该学习如何使用布局管理器而不是使用空布局,你将来会避免这样的问题。除非您有拖放类型的应用程序,否则无需使用空布局。

答案 2 :(得分:0)

我相信在绘制JComponent时,剪辑区域设置为该JComponent。因此,如果其他组件尝试绘制(或者如果你调用它们重绘),它们就不会,因为剪切。