在Java中创建矩形时,我真的调用了paintComponent方法吗?
这是我当前的RectangleComponent类,我将它添加到主JFrame中的面板中,但它从未出现过。我认为它不是绘图,所以我决定在矩形的构造函数中调用paintComponent方法,在对4-5个NullPointerException进行排序后,没有任何变化。我已经阅读了多个关于如何绘制矩形的指南,并且看到了多个代码示例,但是我永远无法让面板与多个JComponent一起工作。如果可以的话,请简单看看我的代码,看看你是否能想出一个解决方案。 谢谢你抽出时间。还列出了我在其中调用矩形构造函数的框架在Java中创建矩形时,我真的调用了paintComponent方法吗?,java,swing,jframe,jpanel,jcomponent,Java,Swing,Jframe,Jpanel,Jcomponent,这是我当前的RectangleComponent类,我将它添加到主JFrame中的面板中,但它从未出现过。我认为它不是绘图,所以我决定在矩形的构造函数中调用paintComponent方法,在对4-5个NullPointerException进行排序后,没有任何变化。我已经阅读了多个关于如何绘制矩形的指南,并且看到了多个代码示例,但是我永远无法让面板与多个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();
}
}
无需将
JPanel
传递给RectangleComponent
的构造函数,只需获取Graphics
,也无需手动调用paintComponent
。看见查看这个演示绘制矩形的自定义组件 您的代码有点创意,有点疯狂,而且逻辑很难理解。最不寻常的是,它有两个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,这两项都不应该完成。您需要阅读图形教程,了解如何正确执行此操作
我建议您考虑重新编写这篇文章,首先,只使用一个JFrand,更好地组织您的代码。
为了使Swing应用程序如期工作,您需要记住很多事情。为了避免可能出现的某些障碍,必须遵循某些步骤,因为您的编码方式是错误的。为此,请严格遵循Swing编程的基础知识
- 就像@HovercraftFullOfEels提到的,你打电话给你的 图形直接,这是一个永远不应该做的
- 其次,查看您的
构造函数,将其设置为 可见,甚至在您向其添加任何组件之前 在确定它的实际大小之前GameFrame()
自定义组件的大小,即JComponent
,因此您无法在屏幕上看到它。当您将jcomponent
扩展到您的类时,将其作为一种习惯习惯来重写,就像重写它的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.*;
导入java.awt.event.*;
导入java.awt.geom.RoundRectangle2D;
导入javax.swing.*;
公共级定制绘画{
私人生活;
私人矩形管死亡;
私有void createAndDisplayGUI(){
JFrame=新JFrame(“定制绘画”);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel centerPanel=新的JPanel();
setLayout(新的GridLayout(0,2,5,5));
//指定此组件的宽度、高度和颜色。
寿命=新矩形组件(Color.GREEN.darker(),20,20);
死亡=新的矩形组件(Color.RED.darker(),20,20);
添加(生活);
添加(死亡);
JPanel buttonPanel=新的JPanel();
buttonPanel.setLayout(新的FlowLayout(FlowLayout.LEFT,5,5));
JButton incLifeButton=新JButton(“增加寿命”);
incLifeButton.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效行动(行动事件ae){
生活。生活(1);
}
});
JButton decleivebutton=新JButton(“减少寿命”);
addActionListener(新ActionListener()){
@凌驾
已执行的公共无效行动(行动事件ae){
生活。减去生活(1);
}
});
JButton incdeath按钮=新JButton(“增加死亡”);
incDeathButton.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效行动(行动事件ae){
死亡。生命(1);
}
});
JButton decDeathButton=新JButton(“减少死亡”);
decDeathButton.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效行动(行动事件ae){
死亡。减去生命(1);
}
});
按钮面板添加(包括按钮);
按钮面板。添加(取消按钮);
按钮面板。添加(incDeathButton);
按钮面板。添加(decDeathButton);
frame.getContentPane().add(中心面板,BorderLayout.CENTER);
frame.getContentPane().add(buttonPanel,BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串\u005B\u005D参数){
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
新建CustomPaint().createAndDisplayGUI();
}
});
}
}
类RectangleComponent扩展了JComponent{
私人色彩
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;
}
}
}