我是否正确地使用了Java Swing和图形?

8
我正在学习Java,并且需要使用Java Swing库和Graphics2D类完成一些任务。基本上,我需要绘制一个由多个部分组成的建筑起重机:一个主体(起重机的身体)和若干个附加臂(基本上看起来像这样:http://i.imgur.com/4YIkYqW.jpg)。
我的问题围绕着我是否正确使用了Java Swing类?在下面的代码中,我省略了不必要的代码,因为我只想确保我的结构是正确的(正确地使用JPanel、paintComponent()等)。任何帮助都将不胜感激,因为我正在学习Java!谢谢各位。
public class CraneSimulator {

    ...
    public JFrame frame;
    public MyPanel panel;

    public CraneSimulator() {
        frame = new JFrame("CraneSimulator");

        ...

        panel = new MyPanel();
        frame.add(panel);

    }

    public static void main(String[] args) {
        CraneSimulator simulator = new CraneSimulator();    
    }
}   

class MyPanel extends JPanel {
    CraneBody body;
    CraneArm arm1;
        ...
    Graphics2D graphics;

    public MyPanel() {
        body = new CraneBody();
        arm1 = new CraneArm(body);
        ...
        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                ...         }
            }
            public void mouseReleased(MouseEvent e) {
                    ...
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                ...             
            }
        });
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        graphics = (Graphics2D) g;
        ...
        body.paint(g);      
        arm1.paint(g);  
    }
}

class CraneBody {
    ...

    public CraneBody() {
         ....
    }
    ...
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

            // Use g2 to actual paint crane Body on screen here (ie. g2.drawRect, etc)      
    }
}

class CraneArm {
    ...

    public CraneArm() {
         ....
    }
    ...
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

            // Use g2 to actual paint the crane armon screen here (ie. g2.drawRect, etc)        
    }
}

3
是的!我的天啊是的!(抱歉,很多人做错了:P)。然而,我建议您构建您的起重机,使每个起重机臂都是前一个的子级。这意味着您可以(理论上)通过将Graphics上下文传递给链中的每个子元素来复合旋转平移。基本上它看起来会像crane.getArm().getArm().getArm() ...一直到你用完手臂-但这只是我的想法。 +1 的确正确使用 Swing Graphics :D - MadProgrammer
8
不要将Graphics类字段声明为全局变量,因为这样会在无意中使用时引发问题。此变量应仅作为局部变量。 - Hovercraft Full Of Eels
2
@HovercraftFullOfEels 很好的发现,我没有看到那个。 - MadProgrammer
嗯,那么是否可以为每个手臂设置一个变量(rotationDegrees),并在我的MouseDragged中调用hit test来调用setRotationDegrees()函数,该函数设置所需的度数(基于鼠标拖动的移动),然后在绘制手臂时,根据此变量应用旋转(使用AffineTransformation)? - Tesla
2
这个问题是否更适合在http://codereview.stackexchange.com/上提问?我倾向于这样认为,因为没有任何错误或错误提示,而是OP询问代码的正确性... - David Kroukamp
显示剩余5条评论
2个回答

3

您的代码结构良好,使用Java Graphics和OOP的优秀实践。

正如评论中建议的那样,如果您没有理由将其定义为实例变量,则最好将Graphics对象局部定义。


1
请注意,引用“graphics”的字段实际上应该被删除。保留该引用实际上是一种非常糟糕的做法。 - Guillaume Polet

1

你的代码几乎完美。但是有一些建议:

  1. 在声明时初始化具有优势
  2. 只需要一个MouseAdapter;
  3. 使用Graphics2D作为参数,这样你就不需要再次将其从Graphics转换。
  4. 删除"graphics"字段,而是将其作为局部变量。(感谢@GuillaumePolet)。

有些人可能会持不同意见,但根据你的代码,我会做出这些更改以使其更整洁。

public class CraneSimulator {
    ...
    private JFrame frame = new JFrame("CraneSimulator");
    private MyPanel panel = new JPanel();

    public CraneSimulator() {
        ...
        frame.add(panel);
    }
    public static void main(String[] args) {
        CraneSimulator simulator = new CraneSimulator();    
    }
}   

class MyPanel extends JPanel {
    CraneBody body = new CraneBody();
    CraneArm arm1 = new CraneArm(body);
    ...
    MouseAdapter mAdapter = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            ...
        }
        public void mouseReleased(MouseEvent e) {
            ...
        }
        public void mouseDragged(MouseEvent e) {
            ...             
        }
    }

    public MyPanel() {
        ...
        addMouseListener(mAdapter);
        addMouseMotionListener(mAdapter);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D graphics = (Graphics2D) g;
        ...
        body.paint(graphics);
        arm1.paint(graphics);  
    }
}

class CraneBody {
    ...
    public CraneBody() {
         ....
    }
    ...
    public void paint(Graphics2D g) {
        // You don't need to cast a Graphics again.      
    }
}

class CraneArm {
    ...
    public CraneArm() {
         ....
    }
    ...
    public void paint(Graphics2D g) {
        // You don't need to cast a Graphics again.
    }
}

2
请注意,引用“graphics”的字段实际上应该被删除。保留该引用实际上是一种非常糟糕的做法。 - Guillaume Polet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接