2015-02-17 3 views
2

Я пытаюсь нарисовать круг в центре окна, и я не могу понять, что это правильно, должно быть очень просто! Я понимаю, что если вы установите JPanel в качестве области содержимого JFrame, макет по умолчанию - flowLayout, и этот чертеж должен начинаться с верхнего левого угла экрана как 0,0. Для того, чтобы попытаться выяснить, что происходит, я нарисовал синий фон, заполняющий JPanel, но это, кажется, есть запас, как так:Как получить JPanel для заполнения родительского JFrame

enter image description here

Когда окно становится меньше синий прямоугольник, рисунок начинает подрезанными с противоположной стороны:

enter image description here

Что происходит! Вот мой код:

import javax.swing.*; 
import java.awt.*; 

public class Test extends JFrame { 

    public static void main(String args[]) 
    { 
     Test test = new Test(); 
     test.Start(); 
    } 

    public void Start() 
    { 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setSize(500, 500); 
     CirclePanel circlePanel = new CirclePanel(); 
     this.setContentPane(circlePanel); 
     this.setVisible(true); 
    } 

    public class CirclePanel extends JPanel 
    { 
     private int radius = 200; 

     public void paintComponent(Graphics g) { 
      g.setColor(Color.blue); 
      g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
      g.setColor(Color.red); 
      int diameter = radius * 2; 
      g.fillOval(getX(), getY(), diameter, diameter); 
     } 

     public int getX() 
     { 
      return (this.getWidth()/2) - radius; 
     } 

     public int getY() 
     { 
      return (this.getHeight()/2) - radius; 
     } 
    } 
} 
+0

Кроме того, я не знаю, если это важно или нет , но вы можете использовать 'Math.min (getWidth(), getHeight())', чтобы найти диаметр, который позволит овалу встраиваться в компонент при рисовании t ... – MadProgrammer

+0

@MadProgrammer благодарит, может быть полезно в будущем! – mbdavis

ответ

3

Проблема заключается в том, что вы перекрывая getX() и getY(). Переименуйте их на что-то еще, и ваш код будет работать должным образом. Кроме того, рекомендуется включить предупреждения компилятора для отсутствующих аннотаций @Override и прислушаться к этим предупреждениям. (Это означало бы, что методы переопределяют методы суперкласса).

+1

Великие умы думают одинаково! 1+ –

+0

Это тот, который провел прошлый час, пытаясь разобраться! Спасибо за подсказку с аннотациями @Override, чтобы спасти мне будущие головные боли. – mbdavis

5

Один большой вопрос, вы неосознанно перекрывая две критические методы, используемые менеджерами компоновки для позиционирования компонентов, в getX() и getY() методов, и, таким образом, вы баловаться с размещением в JPanel в.

Прежде всего переименуйте эти методы, чтобы случайно не переместить JPanel.

Кроме того, не забудьте вызвать метод paintComponent супер и избежать вызова setSize(). Вместо этого переопределите getPreferredSize на вашем JPanel и упакуйте JFrame.

например,

public int getMyX() { 
    return myX; 
} 

public int getMyY() { 
    return myY; 
} 

Например

import javax.swing.*; 
import java.awt.*; 

public class Test extends JFrame { 

    public static void main(String args[]) { 
     //!! 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      Test test = new Test(); 
      test.Start(); 
     } 
     }); 
    } 

    public void Start() { 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     // this.setSize(500, 500); 
     CirclePanel circlePanel = new CirclePanel(); 
     setContentPane(circlePanel); 
     pack(); 
     setVisible(true); 
    } 

    public class CirclePanel extends JPanel { 
     private static final int PREF_W = 500; 
     private static final int PREF_H = PREF_W; 
     private int radius = 200; 

     public void paintComponent(Graphics g) { 
     super.paintComponent(g); //!! 
     g.setColor(Color.blue); 
     g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
     g.setColor(Color.red); 
     int diameter = radius * 2; 
     g.fillOval(getMyX(), getMyY(), diameter, diameter); 
     } 

     //!! 
     public int getMyX() { 
     return (this.getWidth()/2) - radius; 
     } 

     //!! 
     public int getMyY() { 
     return (this.getHeight()/2) - radius; 
     } 

     //!! 
     @Override 
     public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
     } 
    } 
} 
+0

спасибо за совет, могу ли я спросить, в чем цель использования SwingUtilities.invokeLater? – mbdavis

+0

@mbdavis: 'SwingUtilities.invokeLater' - заставить ваш код работать в потоке событий Swing. Swing не является потокобезопасным (большинство графических библиотек нет), поэтому вы должны быть осторожны, чтобы большинство вызовов Swing выполнялись в этом потоке. –

+0

ах, ладно, спасибо! – mbdavis

0

Попробуйте использовать this.add (circlePanel) вместо того, чтобы, если this.setContentPane (circlePanel) и установить размер JPanel, чтобы быть того же размера, как JFrame

Смежные вопросы