简体   繁体   English

重新绘制方法后无法在JPanel上绘制

[英]can't draw on a JPanel after repaint method

I'm experimenting on a GUI that I programmed and I don't understand how I can fix my problem: My GUI contains a jPanel that on receiving a mouseclick, paints a point with filloval command. 我正在尝试对自己编写的GUI进行实验,但我不知道如何解决该问题:我的GUI包含一个jPanel,该jPanel会在接收到鼠标单击时使用filloval命令绘制一个点。

private void myPnlMousePressed(java.awt.event.MouseEvent evt) {                                   
    changed = true;
    p.x = evt.getX();
    p.y = evt.getY();
    drewPoints(p.x, p.y);
} 

private void drewPoints (int x, int y) {
    if (gf == null) {
        gf = (Graphics)myPnl.getGraphics();
    }
    myPointsList.add(new Point(x, y));
    gf.fillOval(x, y, 5, 5);
    xVal.setText("X = " + x);
    yVal.setText("Y = " + y);
}

everything works fine but when I want to open an XML file that I created to save all the points it doesn't work. 一切正常,但是当我想打开为保存所有要点而创建的XML文件时,它不起作用。 The problem is that when I use the repaint method on the jPanel after choosing a file, all the points loads fine but the panel can't draw the points. 问题是,当我选择文件后在jPanel上使用repaint方法时,所有点均加载良好,但面板无法绘制这些点。 If I put the repaint method in the open button listener (before the choosing file) it works, but then if the user cancels the open option so the panel stays blank and I don't want to draw the points again. 如果我将重绘方法放在打开按钮侦听器中(在选择文件之前),则可以,但是如果用户取消了打开选项,则面板保持空白,并且我不想再次绘制点。 I think it happens because the repaint process is not finished. 我认为发生这种情况是因为重新粉刷过程尚未完成。 All the points added to a private List. 所有点都添加到私有列表中。

private void OpenFile() {
    try {
        File thisFile;
        JFileChooser of = new JFileChooser();
        int option = of.showOpenDialog(of);

        if (option == JFileChooser.APPROVE_OPTION){
            thisFileName = of.getSelectedFile().getPath();
            thisFile =  new File(thisFileName);                
            if (!of.getSelectedFile().getName().endsWith(".xml")) {
                String error = "Error, You didn't select XML file";
                JOptionPane.showMessageDialog(this, error, "Wrong type of file", JOptionPane.INFORMATION_MESSAGE);
                return;
            }            
            myPnl.repaint();
            myPointsList.clear();
                        ....
                        ....
                        ....
            for (int i = 0; i < pointsList.getLength(); i++) {
                Element point = (Element) pointsList.item(i);
                p.x = Integer.parseInt(point.getElementsByTagName("X").item(0).getTextContent());
                p.y = Integer.parseInt(point.getElementsByTagName("Y").item(0).getTextContent());
                drewPoints(p.x, p.y);
            }
                        ....

how can I make it work?? 我如何使它工作?

Don't use gf = (Graphics)myPnl.getGraphics(); 不要使用gf = (Graphics)myPnl.getGraphics(); , this is not how painting in Swing works. ,这不是Swing中的绘画工作原理。 The getGraphics method can return null and is nothing more then a snap shot of the last paint cycle, any thing you paint to it will be erased on the next paint cycle (repaint). getGraphics方法可以返回null ,仅是最后一个绘制周期的快照,您对其绘制的任何内容都将在下一个绘制周期(重新绘制)中删除。

Instead, override the JPanel s paintComponent and put all you painting logic there. 而是重写JPanelpaintComponent并将所有绘画逻辑放在此处。 There is an expectation that when called, you are expected to fully re-paint the current state of the component. 期望在被调用时,您应该完全重新绘制组件的当前状态。

See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing 有关绘画如何在Swing中工作的更多详细信息,请参见AWT中的绘画和Swing执行自定义绘画

You have to use the repaint() and override the paint() method: 您必须使用repaint()并重写paint()方法:

class MyPanel extends JPanel implements MouseListener
{
    private int x;
    private int y;

    public MyPanel() {
        super();
        addMouseListener(this);
    }

    @Override public void mouseEntered(MouseEvent e) { }

    @Override public void mouseExited(MouseEvent e) { }

    @Override public void mouseClicked(MouseEvent e) { }

    @Override public void mousePressed(MouseEvent e) { }

    @Override public void mouseReleased(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        repaint();
    }

    @Override public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x, y, 10, 10);
    }
}

If you want to draw all points, don't use x and y but a list of points : 如果要绘制所有点,请不要使用xy而要使用list of points

class MyPanel extends JPanel implements MouseListener
{
    private ArrayList<Point> points = new ArrayList<>();

    public MyPanel() {
        super();
        addMouseListener(this);
    }

    @Override public void mouseEntered(MouseEvent e) { }

    @Override public void mouseExited(MouseEvent e) { }

    @Override public void mouseClicked(MouseEvent e) { }

    @Override public void mousePressed(MouseEvent e) { }

    @Override public void mouseReleased(MouseEvent e) {
        points.add(new Point(e.getX(), e.getY()));
        repaint();
    }

    @Override public void paint(Graphics g) {
        super.paint(g);
        for (Point p : points)
            g.fillOval(p.getX(), p.getY(), 10, 10);
    }
}

where: 哪里:

class Point
{
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

Then use it: 然后使用它:

public static void main(String[] args) {
    JFrame frame = new JFrame("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setLocationRelativeTo(null);

    MyPanel myPanel = new MyPanel();

    frame.add(myPanel);
    frame.setVisible(true);
}

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

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