【发布时间】:2013-08-04 05:06:00
【问题描述】:
在梁的Java 编程简介(第 7 版) 的第 15 章中,他介绍了一个在 JPanel 上制作(2-D)球并在单击放大/缩小按钮时将其放大的程序.我已经修改了程序,以便它还 1) 如果用户单击/选项+单击,则放大/缩小球,2) 允许您通过按下按钮来选择球的颜色,以及 3) 允许您移动用鼠标拖动圆圈。
最后的修改给我带来了一段时间的麻烦,因为我想在开始时将球居中,但随后允许用户用鼠标移动球。我想出的解决方案是让 paintComponent 方法在第一次绘制时只设置球相对于 getWidth() 和 getHeight() 的 x 和 y 坐标。为此,我在 BallCanvas 类中添加了一个 paintCount 变量并创建了一个 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;
...
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++;
}
}
}
【问题讨论】:
-
我不会认为这是糟糕的编程风格。但话说回来,我不是专业人士。这个问题很可能会引出基于意见而不是基于事实的答案,所以我投票结束。
-
也许如果我将焦点更改为“您有更好的方法吗?”这会是一个更合适的问题吗?
-
+1 sscce
-
@ChrisMiddleton 也许,但它可能属于“太宽泛”的类别:可能的答案太多,或者对于这种格式来说,好的答案太长了。请添加详细信息以缩小答案范围或隔离可以在几段中回答的问题。
-
@Jeffrey:提出了一个令人信服的案例;我认为您可以专注于问题的首选尺寸方面。
标签: java swing event-handling jpanel mouseevent