我正在尝试制作一个具有显示多边形和两个按钮的窗口的程序。多边形从3个点(三角形)开始,允许用户按“+”和“ - ”按钮来添加或减去多边形的边。这是我的代码:
在TestPolygonBox中:
package testpolygonbox
import javax.swing.*;
import java.awt.*;
public class TestPolygonBox extends JFrame {
public TestPolygonBox(){
setLayout(new BorderLayout(5,5));
add(new PolygonBox ());
}
public static void main(String[] args) {
TestPolygonBox frame = new TestPolygonBox();
frame.setTitle("Polygon Box");
frame.setSize(400,420);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
接下来是控制类:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class PolygonBox extends JPanel {
private JButton jbtEnlarge = new JButton("+");
private JButton jbtShrink = new JButton("-");
private PolygonPanel polygonPanel = new PolygonPanel();
public PolygonBox(){
JPanel panel = new JPanel();
panel.add(jbtEnlarge);
panel.add(jbtShrink);
setLayout(new BorderLayout());
this.add(polygonPanel,BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
jbtEnlarge.addActionListener(new EnlargeListener());
jbtShrink.addActionListener(new ShrinkListener());
}
class EnlargeListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e){
polygonPanel.enlarge();
}
}
class ShrinkListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e){
polygonPanel.shrink();
}
}
}
class PolygonPanel extends JPanel{
private int polygonSides = 3;
/** Add side to the polygon*/
public void enlarge(){
polygonSides++;
repaint();
}
public void shrink(){
polygonSides--;
repaint();
}
@Override /** Draw requested Shape*/
protected void paintComponent(Graphics g){
int frameWidth = getWidth() / 2;
int frameHeight = getHeight() / 2;
int radius = (int)(Math.min(getWidth(),getHeight())* 0.4);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
g.setColor(Color.BLUE);
Polygon polygon = new Polygon();
polygon.addPoint(xCenter + radius, yCenter);
polygon.addPoint((int)(xCenter + radius * Math.cos(2 * Math.PI/polygonSides)),
(int)(yCenter - radius * Math.sin(2 * Math.PI / polygonSides)));
for (int polygonPoint = 2; polygonPoint <= polygonSides; polygonPoint++){
polygon.addPoint((int)(xCenter + radius * Math.cos(polygonPoint * 2 * Math.PI/polygonSides)),
(int)(yCenter - radius * Math.sin(polygonPoint * 2 * Math.PI / polygonSides)));
}
g.fillPolygon(polygon);
}
}
当我尝试运行此程序时,我收到错误: 线程“main”中的异常java.lang.IllegalArgumentException:向容器添加窗口 在java.awt.Container.checkNotAWindow(Container.java:483) 在java.awt.Container.addImpl(Container.java:1084) at java.awt.Container.add(Container.java:998) 在javax.swing.JFrame.addImpl(JFrame.java:562) 在java.awt.Container.add(Container.java:410) 在testpolygonbox.TestPolygonBox。(TestPolygonBox.java:21) 在testpolygonbox.TestPolygonBox.main(TestPolygonBox.java:24) Java结果:1
如果有人能告诉我在哪个窗口添加到容器中吗?我不确定我做错了什么。
答案 0 :(得分:1)
PolygonBox
是JFrame
窗口,但您将其添加到另一个JFrame
。更改类,使其扩展JPanel
。
public class PolygonBox extends JPanel {
答案 1 :(得分:0)
您的代码存在4个严重问题。
您没有在事件派发线程(EDT)中执行Swing代码。你的主要看起来像这样:
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
initializeGUI();
}
}
}
即使Swing Hello World - 最简单的Swing程序 - 这也是非常重要的。如果你想知道为什么会这样,请阅读concurrency tutorial。简而言之,如果一旦程序变得更大,更复杂,你就不能正确地做到这一点,你会看到Swing类中出现很多不一致,不可重现的异常和错误,你无法追踪。
其次,正如Reimeus所说,你不能把框架放在另一个框架内,PolygonBox必须是JPanel
。
第三,您没有正确填充面板。看看这段代码:
JPanel panel = new JPanel();
panel.add(jbtEnlarge);
panel.add(jbtShrink);
这段代码看起来很怪异,而且确实如此。当你看到它时弹出的问题是:“这些按钮在哪里添加?”那么在panel
当然,但在面板中?这取决于面板使用的布局。那个面板的布局是什么?好吧,因为您没有明确指定它正在使用JPanels的默认布局:BorderLayout。边框布局panel.add(component);
相当于panel.add(component, BorderLayout.CENTER);
。但是你不能把两个组件放在CENTER中,你可以把一个面板包含很多组件或者其他什么,但是你不能直接放两个组件,这就是为什么那个代码不起作用的原因。那么你如何填充面板?选择一个布局学习使用它,然后以适当的方式添加组件。例如,我将使用GridLayout。
JPanel panel = new JPanel(new GridLayout(1, 2));
panel.add(_enlargeButton);
panel.add(_shrinkButton);
使用Grid布局,因为我说我想要一个网格1x2,这些添加是正确的,因为面板现在知道他必须将组件放在网格的每个单元格中。
最后你会看到有绘画问题:多边形没有被删除,它们被涂在一起,你可能会看到面板中按钮的图像...这是因为你有在paintComponent方法中调用super.paintComponent(g)
。事实是代码绘制了一个多边形,是的,但是你还必须完成组件为绘制自身所做的所有其他工作,所以你要做的第一件事就是调用你要覆盖的原始代码,然后绘制你的组件。有关为何如此工作的详尽教程,请参阅Painting in AWT and Swing。
尽管如此,更改一些变量名称以遵循Java约定并重新格式化代码以实现更好的组织。这是你的固定计划:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Polygon;
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.SwingUtilities;
public class TestPolygonBox extends JFrame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() { //Error 1: executing Swing code outside the EDT fixed
public void run()
{
TestPolygonBox frame = new TestPolygonBox();
frame.setVisible(true);
}
});
}
public TestPolygonBox()
{
super("Polygon Box"); //this is JFrame("title") since we are extending a frame
setLayout(new BorderLayout());//this line doesn't actually do nothing since the frame already usesk BorderLayout by default
add(buildPolygonBoxPanel());
setSize(400, 420);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
private JPanel buildPolygonBoxPanel() //Error 2: PolygonBox has to be a panel, also I made it into a mthod returning the panel instead of a whole class since it was unnecessary.
{
JPanel polygonBox = new JPanel(new BorderLayout());
_polygonPanel = new PolygonPanel();
JPanel buttonsPanel = new JPanel(new GridLayout(1, 2)); //Error 4 adding the buttons properly to a panel.
_enlargeButton = new JButton("+1");
_enlargeButton.addActionListener(new EnlargeListener());
_shrinkButton = new JButton("-1");
_shrinkButton.addActionListener(new ShrinkListener());
buttonsPanel.add(_enlargeButton);
buttonsPanel.add(_shrinkButton);
polygonBox.add(_polygonPanel, BorderLayout.CENTER);
polygonBox.add(buttonsPanel, BorderLayout.SOUTH);
return polygonBox;
}
class EnlargeListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
_polygonPanel.enlarge();
}
}
class ShrinkListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
_polygonPanel.shrink();
}
}
private JButton _enlargeButton;
private JButton _shrinkButton;
private PolygonPanel _polygonPanel;
}
class PolygonPanel extends JPanel
{
private int _polygonSides = 3;
/** Add side to the polygon */
public void enlarge()
{
_polygonSides++;
repaint();
}
public void shrink()
{
if (_polygonSides > 3) _polygonSides--;
repaint();
}
@Override
/** Draw requested Shape*/
protected void paintComponent(Graphics g)
{
super.paintComponent(g); //Error 4 fixed, call super.paintComponent
int radius = (int) (Math.min(getWidth(), getHeight()) * 0.4);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
g.setColor(Color.BLUE);
Polygon polygon = new Polygon();
polygon.addPoint(xCenter + radius, yCenter);
polygon.addPoint((int) (xCenter + radius * Math.cos(2 * Math.PI / _polygonSides)), (int) (yCenter - radius * Math.sin(2 * Math.PI / _polygonSides)));
for (int polygonPoint = 2; polygonPoint <= _polygonSides; polygonPoint++)
{
polygon.addPoint((int) (xCenter + radius * Math.cos(polygonPoint * 2 * Math.PI / _polygonSides)), (int) (yCenter - radius * Math.sin(polygonPoint * 2 * Math.PI / _polygonSides)));
}
g.fillPolygon(polygon);
}
}
只需复制并执行它,它看起来像这样: