Рисунок Java Swing исчезает при изменении размера окна

Мне очень нужна ваша помощь, потому что я не могу решить эту проблему самостоятельно. Я пытаюсь создать графический интерфейс и хочу нарисовать что-то в нем после нажатия кнопки, но у меня, кажется, есть какая-то проблема обновления / повторной проверки или многопоточности. Рисунок нарисован, но когда я изменяю размер окна, картина исчезает. Кроме того, при очень быстром перемещении окна части рисунка исчезают. Я перепробовал много вещей, но не могу заставить эту проблему работать, может быть, вы мне поможете. Мне поручили не писать свой собственный код для начала, а использовать функции дизайна NetBeans для генерации кнопок и панелей и т. Д. Возможно, это ухудшает процесс / функции рисования, но я не знаю. Я опубликую вам соответствующий код и буду очень благодарен за предложения (закомментированные вещи - просто артефакты из того, что я пробовал раньше, так что не обращайте на это внимания):

public class NewJFrame extends JFrame  {
  public NewJFrame() { initComponents(); }

  @SuppressWarnings("unchecked")
  private void initComponents() {
    jButton1 = new javax.swing.JButton();
    jPanel1 = new javax.swing.JPanel();
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setMinimumSize(new java.awt.Dimension(1200, 1000));
    jButton1.setText("Draw");
    jButton1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jButton1ActionPerformed(evt);
      }
    });
    GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGap(0, 1000, Short.MAX_VALUE)
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGap(0, 0, Short.MAX_VALUE)
    );
    GroupLayout layout = new GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, 1000, Short.MAX_VALUE)
            .addGap(18, 18, 18)
            .addComponent(jButton1)
            .addGap(33, 33, 33))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(0, 745, Short.MAX_VALUE)
                    .addComponent(jButton1)
                    .addGap(237, 237, 237))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())))
    );

    pack();
  }// </editor-fold>

  private void jButton1ActionPerformed(ActionEvent evt) {
    Graphics g = jPanel1.getGraphics();
    draw(jPanel1, g);
  }

  protected void paintComponent(Graphics g){
    jPanel1.setSize(1000, 1000);
    Dimension d = jPanel1.getSize();
    g.setColor(Color.BLACK);
    for (int i=0; i<=1000;i++){
      if (i%100==0){
        g.setColor(Color.RED);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
      else if(i%50==0 && i%100!=0){
        g.setColor(Color.BLUE);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
      else {
        g.setColor(Color.BLACK);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
    }
    g.setColor(Color.green);
    g.drawLine(0, d.height / 2, d.width, d.height / 2);
  }

  public void draw(JPanel Jpanel1, Graphics g) {
    System.out.println("wuffkowski");
    Jpanel1.setSize(1000,1000);
    Dimension d = Jpanel1.getSize();
    g.setColor(Color.BLACK);
    for (int i=0; i<=1000;i++){
      if (i%100==0){
        g.setColor(Color.RED);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
      else if(i%50==0 && i%100!=0){
        g.setColor(Color.BLUE);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
      else {
        g.setColor(Color.BLACK);
        g.drawLine(i, d.height/2, i, (d.height/2)+100);
      }
    }
    g.setColor(Color.green);
    g.drawLine(0, d.height / 2, d.width, d.height / 2);
    Jpanel1.paintComponents(g);
  }

  public static void lala () {
    try {
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(info.getName())) {
          javax.swing.UIManager.setLookAndFeel(info.getClassName());
          break;
        }
      }
    } catch (ClassNotFoundException ex) {
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
      java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        NewJFrame JF =new NewJFrame();
        JF.setVisible(true);
      }
    });
  }
  private javax.swing.JButton jButton1;
  private javax.swing.JPanel jPanel1;
}

Еще раз большое спасибо за ваше драгоценное время.

4 ответа

Решение

Java не помнит команды рисования для вас; Ваша графика отображается один раз, когда вы нажимаете кнопку, потому что это единственный раз, когда draw() называется.

Если вы хотите обновить рендеринг после изменения размера, переопределите paint(Graphics) и позвонить draw() там.

Если это связано с нажатием кнопки, вы должны добавить в свой класс поля, в которых вы помните все, что вам нужно в draw() в том числе и то, должно ли оно рисовать

private boolean drawAtAll = false;

private void jButton1ActionPerformed(ActionEvent evt) {
  drawAtAll = true; // ok to draw now
  draw();
}

@Override
public void paint(Graphics g) {
   super.paint(g);
   draw();
}

public void draw() {
  if( !drawAtAll ) return;

  Graphics g = jPanel1.getGraphics();
  ...
}

Дальнейшее чтение:

Попробуйте свои силы в этом коде и задайте любые вопросы, которые могут возникнуть, выполните рисование внутри метода paintComponent(...) JPanel. Вместо того, чтобы каждый раз указывать размер JComponent Вы можете просто переопределить getPreferredSize() указанного компонента. Для того, чтобы позвонить вашему paintComponent(...) ты можешь просто написать repaint() вместо того, чтобы явно сделать звонок paintComponent(...) из вашей программы Swing сделает это автоматически.

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

public class PaintingExample
{
    private CustomPanel paintingPanel;
    private Timer timer;
    private int x = 1;
    private int y = 1;
    private ActionListener timerAction = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {
            x++;
            y++;
            paintingPanel.setPosition(x, y);
        }
    };

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Painting Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        paintingPanel = new CustomPanel();
        final JButton startStopButton = new JButton("STOP");
        startStopButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                if (timer.isRunning())
                {
                    startStopButton.setText("START");
                    timer.stop();
                }
                else if (!timer.isRunning())
                {
                    startStopButton.setText("STOP");
                    timer.start();
                }
            }
        });

        frame.add(paintingPanel, BorderLayout.CENTER);
        frame.add(startStopButton, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        timer = new Timer(100, timerAction);
        timer.start();
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PaintingExample().createAndDisplayGUI();
            }
        });
    }
}

class CustomPanel extends JPanel
{
    private int x = 0;
    private int y = 0;

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(800, 600));
    }

    public void setPosition(int a, int b)
    {
        x = a;
        y = b;
        if (x <(getWidth() - 10) && y < (getHeight() - 10))
            repaint();
        else
            System.out.println("Nothing is happening...");
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.clearRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.MAGENTA);
        g.fillOval(x, y, 10, 10);
    }
}

Я не прошел весь ваш код, но сразу видно, что вы не должны переопределять paintComponent метод без вызова super.paintComponent, И ваши закомментированные звонки super.paintComponents (обратите внимание), что не то же самое.

Я также не уверен, что вы имеете в виду "когда я изменяю размер окна", и как это связано с вашим Jpanel1.setSize( 1000, 1000 ) звонки, которые появляются по всему вашему коду. Ваш менеджер по расположению позаботится о размере панели. Вы не должны устанавливать это к фиксированному размеру.

Когда вы изменяете размер панели или меняете ее положение или минимизируете и максимизируете ее, paint(...) вызывается метод, который перерисовывает содержимое. Вы должны перезаписать эту функцию и позволить ей нарисовать вашу линию или что-то еще. Чтобы сделать это, вы, вероятно, должны сохранить свой чертеж в структуре данных, чтобы иметь возможность перерисовывать его при необходимости.

Метод рисования описан здесь.

Другие вопросы по тегам