事件发生后如何重新绘制JPanel

问题描述 投票:0回答:2

我正在尝试在事件发生后重新绘制 JPanel。我真的不知道

 .repaint()
.revalidate()
是如何工作的。每个人都告诉我这会起作用,但不适合我。

我的代码由ParentFrame、ChildFrame和测试类组成。测试类只是为了

main
功能。

我的项目比下面的代码稍微复杂一些,但我只是选择了我需要弄清楚的事情。

基本上,ParentFrame 显示我定义的 ArrayList 中的字符串。一旦我点击

EDIT
按钮,ChildFrame 就会出现。然后我填写 JTextField 并单击
OK
按钮。
然后 ChildFrame 必须消失,ParentFrame 应该用新编辑的 ArrayList 重新绘制。

我的项目使用

addMouseListener
来选择应该编辑哪个,但我刚刚删除了它。因为我唯一需要弄清楚的是如何重新绘制 JPanel。我只是将目标设置为
list.get(0)
,这是第一个。

我尝试用

panel.revalidate();
+
panel.repaint();
重新绘制,但根本不起作用。

这是我的代码。需要你的帮助!!!

父框架

public class ParentFrame extends JFrame {
    private ArrayList<String> list = new ArrayList<>(){{add("test1"); add("test2");}};
    JPanel big;
    JLabel content;
    
    public ParentFrame() {
        super("parent");
        super.setSize(200,200);
        super.setLayout(new BorderLayout());
        
        big = new JPanel();
        
        for(int i=0; i<list.size(); i++) {
            content = new JLabel();
            content.setText(list.get(i));

            big.add(content);
        }
        super.add(big, BorderLayout.CENTER);
        
        JButton edit = new JButton("EDIT");
        edit.addActionListener(new EditListener());
        super.add(edit, BorderLayout.SOUTH);
        
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public ArrayList<String> getParentList() {
        return list;
    }
    
    public void setParentList(int i, String b) {
        this.list.set(i,b);
    }

    public class EditListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            ChildFrame child = new ChildFrame(ParentFrame.this);
            list = child.newList;
            
            big.revalidate();
            big.repaint();
        }
    } 
}

子框架

public class ChildFrame extends JFrame {
    ArrayList<String> newList;
    
    public ChildFrame(ParentFrame pF) {
        super("child");
        super.setSize(100,100);
        super.setLayout(new BorderLayout());
                
        newList = pF.getParentList();
        
        JTextField edit = new JTextField(pF.getParentList().get(0));
        add(edit, BorderLayout.CENTER);
        
        JButton ok = new JButton("OK");
        ok.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                newList.set(0, edit.getText());

                dispose();
            }
        });
        add(ok, BorderLayout.SOUTH);
        
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

测试

public class Test {

    public static void main(String[] args) {
            ParentFrame pF = new ParentFrame();
    }
}

从ParentFrame代码中可以看到,我将

.revalidate()
.repaint()
放在
EditListener
的函数
actionPerformed
中。但这不起作用...

java swing jpanel awt repaint
2个回答
0
投票

请注意,调用 repaint() 不会在屏幕上绘制组件。而是将组件标记为脏(这意味着它正在等待重新绘制)。 实际的重绘发生在事件调度线程上。

现在,当某些事件发生时,您的事件处理程序就会被触发,并且很可能您会更新模型并想要触发重绘。但请注意,事件处理程序是使用事件调度程序线程触发的,只要您阻止该线程,就不会发生重绘。

所以你实际上可以做两件事之一:

  • 使用快速操作更新模型,然后使用 SwingUtilities.invokeLater().
  • 触发重绘
  • 对于运行时间较长的操作,创建一个单独的线程来执行该操作,然后通知 UI 重新绘制。

网络上有很多如何执行此操作的示例,其中之一是 https://www.javamex.com/tutorials/threads/invokelater.shtml


0
投票

我认为这个问题可以通过使用来解决 setVisible(假); 设置可见(真); 在 jPanel 上

© www.soinside.com 2019 - 2024. All rights reserved.