2016-05-05 20 views
2

Ich versuche, ein Raster von Zoll JComponents zu erstellen. Ich möchte, dass das Raster skalierbar ist, ohne dass es sich auf meiner JComponent verformt.Java Swing: Erstellen Sie ein Raster mit benutzerdefinierten JComponents mit Auffüllung

Aber ich bin nur in der Lage, ein Raster mit abgeschnittenen JComponent und schlechter Größe zu bekommen.

Was erhalte ich:

link

Was ich will:

link

Hier ist mein Code:

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

} 

Edit: ich eine gewisse Verbesserung zu tun die Co de, danke euch allen. Es ist nicht perfekt und es ist nicht wirklich optimiert, die Größenänderung ist ziemlich langsam. (wenn Sie Idee für optimize bitte sagen Sie mir!)

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

}

das, was ich jetzt bekommen:

link


+0

"Swing-Programme sollten' paintComponent() 'überschreiben, anstatt' paint() 'zu überschreiben." - [* Painting in AWT and Swing: Die Malmethoden *] (http://www.oracle.com/technetwork/ Java/painting-140037.html # Rückrufe). Warum sollten Sie 'super.paintComponent()' in einer benutzerdefinierten Implementierung von 'paint()' aufrufen? – trashgod

+0

Platzieren Sie Ihr Bauer-Panel in ein anderes Panel, das mit einem GridBagLayout konfiguriert ist. Setzen Sie das GridBagConstraint.fill-Mitglied für Ihr Board auf NONE, und leeren Sie JPanels nach oben, rechts, unten und links. Füllen Sie BEIDES – ControlAltDel

+0

@trashgod i fogot, um das beim Testen zu entfernen. – Slynus

Antwort

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

Wie bereits Sie erwähnt müssen Sie super auf die Methode, die Sie sind, aufrufen Erroring

Überschreiben Sie nicht setBounds(). Die Aufgabe des Layout-Managers ist es, die Größe/Position einer Komponente zu bestimmen. Dies ist das Hauptproblem mit Ihrem Code.

Einige andere Probleme:

Es besteht keine Notwendigkeit getMinimumSize außer Kraft zu setzen(). Wenn ja, würde verwenden Sie einfach:

return getPreferredSize(); 

keinen Code kopieren, wenn Sie nicht haben.

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

Berechnungen nicht wiederholen. Erstellen Sie eine Variable. Es ist einfacher zu debuggen und zu ändern.

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

Beachten Sie die "+1". Ich habe das hinzugefügt, weil die Methode drawRect(...) funktioniert. Versuchen Sie den Code ohne die "+1" und Sie werden sehen, die unteren/rechten Linien fehlen. Dies ist ein perfektes Beispiel dafür, warum Sie Variablen verwenden, um Berechnungen zu speichern. Die Änderung muss nur an einem Ort vorgenommen werden.

Edit:

Eine weitere Änderung:

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

Sie wollen keinen Raum zwischen den Komponenten, so lassen Sie das Layout Krippe seine Arbeit zu tun.

+0

Danke, aber wenn ich setBounds() nicht überschreibe, wie kann ich meine JComponents anpassen? (Ich bekomme nur [Link] (http://i.imgur.com/BGKA1ZL.png)) – Slynus

+0

@Slynus, ich habe keine Ahnung, warum Sie das bekommen. Sie haben meine Vorschläge nicht korrekt umgesetzt. Sie haben Ihre Frage zu den von Ihnen vorgenommenen Änderungen nicht aktualisiert. Auch eine meiner Änderungen hinzugefügt. 'Wie kann ich meine JComponents Größe ändern?' - das ist die Aufgabe Ihres Malcodes. Der Layout-Manager bestimmt die Größe jeder Komponente. Dein Malcode bestimmt, wie dein Gemälde aussieht. Im Moment kodierst du das Bild fest. Wenn Sie die Malerei dynamisieren möchten, sollte die Bemalung auf der Größe der Komponente basieren. – camickr

+0

Ich habe gerade eine "Lösung" gefunden, die gut für mich ist, ich werde den Beitrag bald aktualisieren. Danke für die Hilfe :). – Slynus