Java перерисовать метод не работает при вызове из другого класса - PullRequest
1 голос
/ 26 ноября 2010

Я кодирую Java с Netbeans уже около года и написал много кода для манипулирования данными, который отображает графики на экране.Обычно я помещаю объект 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 ]

1 голос
/ 26 ноября 2010

"Программы Swing должны переопределять paintComponent() вместо переопределения paint()." - Рисование в AWT и Swing: Методы рисования .

main опущено, поскольку содержит только код для настройки двух экранных панелей.

Убедитесь, что вы строите свой графический интерфейс на EDT, как показано в статье Начальные темы .

Приложение: Вот пример, показывающий оба принципа:

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, Визуальное руководство для менеджеров по макету может помочь при выборе макета.

1 голос
/ 26 ноября 2010

Main опущен, поскольку он содержит только код для настройки двух экранных панелей.)

Ну, по определению, когда у вас есть проблема, вы не знаете, какой код является или не является относительным, пока проблема не будет решена. Таким образом, полный SSCCE должен быть опубликован.

Как дикое предположение, я бы сказал, что ваш компонент имеет размер 0, поэтому рисовать нечего.

Обычно я помещаю объект JPanel в главное окно, пишу собственный код рисования и при необходимости вызываю метод repaint ()

Возможно, вам повезло, потому что вы добавили панель в центр BorderLayout, который автоматически дает панели все пространство, доступное для фрейма.

В примере trashgod показан один из способов установки предпочтительного размера пользовательского компонента. Другой способ - переопределить метод getPreferredSize () для возврата правильного значения.

Вы действительно должны научиться использовать менеджер макетов, а не использовать нулевые макеты, и вы избежите подобных проблем в будущем. Нет необходимости использовать нулевую разметку, если у вас нет приложения типа перетаскивания.

0 голосов
/ 26 ноября 2010

Я считаю, что когда вы рисуете JComponent, область клипа устанавливается на этот JComponent.Поэтому, если другие компоненты попытаются нарисовать (или если вы вызовете их перерисовку), они не будут из-за отсечения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...