简体   繁体   English

JProgressBar不可见,直到被告知显示

[英]JProgressBar not visible until told to show

I'm trying to make an application which shows a JProgressBar only while it is performing actions. 我正在尝试制作仅在执行动作时显示JProgressBar的应用程序。 My problem is, when the program is first opened, I set the JProgressBar visibility to false , then to true when an action is being performed and after it is done, back to false . 我的问题是,当程序第一次开了,我设置JProgressBar知名度false ,然后到true当被执行的动作,并完成后,返回false It seems like it would work, and it does, just not when I make it not visible by default. 看起来它会工作,而且会工作,只是当我默认情况下不使它不可见时。 If the visibility is true by default then it works well, but that's not quite what I want. 如果默认情况下可见性为true ,那么它将正常工作,但这并不是我想要的。 How could I make it so that it isn't visible until I set it to be visible? 我如何才能使它在设置为可见之前不可见?

SSCCE just incase my question wasn't clear enough: 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;
    }

}

Ignore the name, I was listening to that song while creating this. 忽略名称,我在创建歌曲时正在听那首歌。 :) :)

This is probably not the way it should be designed , but this code fixes the problem while still using the natural size ( pack() ) needed to display the button and progress bar. 这可能不是应该设计的方式,但是此代码解决了问题,同时仍使用显示按钮和进度条所需的自然大小( pack() )。 This is achieved by setting the progress bar to invisible after pack is called, but before setting the GUI visible. 这是通过调用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;
    }
}

any events in your case (from Runnable#Thread ) doesn't invoke EventDispashThread you have to wrapp that into invokeLater , otherwise since JProgressBar will be visible but after long running taks ended shouldn't be hidden 您遇到的任何事件(来自Runnable#Thread )都不会调用EventDispashThread您必须将其包装到invokeLater ,否则由于JProgressBar是可见的,但是在长时间运行的任务结束后不应隐藏

1) all changes to the GUI must be done on EDT 1)对GUI的所有更改都必须在EDT上完成

2) you can invoke EDV from Swing's Listeners , SwingWorker 's methods process and done and invoke changes to the GUI by using invokeLate r (in special cases invokeAndWait ) 2)您可以从Swing的ListenersSwingWorker的方法process done并调用EDV,并通过使用invokeLate r(在特殊情况下invokeAndWait )来调用对GUI的更改。

3) Runnable#Thread by default doesn't invoke Swing's Methods nor EDT, there must be output to the GUI wrapped into invokeLater (in special cases invokeAndWait ), more in the Concurency in Swing , inc. 3)默认情况下, Runnable#Thread不会调用Swing的方法或EDT,必须将输出包装到invokeLater (在特殊情况下为invokeAndWait )的GUI中输出,更多内容请参见Scur ,Inc.中的Concurency thread safe methods as are setText() , append() etc. 线程安全方法,如setText()append()等。

In your thread call the progressBar.setVisible(true); 在您的线程中调用progressBar.setVisible(true); inside SwingUtilities.invokeAndWait() . SwingUtilities.invokeAndWait()

The code you have posted works perfectly well. 您发布的代码效果很好。 The problem is when you call frame.pack() , the frame resizes to fit all visible component. 问题是当您调用frame.pack() ,框架将调整大小以适合所有可见组件。 When you have progressBar visibility set to false, the frame ignores this component and sizes accordingly. progressBar可见性设置为false时,框架将忽略此组件并相应调整大小。 So when progressBar.setVisible(true) is called later, the component is shown but the frame is not big enough for you to see the component. 因此,当稍后调用progressBar.setVisible(true) ,将显示该组件,但是边框不够大,无法看到该组件。 If you just drag and increase the size of the frame, you can see the progressBar 如果只是拖动并增加框架的大小,则可以看到progressBar

I suggest that you provide explicit frame size like frame.setSize(200,400) and dont call frame.pack() . 我建议您提供显式的帧大小,例如frame.setSize(200,400) ,不要调用frame.pack()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM