Java Swing:使用填充创建自定义JComponents的网格

时间:2016-05-05 15:47:44

标签: java swing paint jcomponent

我试图创建一个海关网格JComponents。我希望网格可以调整大小而不会在我的JComponent上变形。

但我只能使用剪切的JComponent获取一个网格并且调整错误。

我得到了什么:

link

我想要的是什么:

link

这是我的代码:

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


public class Pawn extends JComponent {

   private static Color pileColor = Color.LIGHT_GRAY;
   private static Color faceColor = Color.DARK_GRAY;

   private static Color mouseOverColor = new Color(255, 255, 127);
   private static int padding = 10;

   private String label;

   private boolean pawnState;
   private int radius;

   private int row;
   private int column;

   public static void main(String[] args) {
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            createAndShowGUI();
         }
      });
   }

   private static void createAndShowGUI() {
      JFrame testPawnFrame = new JFrame("Test de la classe Pawn");
      JPanel testPawnPanel = new JPanel();
      testPawnPanel.setLayout(new GridLayout(3, 3,Pawn.padding*2,Pawn.padding*2));


      for (int i = 0; i < 9; i++) {
         testPawnPanel.add(new Pawn());
      }

      testPawnFrame.add(testPawnPanel);
      addQuit(testPawnFrame);

      testPawnFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      testPawnFrame.pack();
      testPawnFrame.setVisible(true);
   }

   public Pawn() {
      this.pawnState = true;
      this.radius = 50;
      this.row = -1;
      this.column = -1;
   }

   public Pawn(int row, int column) {
      this();
      this.row = row;
      this.column = column;
   }

   public void setPosition(int row, int column) {
      if (row >= 0 && column >= 0) {
         this.row = row;
         this.column = column;
      } else {
         throw new Error("La position donee est incorrecte.");
      }
   }

   public void paint(Graphics g) {
      super.paintComponent(g);

      Graphics2D g2 = (Graphics2D) g;

      Ellipse2D circle = new Ellipse2D.Double(padding, padding, radius * 2, radius * 2);

      if (pawnState) {
         g2.setColor(pileColor);
      } else {
         g2.setColor(faceColor);
      }

      g2.fill(circle);
      g2.setColor(Color.BLACK);
      g2.draw(circle);
      g2.drawRect(0, 0, 2 * (radius + padding), 2 * (radius + padding));

   }

   public Dimension getPreferredSize() {
      return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
   }

   public Dimension getMinimumSize() {
      return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
   }

   public void setBounds(int x, int y, int width, int height) {      
      radius = (int) Math.min(width, height) / 2;

      super.setBounds(x, y, width+(padding*2), height+(padding*2));

      repaint();
   }

   public static void addQuit(JFrame frame) {
      ActionListener actionQuit = new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent event) {
            System.exit(0);
         }
      };

      Box quitBox = new Box(BoxLayout.X_AXIS);
      frame.add(quitBox, BorderLayout.SOUTH);
      JButton quitButton = new JButton("Quit");
      quitButton.addActionListener(actionQuit);
      quitBox.add(Box.createHorizontalGlue());
      quitBox.add(quitButton);
   }

}

编辑: 我对代码做了一些改进,谢谢大家。 它并不完美而且没有真正优化,调整大小非常慢。 (如果你有优化的想法,请告诉我!)

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

public class Pawn extends JComponent {

  private static Color pileColor = Color.LIGHT_GRAY;
  private static Color faceColor = Color.DARK_GRAY;
  private static Color mouseOverColor = new Color(255, 255, 127);

  private String label;

  private boolean pawnState;

  private int radius;
  private double padding;

  private int row;
  private int column;

  public static void main(String[] args) {
     javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
           createAndShowGUI();
        }
     });
  }

  private static void createAndShowGUI() {
     JFrame testPawnFrame = new JFrame("Test de la classe Pawn");
     JPanel testPawnPanel = new JPanel();
     testPawnPanel.setLayout(new GridLayout(3, 3));

     for (int i = 0; i < 9; i++) {
        testPawnPanel.add(new Pawn());
     }

     testPawnFrame.add(testPawnPanel);
     addQuit(testPawnFrame);

     testPawnFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     testPawnFrame.pack();
     testPawnFrame.setVisible(true);
  }

  public Pawn() {
     this.pawnState = true;
     this.radius = 50;
     this.padding = 0.1;
     this.row = -1;
     this.column = -1;
  }

  public Pawn(int row, int column) {
     this();
     this.row = row;
     this.column = column;
  }

  public void setPosition(int row, int column) {
     if (row >= 0 && column >= 0) {
        this.row = row;
        this.column = column;
     } else {
        throw new Error("La position donee est incorrecte.");
     }
  }

  public void paint(Graphics g) {
     super.paint(g);
     Graphics2D g2 = (Graphics2D) g;

     Dimension size = getSize();

     radius = (int)(
             (Math.min(size.width, size.height) / 2)
             -(radius*padding));

     Ellipse2D circle = new Ellipse2D.Double(
             (size.width/2)-radius, 
             (size.height/2)-radius, 
             radius * 2, radius * 2);

     if (pawnState) {
        g2.setColor(pileColor);
     } else {
        g2.setColor(faceColor);
     }

     g2.fill(circle);
     g2.setColor(Color.BLACK);
     g2.draw(circle);
     g2.drawRect(0, 0, getWidth()-1, getHeight()-1);
  }

  public Dimension getPreferredSize() {
     int size = 2 * (radius);
     return new Dimension(size, size);
  }

  public static void addQuit(JFrame frame) {
     ActionListener actionQuit = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent event) {
           System.exit(0);
        }
     };

     Box quitBox = new Box(BoxLayout.X_AXIS);
     frame.add(quitBox, BorderLayout.SOUTH);
     JButton quitButton = new JButton("Quit");
     quitButton.addActionListener(actionQuit);
     quitBox.add(Box.createHorizontalGlue());
     quitBox.add(quitButton);
  }

}

我现在得到的东西:

link

1 个答案:

答案 0 :(得分:3)

//super.paint(g);
super.paintComponent(g);

如前所述,您需要在覆盖

的方法上调用super

不要覆盖setBounds()。布局管理器的工作是确定组件的大小/位置。这是您的代码的主要问题。

其他一些问题:

无需覆盖getMinimumSize()。如果你这样做,你只需使用:

return getPreferredSize();

如果您不必,请不要重复代码。

return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );

不要重复计算。创建一个变量。它更容易调试和更改。

//return new Dimension(2 * (radius + padding) , 2 * (radius + padding) );
int size = 2 * (radius + padding) + 1;
return new Dimension(size, size);

注意&#34; + 1&#34;。我添加了这个,因为drawRect(...)方法的工作方式。尝试没有&#34; + 1&#34;的代码你会看到缺少底线/右线。这是使用变量进行计算的一个完美示例。改变只需要在一个地方完成。

编辑:

还有一个变化:

//testPawnPanel.setLayout(new GridLayout(3, 3,Pawn.padding*2,Pawn.padding*2));
testPawnPanel.setLayout(new GridLayout(3, 3));

您不希望组件之间有任何空间,因此请让布局管理员完成其工作。