2016-05-04 23 views
1

Ich schreibe gerade eine Schach-App in Java, aber ich habe ein paar Probleme mit dem Erstellen von Rahmen für Kacheln und mit Bildglättung.Java JPanel setBorder und Antialiasing funktioniert nicht

EDIT: Problem mit Grenzen wurde gelöst. Siehe my answer unten;

Ergebnis:

enter image description here

Wie man dort sehen kann eine gezackte Kanten auf Schachfiguren und Fliesen-Grenze fehlt. Antialiasing funktioniert jedoch, wenn ich getScaledInstance (width, height, Image.SCALE_SMOOTH) hinzufüge, aber das verlangsamt meine App und Symbole sieht hässlich aus, wenn ich Fenstergröße ändere.

With getScaledInstance()

Mein Code:

Tabellenklasse:

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; 
    } 
} 

BoardPanel Klasse:

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 < Board.N; x++) { 
      for (int y = 0; y < Board.N; y++) { 
       TilePanel tilePanel = new TilePanel(new Point(x, y)); 
       boardTiles[x][y] = tilePanel; 
      } 
     } 
     for (int i = Board.N; i > 0; i--) { 
      for (int j = 0; j < Board.N; j++) { 
       add(boardTiles[j][i - 1]); 
      } 
     } 
     validate(); 
    } 

    void drawBoard() { 
     removeAll(); 
     for (int i = Board.N; i > 0; i--) { 
      for (int j = 0; j < Board.N; j++) { 
       boardTiles[j][i - 1].drawTile(); 
       add(boardTiles[j][i - 1]); 
      } 
     } 
     revalidate(); 
     repaint(); 
    } 

    void reverse() { 
     // revers coloums 
     for (int col = 0; col < Board.N; col++) { 
      for (int row = 0; row < 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 < Board.N; row++) { 
      for (int col = 0; col < 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 && 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(); 
     } 
    } 
} 

Gibt es etwas, das ich dieses Problem beheben? Vielen Dank im Voraus.

Antwort

0

Ich Fix Grenzen durch Löschen von g2d.dispose von PaintComponent() -Methode. Aber ich habe immer noch Probleme mit Antialiasing.

0

Symbole sieht hässlich aus, wenn ich Fenstergröße ändere.

  1. also nicht dynamisch auf die Symbole skalieren. Oder:
  2. nicht zulassen, dass die Karte neu skaliert wird.
  3. Vielleicht können Sie die Stretch Icon verwenden, mit der Sie das ursprüngliche Verhältnis beibehalten können, wenn dann das Symbol skaliert wird. Beachten Sie, dass diese Klasse keine Rendering-Hinweise definiert, sodass Sie diese möglicherweise hinzufügen müssen.