使用javax.swing.timer定期更新JLabel不稳定(波动)

时间:2017-07-22 17:52:31

标签: java swing jlabel javax.swing.timer

我想以大约300毫秒的恒定速率更新JLabel。目前我使用以下代码部分来执行此操作:

class setLabel {

    PdfHandler PdfHandling = new PdfHandler(pdfName);//as the name implies, this object is to handle pdf's
    Iterator<String> textIterator=PdfHandling.getPageStringList(pageNr).iterator();//extracting text from a pdf word by word

    ActionListener task = new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            centerLabel.setText(textIterator.next());//update the JLabel cenetrLabel with the next string in the textIterator
        }
    };

    public void startTask(){
            new javax.swing.Timer(rate, task).start();
    }

}

问题是使用此代码会导致JLabel(centerLabel)的非常量更新。这意味着两个“新”标签之间的时间不是恒定的(您可以用裸眼看到)并且由于更新之间的时间太短,似乎会跳过一些字符串。我已经尝试了几个不同的东西,比如使用invokeLater或sheduledExecutorService,但似乎都有同样的问题。我的问题是,如果这是正确的方法,如果使用JLabel方法完成这项任务从一开始就是一个坏主意?如果是这样,那么以平滑可控的方式(有点像视频)一个接一个地显示字符串的好方法。

非常感谢,任何帮助和建议都表示赞赏。

修改

我尝试使用以下代码而不是Iterator,但我不知道这是否更快:

class stringBuffer {
    private ArrayList<String> buf;
    private final int size;
    private int index;

    stringBuffer(ArrayList<String> list){
            buf = list;
            size = buf.size();
    }

    public String getNext(){
            if(index < size){
                return buf.get(index++);
            } else {
                return null;
            }
    }

}

问题仍然存在,所以我试图立即访问该列表

centerLabel.setText(list.get(index++));

但这仍然没有解决问题。

第二次编辑:

这是一个演示问题的可运行示例:

import java.util.ArrayList;
import java.util.Arrays;

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

import java.awt.event.*;
import java.awt.BorderLayout;

class JLabelTest {
    public static void main(String[] args){
        BuildGui gui = new BuildGui();
    }
}

class BuildGui {
    JFrame topLevelFrame;
    JLabel centerLabel;
    JButton startButton;

    BuildGui(){
        initFrame();
        addElements();
        addActionListeners();
    }

    public void initFrame(){
        topLevelFrame = new JFrame("JFrame");
        topLevelFrame.setBounds(200, 200, 400, 200);
        topLevelFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        topLevelFrame.setVisible(true);
    }

    public void addElements(){
        centerLabel = new JLabel("Center");
        startButton = new JButton("Start");

        centerLabel.setHorizontalAlignment(JLabel.CENTER);
        centerLabel.setVerticalAlignment(JLabel.CENTER);

        topLevelFrame.add(startButton, BorderLayout.SOUTH);
        topLevelFrame.add(centerLabel,BorderLayout.CENTER);
    }

    public void addActionListeners(){

        startButton.addActionListener( new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                new setLabel().startTask();
                startButton.setEnabled(false);
            }
        });

    }


    class setLabel {

        private final String[] stringArray =     {"one","two","one","two","one","two","one","two"};//just something to display
        private final int size = stringArray.length;
        private final ArrayList<String> list = new ArrayList<String>(Arrays.asList(stringArray));
        private int index = 0;

        ActionListener task = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
            centerLabel.setText(list.get(index++));
            if(index >= size) index = 0;
            }
        };

        public void startTask(){
            new javax.swing.Timer(300, task).start();
        }

    }

}

第三次编辑

我被告知上一个例子有几个问题。所以我试着解决它们,我希望这个例子更好

import java.util.ArrayList;
import java.util.Arrays;

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

import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.EventQueue;

class JLabelTest2 extends JFrame {
    JLabel centerLabel;
    JButton startButton;

    public static void main(String[] args){
        EventQueue.invokeLater(() -> {
            JLabelTest2 gui = new JLabelTest2();
            gui.setVisible(true);
        });
    }

    JLabelTest2(){
        initUI();
    }

    public void initUI(){
        setBounds(200, 200, 400, 200);

        centerLabel = new JLabel("Center");
        startButton = new JButton("Start");

        centerLabel.setHorizontalAlignment(JLabel.CENTER);
        centerLabel.setVerticalAlignment(JLabel.CENTER);

        getContentPane().add(startButton, BorderLayout.SOUTH);
        getContentPane().add(centerLabel,BorderLayout.CENTER);

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        startButton.addActionListener( new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                new setLabel().startTask();
                startButton.setEnabled(false);
            }
        });

        pack();

    }

    class setLabel {

        private final String[] stringArray = {"one","two","one","two","one","two","one","two"};
        private final int size = stringArray.length;
        private final ArrayList<String> list = new ArrayList<String>(Arrays.asList(stringArray));
        private int index = 0;

        ActionListener task = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                centerLabel.setText(list.get(index++));
                if(index >= size) index = 0;
            }
        };

        public void startTask(){
            new javax.swing.Timer(300, task).start();
        }

    }

}

但不知怎的,我的机器上仍然存在问题。我没有运行很多,即使我关闭所有正在运行的程序,问题也不会改变。在我看不到的代码中是否还有一些问题?

第4次修改

添加centerLabel.repaint()并未更改行为。我仍然看到标签发生变化但频率不稳定。环境信息:

操作系统:Ubuntu 14.04 LTS,64位

处理器:Intel Core™i5-2430M CPU @ 2.40GHz×4

记忆:5,7 GiB

Java信息:

java版“1.8.0_102”

Java(TM)SE运行时环境(版本1.8.0_102-b14)

Java HotSpot(TM)64位服务器VM(版本25.102-b14,混合模式)

0 个答案:

没有答案