创建具有操作功能的“面部”代码

时间:2013-11-07 05:48:32

标签: java user-interface

我有一个任务,我应该创建一个原型绘图程序来显示和操作面。它应该使用2个窗口,一个用于绘制面,另一个用于控制绘图。它应该最初显示一张脸的图像(用形状绘制)。

脸部由头部,两只眼睛,鼻子和嘴巴组成。通过在对象边框内单击鼠标来选择这些部件中的每一个。眼睛被选为一对,因此单击任一眼睛都会选择它们。选择一个面部部件时,将忘记所有先前的选择。

控制窗口仅对所选对象起作用。单击“更改图像”按钮可执行以下任务(取决于所选的面部部分):

  • 头部:头部从绿色变为黄色,紫色变为紫色,再变为绿色
  • 鼻子:鼻子图像改变了三个可能的鼻子图像中的另一个
  • 嘴巴:嘴角图像变为三个可能的嘴图像中的另一个
  • 眼睛:眼睛图像变为四个可能的眼睛图像中的另一个

包含带有行为的滚动条:

  • 选定的头部:使用滚动条值更改,头部变宽和变窄
  • 选定的鼻子:鼻子图像向上或向下移动并且滚动条值更改
  • 选择的嘴:滚动条值更改时,嘴变得更宽或更窄
  • 选择的眼睛:通过滚动条值更改,眼睛移动得更近或更远

我的问题是,我不知道从哪里开始。我已经看了很多关于swing和awt的教程,甚至尝试过使用NetBeans中的调色板管理器。任何人都可以指出我正确的方向或者可能引导我完成代码吗?

1 个答案:

答案 0 :(得分:1)

你的问题不适合这里。此外,尽管您的教师指称不准确,但仍然可以让一个人自己进行研究,从一个相当不错的特定要求到一个正常运行的程序。我并不是说它听起来很重要。

然而,出于对你接近你的导师这一事实的欣赏,也是出于同情,也许我可以给你一些起点和提示。

首先,Swing是正确的开始方式。阅读http://zetcode.com/tutorials/javaswingtutorial/中教程的相关章节,并按照一些项目进行操作。

您可以非常轻松地手动编写Swing界面,对于相对简单的应用程序,以及学习体验,这是一个合理的选择。但是,为了将来参考,许多IDE都有GUI编辑器(NetBeans附带我认为的功能,Eclipse有WindowBuilder插件) - 需要注意的是你必须添加学习如何将IDE用于任务列表(当然,这个最终将为您节省时间。)

无论如何,您的第一步应该是设计您的软件。确定您需要执行哪些操作,需要响应哪些用户操作以及使用哪些信息以及使用哪些信息。您提出以下要求:

  

控制窗口仅对所选对象起作用。点击一下   更改图像按钮执行以下任务(取决于   选定的面部分):

     
      
  • 头部:头部从绿色变为黄色,紫色变为紫色,然后变回   绿色
  •   
  • 鼻子:鼻子图像改变了另外三个可能的鼻子   图像
  •   
  • 嘴巴:嘴角图像变成另外三个可能的嘴巴   图像
  •   
  • 眼睛:眼睛图像变为四个可能的眼睛图像中的另一个
  •   
     

包含带有行为的滚动条:

     
      
  • 选定的头部:头部越宽越窄,滚动条值越大   改变
  •   
  • 选定的鼻子:鼻子图像使用滚动条向上或向下移动   价值变化
  •   
  • 选择的嘴:用卷轴使嘴变得更宽或更窄   条形值变化
  •   
  • 选择眼睛:眼睛靠得更近或更远   除了滚动条值更改
  •   

你在这里使用的基本组件是一个面,所以我们在这里做出一个设计决定,让一个面具有一个具有其他属性的对象(你可以采取不同的方法,并拥有不同的部分面对你的基本单位)。根据滚动条的描述,面具有以下可修改的属性:

  • 头宽。
  • 垂直鼻子位置。
  • 嘴宽。
  • 眼睛之间的距离。

当然,脸也有其他恒定的特征,几乎可以由你随意决定,例如眼睛的直径,皮肤的颜色等等。你将不得不工作那些进行。

除了修改上述属性外,您还需要根据自己的要求做一些事情:

  • 画脸(画)。
  • 在属性发生变化时重绘(重绘)面部。
  • 允许用户通过点击选择一个部分,该部分分为:
    • 响应鼠标点击。
    • 确定给定XY位置的光标下的组件。
    • 向应用程序提供有关选择的信息。

