我有一个任务,我应该创建一个原型绘图程序来显示和操作面。它应该使用2个窗口,一个用于绘制面,另一个用于控制绘图。它应该最初显示一张脸的图像(用形状绘制)。
脸部由头部,两只眼睛,鼻子和嘴巴组成。通过在对象边框内单击鼠标来选择这些部件中的每一个。眼睛被选为一对,因此单击任一眼睛都会选择它们。选择一个面部部件时,将忘记所有先前的选择。
控制窗口仅对所选对象起作用。单击“更改图像”按钮可执行以下任务(取决于所选的面部部分):
包含带有行为的滚动条:
我的问题是,我不知道从哪里开始。我已经看了很多关于swing和awt的教程,甚至尝试过使用NetBeans中的调色板管理器。任何人都可以指出我正确的方向或者可能引导我完成代码吗?
答案 0 :(得分:1)
你的问题不适合这里。此外,尽管您的教师指称不准确,但仍然可以让一个人自己进行研究,从一个相当不错的特定要求到一个正常运行的程序。我并不是说它听起来很重要。
然而,出于对你接近你的导师这一事实的欣赏,也是出于同情,也许我可以给你一些起点和提示。
首先,Swing是正确的开始方式。阅读http://zetcode.com/tutorials/javaswingtutorial/中教程的相关章节,并按照一些项目进行操作。
您可以非常轻松地手动编写Swing界面,对于相对简单的应用程序,以及学习体验,这是一个合理的选择。但是,为了将来参考,许多IDE都有GUI编辑器(NetBeans附带我认为的功能,Eclipse有WindowBuilder插件) - 需要注意的是你必须添加学习如何将IDE用于任务列表(当然,这个最终将为您节省时间。)
无论如何,您的第一步应该是设计您的软件。确定您需要执行哪些操作,需要响应哪些用户操作以及使用哪些信息以及使用哪些信息。您提出以下要求:
控制窗口仅对所选对象起作用。点击一下 更改图像按钮执行以下任务(取决于 选定的面部分):
- 头部:头部从绿色变为黄色,紫色变为紫色,然后变回 绿色
- 鼻子:鼻子图像改变了另外三个可能的鼻子 图像
- 嘴巴:嘴角图像变成另外三个可能的嘴巴 图像
- 眼睛:眼睛图像变为四个可能的眼睛图像中的另一个
包含带有行为的滚动条:
- 选定的头部:头部越宽越窄,滚动条值越大 改变
- 选定的鼻子:鼻子图像使用滚动条向上或向下移动 价值变化
- 选择的嘴:用卷轴使嘴变得更宽或更窄 条形值变化
- 选择眼睛:眼睛靠得更近或更远 除了滚动条值更改
你在这里使用的基本组件是一个面,所以我们在这里做出一个设计决定,让一个面具有一个具有其他属性的对象(你可以采取不同的方法,并拥有不同的部分面对你的基本单位)。根据滚动条的描述,面具有以下可修改的属性:
当然,脸也有其他恒定的特征,几乎可以由你随意决定,例如眼睛的直径,皮肤的颜色等等。你将不得不工作那些进行。
除了修改上述属性外,您还需要根据自己的要求做一些事情:
最后一部分"提供有关选择的信息"是一个实现细节,你有几个选项,你必须决定。例如,你可以创建一些类型的事件监听器接口并告诉面部,并让它在选择改变时调用该接口上的方法 - 这是一种非常好的方法。您还可以让face在内部维护当前选择的属性,在这种情况下,您需要使其能够获取/设置当前所选属性的值。您还可以在编辑器UI窗口中直接调用face方法。所有这些方式都有明显的优点和缺点,我将其作为练习留给读者进行实验。
现在,您还可以根据自己的要求,在单独的窗口中为用户提供滚动条以编辑属性。现在,考虑一下您需要哪些UI组件以及您希望它们如何结合在一起:
Swing已经提供了大部分这些组件。窗口是JFrame
。滚动条是JScrollBar
。标签是JLabel
。 Swing不提供面部,因此您需要自己编写自定义组件。
至于他们如何联系在一起:
现在的主要任务是实现一个绘制面部并响应鼠标点击的Swing组件。
由于您要创建新组件,因此您需要选择适当的基础,可能是JComponent
或JPanel
。在Google的许多教程中都可以轻松找到如何创建新组件的方法(包括我上面链接的一些基础知识),这取决于您的研究。但基本上,重申上述内容,您的自定义面部组件具有以下自定义行为:
我认为这足以让你开始并把它们放在一起。以下一般任务即将开始:
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);
}
});
}
}