代码之家  ›  专栏  ›  技术社区  ›  John R Doner

当从另一个类调用时,javaReFrice方法不起作用

  •  1
  • John R Doner  · 技术社区  · 15 年前

    我已经用NETBeCAS编码了大约一年的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
    

    如果有人对此有任何见解,或者知道一个解决办法,我会很高兴听到 来自你。

    提前感谢您提供任何见解。

    约翰·唐纳

    3 回复  |  直到 15 年前
        1
  •  0
  •   vy32    15 年前

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

        2
  •  1
  •   camickr    15 年前

    建议使用MAIN,因为它只包含设置两个屏幕面板的代码。)

    好吧,根据定义,当你有问题的时候,在问题解决之前,你不知道什么代码是相对的或者不是相对的。所以一个完整的 SSCCE 应该张贴。

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

    我通常在主窗口中放置一个jpanel对象,编写自定义绘制代码,并根据需要调用repaint()方法。

    你可能很幸运,因为你将面板添加到了边框布局的中心,它自动为面板提供框架可用的所有空间。

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

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

        3
  •  1
  •   trashgod    15 年前

    “回转程序应覆盖 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();
                }
            }));
        }
    }
    

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