我想創建一個Java面板,該面板創建用戶點擊的對象。由於我的實際應用程序使用MVC方法,我還希望這些對象能夠在模型更改時重新繪製自己,並提供用於更改其屬性的菜單。如何將MouseListener添加到Java Swing Canvas上的項目
我認爲控制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
,但遺憾的是它沒有工作。我知道使用佈局管理器更好,但似乎無法找到適合我需求的佈局管理器!
在此先感謝。
問題是,這不會轉化鼠標事件,這是'JLayer'將提供什麼,因此推薦它的原因。還有其他問題。父容器實際上不必是繪畫過程的一部分,可以繪製子組件,而無需調用父容器的繪畫,跳過縮放設置... – MadProgrammer
啊,你是對的,雖然我一直在玩與'TestWrapped'演示通過改變它來放大整個頁面。它似乎也沒有正確地翻譯鼠標事件。例如,當在頁面上繪圖時,它不是我的光標所在的位置。 –
我用一個可運行的示例更新了我的問題 – MadProgrammer