最后一部分"提供有关选择的信息"是一个实现细节,你有几个选项,你必须决定。例如,你可以创建一些类型的事件监听器接口并告诉面部,并让它在选择改变时调用该接口上的方法 - 这是一种非常好的方法。您还可以让face在内部维护当前选择的属性,在这种情况下,您需要使其能够获取/设置当前所选属性的值。您还可以在编辑器UI窗口中直接调用face方法。所有这些方式都有明显的优点和缺点,我将其作为练习留给读者进行实验。

现在,您还可以根据自己的要求,在单独的窗口中为用户提供滚动条以编辑属性。现在,考虑一下您需要哪些UI组件以及您希望它们如何结合在一起:

  • 脸窗
    • 包含单个面部组件(如果需要,可包含更多组件)。
  • 编辑窗口
    • 包含滚动条。
    • 如果您愿意,可能包含描述当前选择的标签。

Swing已经提供了大部分这些组件。窗口是JFrame。滚动条是JScrollBar。标签是JLabel。 Swing不提供面部,因此您需要自己编写自定义组件。

至于他们如何联系在一起:

  • 更改面部中的对象选择可以:
    • 如果您愿意,请将滚动条更新为当前值。
    • 将滚动条范围更新为适当的值。
    • 如果您愿意,请更新标签以描述当前选择。
  • 更改滚动条必须:
    • 更新脸上当前选定的属性。
    • 最终导致脸部被重新绘制。

现在的主要任务是实现一个绘制面部并响应鼠标点击的Swing组件。

由于您要创建新组件,因此您需要选择适当的基础,可能是JComponentJPanel。在Google的许多教程中都可以轻松找到如何创建新组件的方法(包括我上面链接的一些基础知识),这取决于您的研究。但基本上,重申上述内容,您的自定义面部组件具有以下自定义行为:

  • Draw a face.
  • Receive mouse events
  • 从鼠标X,Y坐标确定单击的组件。在最基本的层面上,这将需要一些数学。例如,如果您的头部,眼睛,嘴巴和鼻子是椭圆形,则由您来计算给定的X,Y坐标是否在其中一个椭圆的范围内。但是,您需要查看Shape,这将允许您轻松定义形状并提供边界检查方法。

我认为这足以让你开始并把它们放在一起。以下一般任务即将开始:

  • 阅读我链接的教程,很多基础知识应该变得清晰。尝试写一些简单的" hello world"风格应用。
  • 尝试编写一些自定义组件;你的要求是基本的,其中大部分都包含在"绘画"该教程的一部分。
  • 查看教程或一些有关如何使用Shape和实验的示例。

如果您对自己编写的代码有特定的疑问,并且您可能会尝试解决某个特定问题,那么您可以随时回来并将其发布到SO上。

我希望这会有所帮助。更重要的是,我希望这至少可以让您了解如何从需求到实现一般。

编辑:

我玩Shape后已经有一段时间了,所以我把这个小例子放在一起。单击/拖动两个形状以选择它们,这将使它们变为黄色:

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

@SuppressWarnings("serial")
public class ShapeSelect extends JPanel {

    private final Shape firstShape = new Rectangle2D.Float(60, 40, 70, 70);
    private final Shape secondShape = new Ellipse2D.Float(30, 30, 90, 50);
    private Shape selected = null;

    public ShapeSelect () {
        // set up the component
        setPreferredSize(new Dimension(200, 200));
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override public void mouseDragged (MouseEvent event) {
                selectShapeUnder(event.getX(), event.getY());
            }
        });
        addMouseListener(new MouseAdapter() {
            @Override public void mousePressed (MouseEvent event) {
                selectShapeUnder(event.getX(), event.getY());
            }
        });
    }

    // draw our shapes, selected shape is yellow.
    @Override protected void paintComponent (Graphics g) {
        Graphics2D graphics = (Graphics2D)g;
        graphics.setColor((selected == firstShape) ? Color.YELLOW : Color.RED);
        graphics.fill(firstShape);
        graphics.setColor((selected == secondShape) ? Color.YELLOW : Color.GREEN);
        graphics.fill(secondShape);
    }

    // updates 'selected' based on x,y coordinate and redraws component on change.
    public void selectShapeUnder (int x, int y) {
        Shape oldSelected = selected;
        // note that since second shape is draw on top of first, we give second preference.
        // for overlapping shapes the selection should be consistent with the gui display.
        if (secondShape.contains(x, y))
            selected = secondShape;
        else if (firstShape.contains(x, y))
            selected = firstShape;
        else
            selected = null;
        if (selected != oldSelected)
            repaint();
    }


    public static final void main (String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run () {
                JFrame frame = new JFrame("Shape Select");
                frame.getContentPane().add(new ShapeSelect(), BorderLayout.CENTER);
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }


}