В главе 15 из программирования Ляна (7-е изд.) он представляет программу для создания (2-D) шара на JPanel и увеличьте его, нажав кнопки увеличения/уменьшения. Я изменил программу так, чтобы она также 1) увеличивала/уменьшала мяч, если пользователь нажимает/выбирает + клики, 2) позволяет выбрать цвет мяча, нажав кнопку, и 3) позволяет перемещать кругом, перетащив его мышью.Есть ли лучший способ установить начальную позицию для JPanel?)
Последняя модификация - это то, что вызывало у меня проблемы какое-то время, потому что я хотел центрировать мяч в начале, но затем разрешить пользователю перемещать мяч с помощью мыши. Решение, с которым я столкнулся, заключалось в том, чтобы метод paintComponent устанавливал только x- и y-координаты шара относительно getWidth() и getHeight() при его первом рисовании. Для этого я добавил переменную paintCount в класс BallCanvas и сделал оператор if, чтобы он выполнял только первый раз. Когда я пытался выяснить, как это сделать вначале, я увидел другие решения, такие как приведенные здесь: Why can't I access my panel's getWidth() and getHeight() functions?, но я считаю, что решение намного проще.
Итак, вопрос в том, что я считал плохой стиль кодирования? Будет ли профессиональный программист издеваться над этим решением? Или все в порядке?
Что еще более важно, есть ли лучший (но также и относительно простой) способ сделать это, не связанный с настройкой счетчика?
Вот соответствующие биты кода:
начала BallCanvas:
public static class BallCanvas extends JPanel {
private int radius = 20;
private Color color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;
...
Метод шаг (который реагирует на событие MouseDragged):
public void move(MouseEvent e){
ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();
}
paintComponent метод:
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
if(paintCount < 1){
ballX = getWidth()/2 - radius;
ballY = getHeight()/2 - radius;
}
g.fillOval(ballX, ballY, 2*radius, 2*radius);
paintCount++;
}
Полная программа:
// Reference: Liang's Intro to Java Programming
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ControlBall extends JFrame{
private JButton jbtRed = new JButton("Red");
private JButton jbtGreen = new JButton("Green");
private JButton jbtBlue = new JButton("Blue");
private JButton jbtBlack = new JButton("Black");
private BallCanvas canvas = new BallCanvas();
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu("Edit");
private JMenuItem miEnlarge = new JMenuItem("Enlarge");
private JMenuItem miShrink = new JMenuItem("Shrink");
public ControlBall(){
menuBar.add(menu);
menu.add(miEnlarge);
menu.add(miShrink);
JPanel panel = new JPanel();
panel.add(jbtRed);
panel.add(jbtGreen);
panel.add(jbtBlue);
panel.add(jbtBlack);
this.add(canvas, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
this.add(menuBar, BorderLayout.NORTH);
jbtRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.RED);
}
});
jbtGreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.GREEN);
}
});
jbtBlue.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLUE);
}
});
jbtBlack.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLACK);
}
});
miEnlarge.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.enlarge();
}
});
miShrink.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
canvas.shrink();
}
});
canvas.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e){
canvas.changeSize(e);
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
});
canvas.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
canvas.move(e);
}
});
}
public static void main(String[] args){
JFrame frame = new ControlBall();
frame.setTitle("ControlBall");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.setVisible(true);
}
public static class BallCanvas extends JPanel {
private int radius = 20;
private Color color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;
public BallCanvas(){
System.out.println(getWidth() + " " + getHeight());
}
public BallCanvas(int initialRadius){
radius = initialRadius;
}
public void setColor(Color color){
this.color = color;
repaint();
}
public void changeSize(MouseEvent e){
int numClicks = e.getClickCount();
if(e.isAltDown()){
if(radius >= 6){
this.radius -= 5*numClicks;
} else{
// do nothing
}
} else{
this.radius += 5*numClicks;
}
repaint();
}
public void enlarge(){
this.radius += 5;
repaint();
}
public void shrink(){
if(radius >= 10){
this.radius -= 5;
}
repaint();
}
public void move(MouseEvent e){
ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(color);
if(paintCount < 1){
ballX = getWidth()/2 - radius;
ballY = getHeight()/2 - radius;
}
g.fillOval(ballX, ballY, 2*radius, 2*radius);
paintCount++;
}
}
}
Я не считаю это плохой стиль программирования. Но опять же, я не профессионал. Этот вопрос, скорее всего, будет основан на мнениях, а не на фактах, поэтому я голосую, чтобы закрыть. – Jeffrey
Возможно, если я сфокусирую внимание на «есть ли лучший способ, которым вы это сделаете?» Будет ли это более подходящим вопросом? –
+1 для [sscce] (http://sscce.org/) – trashgod