簡體   English   中英

重新繪制方法后無法在JPanel上繪制

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

我正在嘗試對自己編寫的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);
}

一切正常,但是當我想打開為保存所有要點而創建的XML文件時,它不起作用。 問題是,當我選擇文件后在jPanel上使用repaint方法時,所有點均加載良好,但面板無法繪制這些點。 如果我將重繪方法放在打開按鈕偵聽器中(在選擇文件之前),則可以,但是如果用戶取消了打開選項,則面板保持空白,並且我不想再次繪制點。 我認為發生這種情況是因為重新粉刷過程尚未完成。 所有點都添加到私有列表中。

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

我如何使它工作?

不要使用gf = (Graphics)myPnl.getGraphics(); ,這不是Swing中的繪畫工作原理。 getGraphics方法可以返回null ,僅是最后一個繪制周期的快照,您對其繪制的任何內容都將在下一個繪制周期(重新繪制)中刪除。

而是重寫JPanelpaintComponent並將所有繪畫邏輯放在此處。 期望在被調用時,您應該完全重新繪制組件的當前狀態。

有關繪畫如何在Swing中工作的更多詳細信息,請參見AWT中的繪畫和Swing執行自定義繪畫

您必須使用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);
    }
}

如果要繪制所有點,請不要使用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);
    }
}

哪里:

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

然后使用它:

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