【发布时间】:2014-02-06 03:21:33
【问题描述】:
我想制作一个 Java 面板,用于创建用户单击的对象。由于我的实际应用程序使用 MVC 方法,我还希望这些对象能够在模型更改时重新绘制自己,并提供菜单来更改它们的属性。
我认为控制它们的 x 和 y 位置的最佳方法是采用基于画布的方法,其中 JPanel 从 paintComponent 方法调用这些对象的绘制方法。然而,这只会在画布上绘制形状,并且不会添加对象本身,从而失去控制对象属性的所有能力。如果有人能告诉我我想做的最好的方法,我将不胜感激。
我创建了一些示例代码,如下所示。单击时,我希望圆圈更改颜色,这是使用 MouseListener 实现的(它基本上代表在这个小示例中更改模型属性)。另外我想确保放大/缩小仍然适用于任何示例代码/建议可以提供,所以我添加了按钮来放大和缩小对象作为快速测试。
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.geom.Ellipse2D;
public class Main {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ExamplePanel panel = new ExamplePanel();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
//I could not get this to with when it extended JLayeredPane
private static class ExamplePanel extends JPanel {
private static final int maxX = 500;
private static final int maxY = 500;
private static double zoom = 1;
private static final Circle circle = new Circle(100, 100);
public ExamplePanel() {
this.setPreferredSize(new Dimension(maxX, maxY));
this.setFocusable(true);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom += 0.1;
repaint();
}
});
add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom -= 0.1;
repaint();
}
});
add(zoomOut);
// add(circle); // Comment back in if using JLayeredPane
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
super.paintComponent(g);
circle.paint(g); // Comment out if using JLayeredPane
}
}
static class Circle extends JPanel {
private Color color = Color.RED;
private final int x;
private final int y;
private static final int DIMENSION = 100;
public Circle(int x, int y) {
// setBounds(x, y, DIMENSION, DIMENSION);
this.x = x;
this.y = y;
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
color = Color.BLUE;
}
@Override
public void mouseReleased(MouseEvent e) {
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(color);
g2.fillOval(x, y, DIMENSION, DIMENSION);
}
// I had some trouble getting this to work with JLayeredPane even when setting the bounds
// In the constructor
// @Override
// public void paintComponent(Graphics g) {
// Graphics2D g2 = (Graphics2D) g;
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2.setPaint(color);
// g2.fillOval(x, y, DIMENSION, DIMENSION);
// }
@Override
public Dimension getPreferredSize(){
return new Dimension(DIMENSION, DIMENSION);
}
}
}
顺便说一句,我确实尝试使用JLayeredPane(很有用,因为我还想对我的对象进行分层)但无法让我的对象甚至渲染。我知道它没有默认布局管理器,所以尝试在构造函数的圆圈中调用setBounds,但遗憾的是它不起作用。我知道最好使用布局管理器,但似乎找不到适合我需要的!
提前致谢。
【问题讨论】:
标签: java swing canvas position