有没有更好的方法来设置JPanel图形的初始位置?)

在Liang的Java编程简介(第7版)的第15章中,他介绍了一个在JPanel上制作(2-D)球的程序,并在点击放大/缩小按钮时将其放大。 我修改了程序,以便1)放大/缩小球,如果用户点击/选项+点击,2)允许你通过按下按钮选择球的颜色,3)允许你移动用鼠标拖动它。

最后一次修改是给我带来麻烦的一段时间,因为我想在开始时将球放在中心,但是然后允许用户用鼠标移动球。 我想出的解决方案是让paintComponent方法仅在第一次绘制时相对于getWidth()和getHeight()设置球的x坐标和y坐标。 为此,我向BallCanvas类添加了一个paintCount变量,并创建了一个if语句,以便它只在第一次执行时执行。 当我最初试图弄清楚如何做到这一点时,我看到了其他解决方案,比如这里给出的解决方案: 为什么我不能访问我的面板的getWidth()和getHeight()函数? ,但我发现我的解决方案更简单。

所以问题是:我认为编码风格是不是很糟糕? 专业程序员会嘲笑这个解决方案吗? 还是可以吗?

更重要的是,有没有更好(但也相对简单)的方法来做这个不涉及设置计数器?

以下是相关的代码:

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

move方法(响应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++; } } } 

有几点需要注意:

  • 覆盖getPreferredSize()以建立面板的初始几何体。

  • 使用该几何体来确定球的初始位置。

  • 调用pack()然后设置位置和可见性。

  • 使用Action来封装菜单和控件共享的代码。

  • 始终使用适配器。

  • 正确使用初始线程 。

  • 请参阅此问答 ,从几个角度检查相关示例。

图片

 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() { @Override public void actionPerformed(ActionEvent e) { canvas.setColor(Color.RED); } }); jbtGreen.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { canvas.setColor(Color.GREEN); } }); jbtBlue.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { canvas.setColor(Color.BLUE); } }); jbtBlack.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { canvas.setColor(Color.BLACK); } }); miEnlarge.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { canvas.enlarge(); } }); miShrink.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { canvas.shrink(); } }); canvas.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { canvas.changeSize(e); } @Override public void mouseDragged(MouseEvent e) { canvas.move(e); } }); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new ControlBall(); frame.setTitle("ControlBall"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public static class BallCanvas extends JPanel { private static final int SIZE = 400; private int radius = 20; private Color color = Color.BLACK; private int ballX = SIZE / 2 - radius; private int ballY = SIZE / 2 - radius; 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(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(color); g.fillOval(ballX, ballY, 2 * radius, 2 * radius); } @Override public Dimension getPreferredSize() { return new Dimension(SIZE, SIZE); } } }