简体   繁体   English

Gui 图形未出现在面板中

[英]Gui graphic does not appear in Panel

I am trying to make a drawOval moving by using the two buttons that I set to be North and East so the ball will move between the JButtons, at the center.我试图通过使用我设置为NorthEast的两个按钮使drawOval移动,因此球将在中心的 JButton 之间移动。

Why does not appear at the panel?为什么不出现在面板上?

Also I am thinking using a function that make this x=x+ ;此外,我正在考虑使用一个使x=x+的函数; and y=y+1 when I pressed left or right.当我向左或向右按​​下时, y=y+1

I do not figure out what can I do.我不知道我能做什么。

So this is the code I made:所以这是我制作的代码:

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

    }   
}

To understand why it's not working, you need to understand how the paint system actually works要了解为什么它不起作用,您需要了解油漆系统的实际工作原理

Just by looking at this snippet it should be obvious something is wrong.仅通过查看此代码段,就应该很明显有问题。

public class Main extends JFrame implements ActionListener {
    //...    
    public void paintComponent (Graphics g) {
        super.paintComponents(g);
        //...
    }
}

You've declare a method called paintComponent but are calling the super method paintComponents (note the s at the end).您已经声明了一个名为paintComponent的方法,但正在调用super 方法paintComponents (注意末尾的s )。

Further, when ever you "think" you're overriding a method, you should make use of the #Override attribute, this will cause a compiler error when you've done something wrong此外,当你“认为”你正在重写一个方法时,你应该使用#Override属性,当你做错了什么时这会导致编译器错误

public class Main extends JFrame implements ActionListener {
    //... 
    @Overrride   
    public void paintComponent (Graphics g) {
        super.paintComponents(g);
        //...
    }
}

The above code will now fail to compile, as JFrame doesn't declare a paintComponent method.上面的代码现在将无法编译,因为JFrame没有声明paintComponent方法。

As a general rule, you should avoid extending directly from JFrame (or other top level containers), they are compound components and have a complex hierarchy and functionality.作为一般规则,您应该避免直接从JFrame (或其他顶级容器)扩展,它们是复合组件并且具有复杂的层次结构和功能。

A better place to start might be with a JPanel一个更好的起点可能是使用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);

        }
    }

}

You should take the time to have a look at Painting in Swing and Performing Custom Painting for more details.您应该花时间查看在 Swing绘画执行自定义绘画以了解更多详细信息。

Some other concepts you might like to take the time to learn:您可能想花时间学习的其他一些概念:

  • Single Responsibility Principle - a class should do one thing and do it well 单一职责原则——一个班级应该做一件事并且做好
  • Observer Pattern - This typically represent in Swing as the listener API观察者模式- 这通常在 Swing 中表示为侦听器 API
  • Model-View-Controller - this encompasses the above and defines different layers of responsibility for different parts of the program, it will helper you understand the basic structure of Swing as well 模型-视图-控制器- 这包括上述内容,并为程序的不同部分定义了不同的职责层,它也将帮助您理解 Swing 的基本结构

Also I am thinking using a function that make this x=x+ ;此外,我正在考虑使用一个使x=x+的函数; and y=y+1 when I pressed left or right.当我向左或向右按​​下时, y=y+1

Ok, so this is where the "model" part of the MVC will play it's part.好的,这就是 MVC 的“模型”部分将发挥作用的地方。

So lets start by defining the basic properties we expect the model to support...因此,让我们首先定义我们希望模型支持的基本属性......

public interface ShapeModel {
    public Point getPoint();
    public void addChangeListener(ChangeListener listener);
    public void removeChangeListener(ChangeListener listener);
}

Here is supports a Point to act as the location and a ChangeListener to act as the observer pattern, which will notify interested parties that the state of the model has changed.这里支持一个Point作为位置,一个ChangeListener作为观察者模式,它会通知感兴趣的各方模型的状态已经改变。

Why start with a interface ?为什么要从interface开始? As a general concept, you should always prefer to code to interface instead of implementation.作为一般概念,您应该始终更喜欢对接口而不是实现进行编码。 In this case, one aspect of the interface which hasn't been defined is, how does the Point get updated?在这种情况下,尚未定义的interface一个方面是, Point如何更新? That's of little interest to most parties who want to work with the model, they just want to know when it changes, the mutation of the model can be expressed either directly via the implementation or a "mutable" interface which extends from the this interface对于大多数想要使用模型的各方来说,这没什么兴趣,他们只是想知道它何时发生变化,模型的变异可以通过实现或从 this interface扩展的“可变” interface直接表达

Next, we define a default implementation...接下来,我们定义一个默认实现...

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);
    }

}

This does define how the paint is to be updated.这确实定义了如何更新油漆。

Finally, we update the TestPane and PaintPane to support the model...最后,我们更新了TestPanePaintPane以支持模型...

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);

    }
}

Why does not appear at the panel?为什么不出现在面板上?

To display graphic you created, use follow these steps,要显示您创建的图形,请使用以下步骤,

Remove paintComponent method and replace it with below code..删除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);
        }
    };
}

Then call it in Main() constructor,然后在Main()构造函数中调用它,

p.add("Center", createOvel());

This will display the graphic you created.这将显示您创建的图形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM