如何实时更新Swing组件

时间:2018-02-11 17:52:13

标签: java swing

我正在编写一个非常大整数的乘法应用程序,我需要在Swing组件中更新乘法的每个sigle步骤(我创建了一个带有JTextArea的JPane扩展类,然后将它添加到ScrollPane中的JFrame )。问题是这个Swing组件只在乘法算法完成后才更新。我尝试使用一个可以每10毫秒调用一次Pane重绘方法的Thread,但它没有用。接下来是问题的一个例子。

这是主要的Frame类:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class Frame extends JFrame implements ActionListener{
private Console console;
private JButton calculate;
private Calculator calculator;


public Frame(){
    console=new Console();
    calculate=new JButton("Calculate");
    calculate.addActionListener(this);
    calculate.setActionCommand("");
    calculator=new Calculator(this);
    this.setLayout(new BorderLayout());
    this.add(console,BorderLayout.CENTER);
    this.add(calculate, BorderLayout.NORTH);
    this.setTitle("Frame");
    this.setVisible(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setSize(new Dimension(500,500));
    this.setLocationRelativeTo(null);


}


public void writeOnConsole(String txt){
    console.write(txt);
}


@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    if(e.getActionCommand().equals("")){
        console.clear();
        calculator.calculate();
    }
}


public static void main(String[] args) {
    new Frame();
}
}

这是控制台类

import java.awt.BorderLayout;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;

public class Console extends JPanel{

    private JTextArea area;


    public Console(){
        this.setBorder(new TitledBorder("Console:"));
        area=new JTextArea();
        this.setLayout(new BorderLayout());
        JScrollPane scroll=new JScrollPane(area);
        this.add(scroll,BorderLayout.CENTER);
    }

    public void clear(){
        area.setText("");
    }
    public void write(String txt){
        area.append(txt+"\n");
    }
}

最后,这是Calculator类(负责调用写作的人)

public class Calculator {


    private Frame parent;

    public Calculator(Frame f){
        parent=f;
    }

    public void calculate(){
        for (int i = 0; i <= 1000000; i++) {
            parent.writeOnConsole("Iteration "+i);
        }
    }
}

请注意,如果您运行该程序,GUI将冻结,直到Calculator类完成循环。

3 个答案:

答案 0 :(得分:0)

如果您的布局类似于BorderLayout,并且您希望在JFrame中更新它,请执行以下操作

JFrame frame = new JFrame();
BorderLayout layout = new BorderLayout();
layout.layoutContainer(frame.getContentPane());// use the frame as the border layout container

否则你可以使用JFrame pack()方法。 pack方法根据组件的首选大小打包窗口中的组件。它不是用于更新,而是更新JFrame,这是一种技巧

JFrame frame = new JFrame();
//change the components dynamically
frame.pack();

或使用Container methdod validate()。验证容器意味着布置其子组件。与布局相关的更改,例如设置组件的边界或将组件添加到容器中。

JFrame frame = new JFrame();
Container container = frame.getContentPane();
container.validate();

或者如果您想更新特定组件,请使用

Component component = new JPanel();
component.repaint();

如果此组件是轻量级组件,则repaint()方法会尽快调用此组件的paint方法。

或者如果您想要例如动态地逐个发生许多变化,那么您可以使用下面的代码,这与我上面提到的内容完全不同。为此,您可以在另一个线程中使用platform.runlater()来处理即将实时更改的所有内容

new Thread(new Runnable() 
    {
    @Override 
    public void run() 
    {

        Platform.runLater(new Runnable()//use platform.runlater if you are using javafx
        {
            @Override 
            public void run() 
            {
                try
                {Thread.sleep(50);}catch(Exception e){}//use it in for loop where changes happen
                //do some realtime change of components
            }
        });

}).start();

答案 1 :(得分:0)

尝试使用update方法调用paint方法来维护每个更改

答案 2 :(得分:0)

您的控制台类将是

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;


public class Console extends JPanel{

    private JTextArea area;


    public Console(){
        this.setBorder(new TitledBorder("Console:"));
        area=new JTextArea();
        this.setLayout(new BorderLayout());
        JScrollPane scroll=new JScrollPane(area);
        this.add(scroll,BorderLayout.CENTER);
    }

    public void clear(){
        area.setText("");
    }
    public void write(String txt){

        area.append(txt+" "+"\n");

    }
  }

并且Calculator类是

public class Calculator {


    private Frame parent;

    public Calculator(Frame f){
        parent=f;
    }

    public void calculate(){
        new Thread(new Runnable() {
            @Override 
            public void run() 
            {

                for (int i = 0; i <= 100; i++) {
                    try
                    {
                        Thread.sleep(50);

                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }

                    parent.writeOnConsole("Iteration "+i);
                }

            }   
        }).start();


    }
}

正如您所见,我使用另一个线程进行更改