JPanel和JScrollPane以及错误渲染

Yau*_*nka 3 java swing awt jpanel jscrollpane

我的英语不好,但我会尽力解释.我有个问题.在JPanel我画线....他们应该超出对象的区域JPanel和JScrollPane理论上应该显示整个面板,但它没有更新,也没有显示为面板范围发布的所有行.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Console;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class TestFrame extends JFrame {

    static int speed = 10;
    static int floor = 22;
    public static void createGUI() {
        JFrame frame = new JFrame("Test frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final Font font = new Font("Verdana", Font.PLAIN, 25);

        JPanel butPanel = new JPanel();     

        JButton biginButton = new JButton("start");
        biginButton.setFont(font);
        biginButton.setFocusable(false);
        butPanel.add(biginButton);

        JButton remButton = new JButton("repaint");
        remButton.setFont(font);
        remButton.setFocusable(false);
        butPanel.add(remButton);

        final JPanel labPanel = new JPanel();
        final JScrollPane scrollPane = new JScrollPane(labPanel);
        labPanel.setLayout(new BoxLayout(labPanel, BoxLayout.Y_AXIS));

        biginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //labPanel.getGraphics().drawString("Ololo", 50, 50);
                int floH = 100;
                for(int i = 0; i < floor; i++){
                    labPanel.getGraphics().drawLine(0, i*floH, 300, i*floH);
                    labPanel.getGraphics().setColor(Color.RED);
                    scrollPane.revalidate();    
                }
            }
        });

        remButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                    labPanel.repaint();
                    scrollPane.revalidate();                                
            }           
        });

        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(butPanel, BorderLayout.NORTH);
        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setPreferredSize(new Dimension(screenSize.width-10, screenSize.height-10));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame.setDefaultLookAndFeelDecorated(true);
                createGUI();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

Hov*_*els 5

我猜你正在尝试绘制一个JPanel然后期望JPanel应该变得更大以适应你的绘图,这不仅不适合你,而且如果你调用repaint()你会失去绘图在JPanel上.

如果是的话,那么,

  • 仅仅因为你绘制超出JPanel或其他JComponent的大小将不会自动使该组件更大,因为组件本身没有"知识",你正在超出它的范围.如果要调整组件大小,则必须自己执行此操作.
  • 最好让JPanel通过覆盖其getPreferredSize()方法来设置自己的大小.这将阻止其他代码将其大小重置为其他内容.
  • 您不希望通过调用getGraphics()它来获取组件的图形.如此获得的Graphics对象持续时间很短,下次调用paint(...)或paintComponent()时,绘制的任何内容都会消失.可以在BufferedImage上调用getGraphics(),但不能在Component或JComponent上调用(除非你有充分理由这样做并且知道如何防止Graphics对象变为null).
  • 覆盖JPanel或其他一些JComponent并绘制paintComponent(...)此组件的override方法.如果您使用的是BufferedImage,则在此paintComponent方法中绘制BufferedImage.

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestDrawing extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = 600;
   private DrawingPanel drawingPanel = new DrawingPanel();

   public TestDrawing() {
      JPanel northPanel = new JPanel();
      northPanel.add(new JButton(new AbstractAction("Draw Lines") {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            drawingPanel.drawLines();
            drawingPanel.repaint();
         }
      }));

      setLayout(new BorderLayout());
      add(new JScrollPane(drawingPanel));
      add(northPanel, BorderLayout.PAGE_START);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      TestDrawing mainPanel = new TestDrawing();

      JFrame frame = new JFrame("TestDrawing");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class DrawingPanel extends JPanel {
   private static final int BI_W = 500;
   private static final int FLOOR = 22;
   private static final int FLO_H = 100;
   private BufferedImage img = new BufferedImage(BI_W, FLO_H * FLOOR, BufferedImage.TYPE_INT_ARGB);

   public DrawingPanel() {

   }

   public void drawLines() {

      Graphics g = img.getGraphics();
      g.setColor(Color.black);
      for (int i = 0; i < FLOOR; i++) {
         g.drawLine(0, i * FLO_H, 300, i * FLO_H);
         g.setColor(Color.RED);
      }
      g.dispose();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(BI_W, FLO_H * FLOOR);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (img != null) {
         g.drawImage(img, 0, 0, this);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)