1

我正在尝试制作一个JProgressBar仅在执行操作时才显示的应用程序。我的问题是,当程序第一次打开时,我将JProgressBar可见性设置为false,然后true在执行操作时设置为,完成后返回到false。看起来它会起作用,而且它确实起作用,只是当我默认使它不可见时。如果true默认情况下可见性,那么它运行良好,但这不是我想要的。我怎样才能使它不可见,直到我将它设置为可见?

SSCCE 只是以防我的问题不够清楚:

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class SmileBack {

    private JFrame frame;

    private JPanel panel, container;

    private JButton loadButton;

    private JProgressBar progressBar;

    public static void main(String[] arguments) {
        new SmileBack().constructFrame();
    }

    public void constructFrame() {
        frame = new JFrame("RSTracker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(getContentPane());
        frame.pack();
        frame.setVisible(true);
    }

    public JPanel getContentPane() {
        panel = new JPanel(new BorderLayout());

        progressBar = new JProgressBar();
        progressBar.setIndeterminate(true);
        //progressBar.setVisible(false); // doesn't work when this is uncommented

        loadButton = new JButton("Load memberlist");
        loadButton.setEnabled(true);
        loadButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        progressBar.setVisible(true);
                        // do my stuff here...
                        try {
                            Thread.sleep(2000); // just for the sake of example
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        progressBar.setVisible(false);
                    }

                }).start();
            }

        });

        container = new JPanel(new FlowLayout());
        container.add(loadButton);
        container.add(progressBar);

        panel.add(container);

        return panel;
    }

}

忽略名字,我在创作时正在听那首歌。:)

4

4 回答 4

2

这可能不是它应该设计的方式,但是这段代码解决了这个问题,同时仍然使用pack()显示按钮和进度条所需的自然大小 ()。这是通过在调用 pack之后,但设置 GUI 可见之前将进度条设置为不可见来实现的。

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class SmileBack {

    private JFrame frame;

    private JPanel panel, container;

    private JButton loadButton;

    private JProgressBar progressBar;

    public static void main(String[] arguments) {
        new SmileBack().constructFrame();
    }

    public void constructFrame() {
        frame = new JFrame("RSTracker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(getContentPane());
        // after this, everything is instantiated;
        frame.pack();
        setProgressBarVisibility(false);
        frame.setVisible(true);
    }

    public void setProgressBarVisibility(boolean visible) {
        progressBar.setVisible(visible);
    }

    public JPanel getContentPane() {
        panel = new JPanel(new BorderLayout());

        progressBar = new JProgressBar();
        progressBar.setIndeterminate(true);

        loadButton = new JButton("Load memberlist");
        loadButton.setEnabled(true);
        loadButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        progressBar.setVisible(true);
                        // do my stuff here...
                        try {
                            Thread.sleep(2000); // just for the sake of example
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        progressBar.setVisible(false);
                    }

                }).start();
            }

        });

        container = new JPanel(new FlowLayout());
        container.add(loadButton);
        container.add(progressBar);

        panel.add(container);

        return panel;
    }
}
于 2012-01-11T06:22:35.650 回答
2

您的情况下的任何事件(from )都 Runnable#Thread不会调用EventDispashThread您必须将其包装成invokeLaterJProgressBar

1) 对 GUI 的所有更改都必须在 EDT 上完成

2) 您可以从Swing 的 ListenersSwingWorker的方法调用 EDV ,process并使用rdone调用对 GUI 的更改(在特殊情况下)invokeLateinvokeAndWait

3)Runnable#Thread默认情况下不调用 Swing 的方法或 EDT,必须有输出到 GUI 包装到invokeLater(在特殊情况下invokeAndWait),更多在Swing 中的 Concurency , inc。线程安全的方法setText()append()等等。

于 2012-01-11T07:11:12.580 回答
1

在你的线程调用progressBar.setVisible(true);里面SwingUtilities.invokeAndWait()

于 2012-01-11T06:09:10.573 回答
0

您发布的代码运行良好。问题是当您调用时frame.pack(),框架会调整大小以适合所有可见组件。当您将progressBar可见性设置为 false 时,框架会忽略此组件并相应地调整大小。因此, progressBar.setVisible(true)稍后调用时,会显示组件,但框架不够大,您无法看到组件。如果你只是拖动并增加框架的大小,你可以看到progressBar

我建议您提供明确的帧大小,例如frame.setSize(200,400)并且不要调用frame.pack().

于 2012-01-11T06:08:57.113 回答