这是我当前的RectangleComponent类,我将它添加到我的主JFrame中的面板,但它永远不会出现。我认为它不是绘图所以我决定在Rectangle的构造函数中调用paintComponent方法,并在通过4-5 nullPointerExceptions进行排序后,没有任何更改。我已经阅读了有关如何绘制矩形的多个指南,并且我已经看到了多个代码示例,但我永远无法让面板与多个JComponent一起使用。如果可以,请简要查看我的代码,看看您是否可以设计解决方案。 感谢您的时间。还列出了我在中调用矩形构造函数的框架。
public class GameFrame extends JFrame
{
private SpellBarComponent bar;
private JPanel mainPanel = new JPanel();
private JPanel buttonPanel = new JPanel();
private JPanel healthPanel = new JPanel();
Color green = new Color(29, 180, 29);
Color red = new Color(255, 0, 0);
private RectangleComponent life;
private RectangleComponent death;
private JFrame frame = new JFrame();
public GameFrame(char x)
{
frame.setSize(1024, 768);
frame.setTitle("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
FlowLayout layout = new FlowLayout();
createPanels(x);
healthPanel.setLayout(layout);
buttonPanel.setLayout(layout);
mainPanel.setLayout(layout);
frame.getContentPane().add(mainPanel);
frame.pack();
repaint();
}
public RectangleComponent getLife()
{
return life;
}
private void createHealth()
{
life = new RectangleComponent(green, healthPanel);
death = new RectangleComponent(red, healthPanel);
}
private void createPanels(char x)
{
add(healthPanel);
pack();
createBar(x);
createHealth();
mainPanel.add(buttonPanel);
mainPanel.add(healthPanel);
healthPanel.add(death);
healthPanel.add(life);
buttonPanel.add(bar.getSpell1());
buttonPanel.add(bar.getSpell2());
buttonPanel.add(bar.getSpell3());
add(mainPanel);
}
private void createBar(char x)
{
bar = new SpellBarComponent(x, mainPanel);
}
}
public class RectangleComponent extends JComponent
{
Color color;
int width;
int height = 18;
RoundRectangle2D roundedRectangle;
private JPanel panel;
public RectangleComponent(Color color, JPanel panel)
{
this.panel = panel;
this.color = color;
paintComponent(panel.getGraphics());
}
public void paintComponent(Graphics g)
{
Graphics2D graphics2 = (Graphics2D) g;
width = 125;
roundedRectangle = new RoundRectangle2D.Float(10, 10, width, height, 10, 10);
graphics2.setPaint(color);
graphics2.fill(roundedRectangle);
graphics2.draw(roundedRectangle);
}
public void subtractLife(int amount)
{
width -= amount;
roundedRectangle.setRoundRect(10, 10, width, height, 10, 10);
repaint();
}
}
答案 0 :(得分:3)
无需将JPanel
传递给RectangleComponent
的构造函数,只需获取Graphics
,无需手动调用paintComponent
。见Painting in AWT and Swing。查看此example,演示绘制矩形的自定义组件。
答案 1 :(得分:3)
你的代码有点创意,有点疯狂,并且逻辑非常难以理解。最不寻常的方面是它有两个JFrame,一个叫做“frame”,一个是GameFrame对象本身,两个都添加了组件,但只有一个显示。您还有许多返回void的方法(如果过度使用会增加代码味道),只会增加使代码更加混乱。
例如,
public GameFrame(char x) {
// here you set up the "frame" JFrame
frame.setSize(1024, 768);
frame.setTitle("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
FlowLayout layout = new FlowLayout();
createPanels(x);
healthPanel.setLayout(layout);
buttonPanel.setLayout(layout);
mainPanel.setLayout(layout);
// here you add content to the frame JFrame, and pack it
frame.getContentPane().add(mainPanel);
frame.pack();
repaint(); // and then call repaint on the "this" JFrame?
}
public RectangleComponent getLife() {
return life;
}
private void createHealth() {
life = new RectangleComponent(green, healthPanel);
death = new RectangleComponent(red, healthPanel);
}
private void createPanels(char x) {
add(healthPanel); // now you add content to the "this" JFrame
pack(); // and pack it
createBar(x);
createHealth();
mainPanel.add(buttonPanel);
mainPanel.add(healthPanel); // and then re-add a JPanel into a second JPanel?
healthPanel.add(death);
healthPanel.add(life);
buttonPanel.add(bar.getSpell1());
buttonPanel.add(bar.getSpell2());
buttonPanel.add(bar.getSpell3());
add(mainPanel); // and then re -add the mainPanel into the "this" JFrame???
}
这一切都非常令人困惑,并且不太可能起作用。
然后你试图直接调用paintComponent并在JComponent上调用getGraphics,这两个都不应该完成。您将需要浏览图形教程以了解如何正确执行此操作。
我建议你考虑重写这个,首先,只使用一个JFrame,并更好地组织你的代码。
答案 2 :(得分:3)
为了使您的Swing应用程序按预期工作,您需要记住许多事项。为了逃避可能出现的某些障碍,必须遵循一定的步骤,因为您以错误的方式编码。为了坚持Swing Programming的基础知识,并遵循它们。
就像@HovercraftFullOfEels所提到的那样,你打电话给你 图形直接,哪一个不应该做。
其次,查看您设置的GameFrame()
构造函数
即使在您添加任何组件之前,也可以看到它们
在它的实际尺寸确定之前
编码中的这些循环漏洞可能会引起很多麻烦,因为你坐下来编写大型程序,所以最好从一开始就走在安全的道路上,然后在后期诅咒自己。正如他们所说预防胜于治疗。
现在进入你的程序,你错过了主要的东西,因为你没有指定CustomComponent
的大小,即JComponent
,因此你无法在屏幕上看到它。当您将JCompoent
扩展到您的班级时,请将其设为惯用的习惯,以覆盖getPreferredSize(),与覆盖paintComponent(...)
方法的方式相同。
看看这个小程序,我为你精心设计,可能会帮助你,更多地理解逻辑。
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
public class CustomPainting {
private RectangleComponent life;
private RectangleComponent death;
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Custom Painting");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(0, 2, 5, 5));
// Specifying the WIDTH, HEIGHT and Colour for this JComponent.
life = new RectangleComponent(Color.GREEN.darker(), 20, 20);
death = new RectangleComponent(Color.RED.darker(), 20, 20);
centerPanel.add(life);
centerPanel.add(death);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
JButton incLifeButton = new JButton("INCREASE LIFE");
incLifeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
life.addLife(1);
}
});
JButton decLifeButton = new JButton("DECREASE LIFE");
decLifeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
life.subtractLife(1);
}
});
JButton incDeathButton = new JButton("INCREASE DEATH");
incDeathButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
death.addLife(1);
}
});
JButton decDeathButton = new JButton("DECREASE DEATH");
decDeathButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
death.subtractLife(1);
}
});
buttonPanel.add(incLifeButton);
buttonPanel.add(decLifeButton);
buttonPanel.add(incDeathButton);
buttonPanel.add(decDeathButton);
frame.getContentPane().add(centerPanel, BorderLayout.CENTER);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String\u005B\u005D args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CustomPainting().createAndDisplayGUI();
}
});
}
}
class RectangleComponent extends JComponent {
private Color colour;
private static final int MARGIN = 10;
private int width;
private int height;
private int originalWidth;
private RoundRectangle2D roundedRectangle;
public RectangleComponent(Color c, int w, int h) {
colour = c;
width = w;
height = h;
originalWidth = width;
}
/*
* Overriding this method, so that
* the size of the JComponent
* can be determined, on the screen
* or by the LayoutManager concern.
*/
@Override
public Dimension getPreferredSize() {
return (new Dimension(width, height));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
roundedRectangle = new RoundRectangle2D.Float(MARGIN, MARGIN,
width, height, MARGIN, MARGIN);
g2d.setPaint(colour);
g2d.draw(roundedRectangle);
g2d.fill(roundedRectangle);
}
public void subtractLife(int amount) {
width -= amount;
System.out.println("ORIGINAL Width : " + originalWidth);
System.out.println("Width : " + width);
if (width > 0) {
roundedRectangle.setRoundRect(MARGIN, MARGIN, width, height,
MARGIN, MARGIN);
/*
* This repaint() will call the paintComponent(...)
* by itself, so nothing else to be done.
*/
repaint();
} else {
width += amount;
}
}
public void addLife(int amount) {
width += amount;
System.out.println("ORIGINAL Width : " + originalWidth);
System.out.println("Width : " + width);
if (width < originalWidth) {
roundedRectangle.setRoundRect(MARGIN, MARGIN, width, height,
MARGIN, MARGIN);
repaint();
} else {
width -= amount;
}
}
}
请问任何问题,当你通过这个程序时可能会出现这样的问题:-),我很乐意帮忙: - )
**两种颜色的最新编辑:**
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
public class CustomPainting {
private RectangleComponent lifeDeath;
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Custom Painting");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(0, 2, 5, 5));
// Specifying the WIDTH, HEIGHT and Colour for this JComponent.
lifeDeath = new RectangleComponent(Color.GREEN, Color.RED, 20, 20);
centerPanel.add(lifeDeath);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2, 5, 5));
JButton incLifeButton = new JButton("INCREASE LIFE");
incLifeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
lifeDeath.addLife(1);
}
});
JButton decLifeButton = new JButton("DECREASE LIFE");
decLifeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
lifeDeath.subtractLife(1);
}
});
buttonPanel.add(incLifeButton);
buttonPanel.add(decLifeButton);
frame.getContentPane().add(centerPanel, BorderLayout.CENTER);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String\u005B\u005D args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CustomPainting().createAndDisplayGUI();
}
});
}
}
class RectangleComponent extends JComponent {
private Color lifeColour;
private Color deathColour;
private static final int MARGIN = 10;
private int widthLife;
private int widthDeath;
private int height;
private int originalWidth;
private RoundRectangle2D roundedRectangle;
public RectangleComponent(Color lc, Color dc, int w, int h) {
lifeColour = lc;
deathColour = dc;
widthLife = w;
height = h;
originalWidth = widthLife;
widthDeath = 0;
}
/*
* Overriding this method, so that
* the size of the JComponent
* can be determined, on the screen
* or by the LayoutManager concern.
*/
@Override
public Dimension getPreferredSize() {
return (new Dimension(originalWidth, height));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
roundedRectangle = new RoundRectangle2D.Float((MARGIN + widthDeath), MARGIN,
widthLife, height, MARGIN, MARGIN);
g2d.setPaint(lifeColour);
g2d.draw(roundedRectangle);
g2d.fill(roundedRectangle);
roundedRectangle.setRoundRect(MARGIN, MARGIN,
widthDeath, height, MARGIN, MARGIN);
g2d.setPaint(deathColour);
g2d.draw(roundedRectangle);
g2d.fill(roundedRectangle);
}
public void subtractLife(int amount) {
widthLife -= amount;
widthDeath += amount;
System.out.println("ORIGINAL Width : " + originalWidth);
System.out.println("Width Life : " + widthLife);
System.out.println("Width Death : " + widthDeath);
if (widthLife > 0 && widthDeath < originalWidth) {
/*
* This repaint() will call the paintComponent(...)
* by itself, so nothing else to be done.
*/
repaint();
} else {
widthLife += amount;
widthDeath -= amount;
}
}
public void addLife(int amount) {
widthLife += amount;
widthDeath -= amount;
System.out.println("ORIGINAL Width : " + originalWidth);
System.out.println("Width Life : " + widthLife);
System.out.println("Width Death : " + widthDeath);
if (widthLife < originalWidth && widthDeath > 0) {
repaint();
} else {
widthLife -= amount;
widthDeath += amount;
}
}
}