Gui 图形未出现在面板中
Gui graphic does not appear in Panel
我正在尝试使用我设置为 North
和 East
的两个按钮进行 drawOval
移动,这样球将在 JButton 之间移动,位于中心.
为什么没有出现在面板上?
我也在考虑使用一个函数来实现 x=x+
;和 y=y+1
当我向左或向右按时。
我不知道我能做什么。
所以这是我编写的代码:
public class Main extends JFrame implements ActionListener {
JButton left;
JButton right;
JPanel p;
Main(){
JButton left = new JButton("left");
left.addActionListener(this);
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
//The first way I think is better to make it move.
}
});
JButton right = new JButton("right");
right.addActionListener(this);
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West",left);// to the left
p.add("East",right);//to the right
Container c = getContentPane();
c.add(p);
}
public static void main(String[] args) {
Main f=new Main();
f.setTitle("Heracles");
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true); //this is the window
}
public void paintComponent (Graphics g) {
super.paintComponents(g);
Graphics2D g1=(Graphics2D) g;
g.drawOval(3, 5, 45, 46); // The ball
g.fillOval(20, 30, 40, 40);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Why does not appear at the panel?
要显示您创建的图形,请按照以下步骤使用,
删除 paintComponent
方法并将其替换为以下代码..
public JComponent createOvel() {
return new JComponent() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g1 = (Graphics2D) g;
g.drawOval(3, 5, 45, 46); // The ball
g.fillOval(20, 30, 40, 40);
}
};
}
然后在Main()
构造函数中调用,
p.add("Center", createOvel());
这将显示您创建的图形。
要了解它为什么不起作用,您需要了解绘画系统的实际工作原理
只要看一下这个片段,就应该很明显出了点问题。
public class Main extends JFrame implements ActionListener {
//...
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
您已经声明了一个名为 paintComponent
的方法,但正在调用超级方法 paintComponents
(注意末尾的 s
)。
此外,当你 "think" 覆盖一个方法时,你应该使用 #Override
属性,这会在你做错事情时导致编译器错误
public class Main extends JFrame implements ActionListener {
//...
@Overrride
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
上面的代码现在将无法编译,因为 JFrame
没有声明 paintComponent
方法。
作为一般规则,您应该避免直接从 JFrame
(或其他顶级容器)扩展,它们是复合组件并且具有复杂的层次结构和功能。
更好的起点可能是 JPanel
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
public TestPane() {
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
paintPane = new PaintPane();
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
g1.drawOval(3, 5, 45, 46); // The ball
g1.fillOval(20, 30, 40, 40);
}
}
}
您应该花时间查看 Painting in Swing and Performing Custom Painting 了解更多详情。
您可能愿意花时间学习的其他一些概念:
- Single Responsibility Principle - 一个class应该做一件事并且把它做好
- Observer Pattern - 这通常在 Swing 中表示为侦听器 API
- Model-View-Controller - 这涵盖了上述内容,并为程序的不同部分定义了不同的责任层,它也将帮助您理解 Swing 的基本结构
Also I am thinking using a function that make this x=x+
; and y=y+1
when I pressed left or right.
好的,这就是 MVC 的 "model" 部分发挥作用的地方。
所以让我们从定义我们希望模型支持的基本属性开始...
public interface ShapeModel {
public Point getPoint();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
这里支持一个Point
作为位置和一个ChangeListener
作为观察者模式,它会通知感兴趣的人模型的状态发生了变化。
为什么要以 interface
开头?作为一般概念,您应该始终更喜欢为接口而不是实现编写代码。在这种情况下,尚未定义 interface
的一个方面是,Point
如何更新?对于大多数想要使用该模型的人来说,这没什么兴趣,他们只想知道它何时发生变化,模型的变化可以直接通过实现或 "mutable" interface
来表达从 this interface
延伸
接下来,我们定义一个默认实现...
public class DefaultShapeModel implements ShapeModel {
private Point point = new Point(40, 40);
private List<ChangeListener> listeners = new ArrayList<>(25);
@Override
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
fireStateChanged();
}
protected void fireStateChanged() {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
@Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
}
这确实定义了绘画的更新方式。
最后,我们更新 TestPane
和 PaintPane
以支持模型...
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
private DefaultShapeModel model;
public TestPane() {
model = new DefaultShapeModel();
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
Point p = model.getPoint();
p.x--;
if (p.x > 0) {
p.x = 0;
}
model.setPoint(p);
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Point p = model.getPoint();
p.x++;
if (p.x + 40 > paintPane.getWidth()) {
p.x = paintPane.getWidth() - 40;
}
model.setPoint(p);
}
});
paintPane = new PaintPane(model);
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
private ShapeModel model;
public PaintPane(ShapeModel model) {
this.model = model;
this.model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
});
}
public ShapeModel getModel() {
return model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
Point p = getModel().getPoint();
g1.fillOval(p.x, p.y, 40, 40);
g1.setColor(Color.WHITE);
g1.drawOval(p.x, p.y, 40, 40);
}
}
我正在尝试使用我设置为 North
和 East
的两个按钮进行 drawOval
移动,这样球将在 JButton 之间移动,位于中心.
为什么没有出现在面板上?
我也在考虑使用一个函数来实现 x=x+
;和 y=y+1
当我向左或向右按时。
我不知道我能做什么。
所以这是我编写的代码:
public class Main extends JFrame implements ActionListener {
JButton left;
JButton right;
JPanel p;
Main(){
JButton left = new JButton("left");
left.addActionListener(this);
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
//The first way I think is better to make it move.
}
});
JButton right = new JButton("right");
right.addActionListener(this);
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("West",left);// to the left
p.add("East",right);//to the right
Container c = getContentPane();
c.add(p);
}
public static void main(String[] args) {
Main f=new Main();
f.setTitle("Heracles");
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true); //this is the window
}
public void paintComponent (Graphics g) {
super.paintComponents(g);
Graphics2D g1=(Graphics2D) g;
g.drawOval(3, 5, 45, 46); // The ball
g.fillOval(20, 30, 40, 40);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Why does not appear at the panel?
要显示您创建的图形,请按照以下步骤使用,
删除 paintComponent
方法并将其替换为以下代码..
public JComponent createOvel() {
return new JComponent() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g1 = (Graphics2D) g;
g.drawOval(3, 5, 45, 46); // The ball
g.fillOval(20, 30, 40, 40);
}
};
}
然后在Main()
构造函数中调用,
p.add("Center", createOvel());
这将显示您创建的图形。
要了解它为什么不起作用,您需要了解绘画系统的实际工作原理
只要看一下这个片段,就应该很明显出了点问题。
public class Main extends JFrame implements ActionListener {
//...
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
您已经声明了一个名为 paintComponent
的方法,但正在调用超级方法 paintComponents
(注意末尾的 s
)。
此外,当你 "think" 覆盖一个方法时,你应该使用 #Override
属性,这会在你做错事情时导致编译器错误
public class Main extends JFrame implements ActionListener {
//...
@Overrride
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
上面的代码现在将无法编译,因为 JFrame
没有声明 paintComponent
方法。
作为一般规则,您应该避免直接从 JFrame
(或其他顶级容器)扩展,它们是复合组件并且具有复杂的层次结构和功能。
更好的起点可能是 JPanel
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
public TestPane() {
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
paintPane = new PaintPane();
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
g1.drawOval(3, 5, 45, 46); // The ball
g1.fillOval(20, 30, 40, 40);
}
}
}
您应该花时间查看 Painting in Swing and Performing Custom Painting 了解更多详情。
您可能愿意花时间学习的其他一些概念:
- Single Responsibility Principle - 一个class应该做一件事并且把它做好
- Observer Pattern - 这通常在 Swing 中表示为侦听器 API
- Model-View-Controller - 这涵盖了上述内容,并为程序的不同部分定义了不同的责任层,它也将帮助您理解 Swing 的基本结构
Also I am thinking using a function that make this
x=x+
; andy=y+1
when I pressed left or right.
好的,这就是 MVC 的 "model" 部分发挥作用的地方。
所以让我们从定义我们希望模型支持的基本属性开始...
public interface ShapeModel {
public Point getPoint();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
这里支持一个Point
作为位置和一个ChangeListener
作为观察者模式,它会通知感兴趣的人模型的状态发生了变化。
为什么要以 interface
开头?作为一般概念,您应该始终更喜欢为接口而不是实现编写代码。在这种情况下,尚未定义 interface
的一个方面是,Point
如何更新?对于大多数想要使用该模型的人来说,这没什么兴趣,他们只想知道它何时发生变化,模型的变化可以直接通过实现或 "mutable" interface
来表达从 this interface
接下来,我们定义一个默认实现...
public class DefaultShapeModel implements ShapeModel {
private Point point = new Point(40, 40);
private List<ChangeListener> listeners = new ArrayList<>(25);
@Override
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
fireStateChanged();
}
protected void fireStateChanged() {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
@Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
}
这确实定义了绘画的更新方式。
最后,我们更新 TestPane
和 PaintPane
以支持模型...
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
private DefaultShapeModel model;
public TestPane() {
model = new DefaultShapeModel();
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
Point p = model.getPoint();
p.x--;
if (p.x > 0) {
p.x = 0;
}
model.setPoint(p);
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Point p = model.getPoint();
p.x++;
if (p.x + 40 > paintPane.getWidth()) {
p.x = paintPane.getWidth() - 40;
}
model.setPoint(p);
}
});
paintPane = new PaintPane(model);
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
private ShapeModel model;
public PaintPane(ShapeModel model) {
this.model = model;
this.model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
});
}
public ShapeModel getModel() {
return model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
Point p = getModel().getPoint();
g1.fillOval(p.x, p.y, 40, 40);
g1.setColor(Color.WHITE);
g1.drawOval(p.x, p.y, 40, 40);
}
}