title: Java JPanel setBorder and antialiasing not working
body: <p>I am currently writing a chess app in Java, but i have some problems with creating border for tiles and with image smoothing.</p>
  
  <p><strong>EDIT:</strong>
  Problem with borders was solved. See <a href="https://stackoverflow.com/a/37032059/6291224">my answer</a> below;</p>
  
  <p><strong>Result:</strong></p>
  
  <p><a href="https://i.stack.imgur.com/XdKZl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XdKZl.png" alt="enter image description here"></a></p>
  
  <p>As you can see there is a jaggy edges on chess pieces and tile border is missing.
  However, antialiasing is working if i add getScaledInstance(width, height, Image.SCALE_SMOOTH), but this slows down my app and icons looks ugly when i resize window.</p>
  
  <p><a href="https://i.stack.imgur.com/aPRMV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aPRMV.png" alt="With getScaledInstance()"></a></p>
  
  <p><strong>My code:</strong></p>
  
  <p>Table class:</p>
  
  <pre><code>import javax.swing.JFrame;
  import javax.swing.JMenu;
  import javax.swing.JMenuBar;
  import javax.swing.JMenuItem;
  import javax.swing.WindowConstants;
  import java.awt.BorderLayout;
  import java.awt.Dimension;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  
  public class Table {
      private final BoardPanel boardPanel;
      private final Board chessBoard;
  
      private final static Dimension OUTER_FRAME_DIMENSION = new Dimension(650, 650);
      private final static Dimension MIN_FRAME_DIMENSION = new Dimension(550, 550);
  
      public Table(Board chessBoard) {
          this.chessBoard = chessBoard;
          boardPanel = new BoardPanel(chessBoard);
  
          JFrame gameFrame = new JFrame("Chess");
          gameFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          gameFrame.setLayout(new BorderLayout());
          gameFrame.setSize(OUTER_FRAME_DIMENSION);
          gameFrame.setMinimumSize(MIN_FRAME_DIMENSION);
  
  
          gameFrame.setJMenuBar(createMenuBar());
          gameFrame.add(boardPanel, BorderLayout.CENTER);
          gameFrame.pack();
          gameFrame.setVisible(true);
      }
  
      private JMenuBar createMenuBar() {
          final JMenuBar menuBar = new JMenuBar();
          menuBar.add(createFileMenu());
          menuBar.add(createPreferencesMenu());
          return menuBar;
      }
  
      private JMenu createFileMenu() {
          final JMenu fileMenu = new JMenu("File");
          final JMenuItem exitMenuItem = new JMenuItem("Exit");
          exitMenuItem.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  System.exit(0);
              }
          });
          fileMenu.add(exitMenuItem);
          return fileMenu;
      }
  
      private JMenu createPreferencesMenu() {
          final JMenu preferencesMenu = new JMenu("Preferences");
          final JMenuItem flipBoardMenuItem = new JMenuItem("Flip Board");
          flipBoardMenuItem.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  boardPanel.reverse();
                  boardPanel.drawBoard();
              }
          });
          preferencesMenu.add(flipBoardMenuItem);
          return preferencesMenu;
      }
  }
  </code></pre>
  
  <p>BoardPanel class:</p>
  
  <pre><code>import javax.swing.BorderFactory;
  import javax.swing.JPanel;
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.GridBagLayout;
  import java.awt.GridLayout;
  import java.awt.Image;
  import java.awt.Point;
  import java.awt.RenderingHints;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  import java.awt.geom.AffineTransform;
  
  import static javax.swing.SwingUtilities.invokeLater;
  import static javax.swing.SwingUtilities.isLeftMouseButton;
  import static javax.swing.SwingUtilities.isRightMouseButton;
  
  class BoardPanel extends JPanel {
      private final Board chessBoard;
      private final TilePanel[][] boardTiles;
  
      private Point start; // first click
      private Point target;  // second click
  
      private static final Dimension BOARD_PANEL_DIMENSION = new Dimension(650, 650);
      private static final Dimension TILE_PANEL_DIMENSION = new Dimension(100, 100);
  
      BoardPanel(Board chessBoard) {
          super(new GridLayout(Board.N, Board.N));
          this.chessBoard = chessBoard;
          this.boardTiles = new TilePanel[Board.N][Board.N];
  
          ImageManager.readPieceImages();
          setPreferredSize(BOARD_PANEL_DIMENSION);
          fillBoard();
          validate();
      }
  
      private void fillBoard() {
          for (int x = 0; x &lt; Board.N; x++) {
              for (int y = 0; y &lt; Board.N; y++) {
                  TilePanel tilePanel = new TilePanel(new Point(x, y));
                  boardTiles[x][y] = tilePanel;
              }
          }
          for (int i = Board.N; i &gt; 0; i--) {
              for (int j = 0; j &lt; Board.N; j++) {
                  add(boardTiles[j][i - 1]);
              }
          }
          validate();
      }
  
      void drawBoard() {
          removeAll();
          for (int i = Board.N; i &gt; 0; i--) {
              for (int j = 0; j &lt; Board.N; j++) {
                  boardTiles[j][i - 1].drawTile();
                  add(boardTiles[j][i - 1]);
              }
          }
          revalidate();
          repaint();
      }
  
      void reverse() {
          // revers coloums
          for (int col = 0; col &lt; Board.N; col++) {
              for (int row = 0; row &lt; Board.N / 2; row++) {
                  TilePanel temp = boardTiles[row][col];
                  boardTiles[row][col] = boardTiles[Board.N - row - 1][col];
                  boardTiles[Board.N - row - 1][col] = temp;
              }
          }
  
          // reverse rows
          for (int row = 0; row &lt; Board.N; row++) {
              for (int col = 0; col &lt; Board.N / 2; col++) {
                  TilePanel temp = boardTiles[row][col];
                  boardTiles[row][col] = boardTiles[row][Board.N - col - 1];
                  boardTiles[row][Board.N - col - 1] = temp;
              }
          }
      }
  
      private class TilePanel extends JPanel {
          private final Tile tile;
          private Image pieceImage;
  
  
          TilePanel(final Point p) {
              super(new GridBagLayout());
              this.tile = chessBoard.getTile(p);
  
              setPreferredSize(TILE_PANEL_DIMENSION);
              setColor();
              setPieceIcon();
              highlightBorder();
  
              addMouseListener(new MouseListener() {
                  @Override
                  public void mouseClicked(MouseEvent e) {
                      if (isRightMouseButton(e)) {
                          start = null;
                          target = null;
                      } else if (isLeftMouseButton(e)) {
                          if (start == null) { // first click
                              start = tile.isOccupied() ? tile.getPosition() : null;
                              System.out.println(tile);
                          } else { // second click
                              target = tile.getPosition();
                              Move move = new Move(chessBoard, start, target);
                              if (move.isValid()) {
                                  System.out.println(move);
                                  chessBoard.movePiece(start, target);
                                  System.out.println(chessBoard);
                                  repaint();
                              }
                              start = null;
                              target = null;
                          }
                      }
                      invokeLater(new Runnable() {
                          @Override
                          public void run() {
                              drawBoard();
                          }
                      });
                  }
  
                  @Override
                  public void mousePressed(MouseEvent e) {
  
                  }
  
                  @Override
                  public void mouseReleased(MouseEvent e) {
  
                  }
  
                  @Override
                  public void mouseEntered(MouseEvent e) {
  
                  }
  
                  @Override
                  public void mouseExited(MouseEvent e) {
  
                  }
              });
              validate();
          }
  
          private void highlightLegalMoves() {
              if (start != null &amp;&amp; chessBoard.getTile(start).isOccupied()) {
                  Piece piece = chessBoard.getTile(start).getPiece();
                  for (Move move : piece.generateMoves(chessBoard, start)) {
                      if (tile == move.getStartTile()) {
                          setBorder(BorderFactory.createLineBorder(new Color(255, 255, 102)));
                      } else if (tile == move.getTargetTile()) {
                          setBackground(new Color(255, 255, 102));
                      }
                  }
              }
          }
  
          private void highlightBorder() {
              setBorder(BorderFactory.createLineBorder(Color.GRAY));
          }
  
          private void setPieceIcon() {
              removeAll();
              if (tile.isOccupied()) {
                  Piece piece = tile.getPiece();
                  pieceImage = ImageManager.getPieceImage(piece.toString());
              } else {
                  pieceImage = null;
              }
          }
  
          private void drawTile() {
              setColor();
              setPieceIcon();
              highlightLegalMoves();
              highlightBorder();
              revalidate();
              repaint();
          }
  
          final AffineTransform getTransform() {
              AffineTransform at = new AffineTransform();
              at.scale(getWidth() / 900.0,
                      getHeight() / 900.0);
              return at;
          }
  
          private void setColor() {
              Color light = new Color(247, 236, 202);
              Color dark = new Color(102, 68, 46);
              boolean black
                      = (tile.getPosition().x % 2 == 0) == (tile.getPosition().y % 2 == 0);
              setBackground(black ? dark : light);
          }
  
          @Override
          protected void paintComponent(Graphics g) {
              super.paintComponent(g);
              Graphics2D g2d = (Graphics2D) g;
              g2d.transform(getTransform());
              AffineTransform at = new AffineTransform();
  
              g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
                      RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
              g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                      RenderingHints.VALUE_INTERPOLATION_BILINEAR);
              g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                      RenderingHints.VALUE_ANTIALIAS_ON);
              g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
                      RenderingHints.VALUE_COLOR_RENDER_QUALITY);
              g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                      RenderingHints.VALUE_RENDER_QUALITY);
  
  
              at.setToTranslation(10, 0);
              g2d.drawImage(pieceImage, at, null);
              g2d.dispose();
          }
      }
  }
  </code></pre>
  
  <p>Is there anything I can fix this issue? Many thanks in advance.</p>