添加项目到JPanel不要'出现

时间:2016-04-26 20:33:55

标签: java swing

我希望有人能帮助我。我无法找到描述这个问题的人。在扩展Window的主类(JFrame)中,我添加了一个扩展Panel的类(JPanel)的对象并将其添加到我的框架中。

到目前为止一切顺利,JPanel类中的所有内容都显示出来,但是当我在我的主类中创建ShapeDef对象(用于定义和绘制数字)时,然后尝试将其添加到Panel,数字不会显示出来。为什么?我尝试使用revalidate()repaint,但它似乎无法运作。

这里有一些代码:

主级:

public class Window extends JFrame implements ActionListener{

private JPanel myPanel;
private ShapeDef rect1, rect2;

public Window(){
    super("Test Window");
    setLayout(new BorderLayout());

    myPanel = new Panel(new BorderLayout()); 
    myPanel.setBackground(Color.BLACK);

    rect1 = new ShapeDef("Rectangle", Color.green, 200, 300, 20, 80);
    rect2 = new ShapeDef("Rectangle", Color.BLUE, 300, 700, 50, 40);
    myPanel.add(rect1);
    myPanel.add(rect2);

    add(myPanel, BorderLayout.CENTER);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            JFrame myFrame = new PongInvaders();
            myFrame.setSize(1280, 720);
            myFrame.setBackground(Color.BLACK);
            myFrame.pack();
            myFrame.setVisible(true);
        }
    });
}

ShapeDef类:

public class ShapeDef extends JComponent{
    private final Color color;
    private final int x, y, width, height;
    private final String type;

    public ShapeDef(String type, Color color, int x, int y, int width, int height){
        this.type = type;
        this.color = color;
        setBounds(x, y, width, height);
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;

    }

        @Override
        public void paintComponent(Graphics g){
        super.paintComponent(g);
        if(type.equalsIgnoreCase("Rectangle")){
            g.setColor(color);
            g.fillRect(0, 0, width, height);
        }
        else if(type.equalsIgnoreCase("Oval")){
            g.setColor(color);
            g.fillOval(x, y, width, height);
        }
    }
}

由李克强建议的当前版本的代码绘制了两个矩形,但是rect2在(0,0)处产生,而rect1在正确的坐标处产生。基本上这个问题已经回答了,所以谢谢大家的帮助。然而,为什么只有一个矩形在(0,0)产生,而另一个产生于设定坐标,当它们都被添加到同一个JPanel?

@MadProgrammer虽然你的答案不是我所期待的,但我认为这是我需要的答案。你绝对不辜负你的用户名。非常感谢您花时间教我更多关于创建更好的代码结构的知识。

我还想指出,其他答案非常有帮助和启发,他们也教我很多。

5 个答案:

答案 0 :(得分:1)

你最大的问题是你要覆盖ShapeDef中的所有维度(x,y,width,height),而不是使用JCompoment方法(setSize,setPreferredSize(),setLocation)来设置它们。因此,您的ShapeDef没有大小,并且您在其中执行的任何绘制都将被图形剪辑阻止。

您还应该将 if (cb.GetChecked()) grid.Refresh(); 的布局管理器显式设置为null

答案 1 :(得分:1)

  

向JPanel添加项目不要'出现

如果您延伸到JComponent,则JComponent本身已具有管理其维度和位置的属性,例如xywidth,{{1 }}

但是,您不是使用继承的属性,而是创建另一组具有相同名称的属性,这些属性可能会遮蔽继承的属性。

我发现您正在创建自己的heightxywidth,这是不必要的。如果这些是为其他目的而创建的,您可能希望将它们重命名为其他目的。

除此之外,如果您只想要一些自定义绘图,则不必总是将height课程扩展为ShapeDef。你可以这样做:

JComponent

让你的JPanel持有ShapeDef的一个实例,并在JPanel中绘制它,只需这样做:

class ShapeDef
{
    //other constructors and attributes not shown
    public void draw(Graphics g){
        //draw your drawings here..
    }
}

答案 2 :(得分:1)

除了ControlAltDel在his Answer中所说的内容(将LayoutManager设置为null),您还必须为fillRect和fillOval设置x和y坐标为零。如果不这样做,由于剪裁,矩形将不可见。

public class ShapeDef extends JComponent {
    private final Color color;
    private int width, height;
    private final String type;

    public ShapeDef(String type, Color color, int x, int y, int width, int height){
        this.type = type;
        this.color = color;
        this.width = width;
        this.height = height;
        this.setBounds(x, y, width, height); // creates a bounding box for your drawing
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        if(type.equalsIgnoreCase("Rectangle")){
            g.setColor(color);
            g.fillRect(0, 0, width, height); // draws inside of your bounding box
            System.out.println("Rect");
        }
        else if(type.equalsIgnoreCase("Oval")){
            g.setColor(color);
            g.fillOval(0, 0, width, height); // draws inside of your bounding box
        }
    }
}

另外请考虑使用枚举而不是字符串作为类型参数。

答案 3 :(得分:1)

就个人而言,我认为你从错误的角度来看待解决方案。组件并没有真正设计用于实现这一目标,确保你可以让它们做到这一点,但它会导致一些有趣的路径,如果你不小心的话可能会让你在排水沟里流血。

相反,我定义了一个"基本"形状可以"画"从中,定义所有其他形状。

public interface Drawable {
    public Color getStrokeColor();
    public Color getFillColor();
    public Rectangle getBounds();
    public void paint(Graphics2D g2d);
}

public abstract class AbstractDrawable implements Drawable {

    private Color strokeColor;
    private Color fillColor;

    public AbstractDrawable(Color strokeColor, Color fillColor) {
        this.strokeColor = strokeColor;
        this.fillColor = fillColor;
    }

    @Override
    public Color getStrokeColor() {
        return strokeColor;
    }

    @Override
    public Color getFillColor() {
        return fillColor;
    }

}

public class RectangleDrawable extends AbstractDrawable {

    private Rectangle bounds;

    public RectangleDrawable(int x, int y, int width, int height, Color strokeColor, Color fillColor) {
        super(strokeColor, fillColor);
        bounds = new Rectangle(x, y, width, height);
    }

    @Override
    public Rectangle getBounds() {
        return bounds;
    }

    @Override
    public void paint(Graphics2D g2d) {
        g2d.setColor(getFillColor());
        g2d.fill(getBounds());
        g2d.setColor(getStrokeColor());
        g2d.draw(getBounds());
    }

}

public class OvalDrawable extends AbstractDrawable {

    private Ellipse2D bounds;

    public OvalDrawable(int x, int y, int width, int height, Color strokeColor, Color fillColor) {
        super(strokeColor, fillColor);
        bounds = new Ellipse2D.Double(x, y, width, height);
    }

    @Override
    public Rectangle getBounds() {
        return bounds.getBounds();
    }

    @Override
    public void paint(Graphics2D g2d) {
        g2d.setColor(getFillColor());
        g2d.fill(bounds);
        g2d.setColor(getStrokeColor());
        g2d.draw(bounds);
    }

}

然后我有一个能够管理和绘画的专用组件

Simple Shapes

public class DrawablePane extends JPanel {

    private List<Drawable> drawables;

    public DrawablePane() {
        drawables = new ArrayList<>(25);
    }

    public void add(Drawable drawable) {
        drawables.add(drawable);
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        for (Drawable drawable : drawables) {
            drawable.paint(g2d);
        }
        g2d.dispose();
    }

}

可能会使用类似......

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }

        DrawablePane pane = new DrawablePane();
        pane.add(new RectangleDrawable(10, 10, 100, 150, Color.YELLOW, Color.GREEN));
        pane.add(new OvalDrawable(100, 20, 50, 50, Color.MAGENTA, Color.BLUE));

        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(pane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
});

答案 4 :(得分:0)

您的ShapeDef课程应确定其大小和位置。您可以将其定义如下:

public class ShapeDef extends JComponent {
    private final Color color;
    private final String type;

    public ShapeDef(String type, Color color, int x, int y, int width, int height) {
        this.type = type;
        this.color = color;

        setPreferredSize(new Dimension(width, height));
        setLocation(new Point(x, y));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (type.equalsIgnoreCase("Rectangle")) {
            g.setColor(color);
            g.fillRect(getX(), getY(), getSize().width, getSize().height);
            System.out.println("Rect");
        } else if (type.equalsIgnoreCase("Oval")) {
            g.setColor(color);
            g.fillOval(getX(), getY(), getSize().width, getSize().height);
        }
    }
}

然后你可以在你的窗口类中使用它:

public class MyWindow extends JFrame {
    private JPanel myPanel;
    private ShapeDef shape;

    public MyWindow() {
        super("Test Window");
        setLayout(new BorderLayout());

        myPanel = new JPanel(new BorderLayout());
        myPanel.setBackground(Color.BLACK);

        shape = new ShapeDef("Rectangle", Color.green, 200, 300, 20, 80);
        myPanel.add(shape, BorderLayout.CENTER);

        add(myPanel, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }


    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame myFrame = new MyWindow();
                myFrame.pack();
                myFrame.setVisible(true);
            }
        });
    }
}

你真的不需要那个定制的Panel课,关于你在做什么。