JProgressBar 在被告知显示之前不可见
我正在尝试创建一个仅在执行操作时显示 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;
}
}
忽略这个名字,我在创作这首歌时正在听那首歌。 :)
I'm trying to make an application which shows a JProgressBar
only while it is performing actions. 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
. 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. 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:
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. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可能不是它应该的设计方式,但此代码修复了问题,同时仍然使用显示按钮和进度栏所需的自然大小 (
pack()
) 。这是通过在调用 pack 之后、但在将 GUI 设置为可见之前将进度条设置为不可见来实现的。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. This is achieved by setting the progress bar to invisible after pack is called, but before setting the GUI visible.您的情况下的任何事件(来自
Runnable#Thread
)都不会调用EventDispashThread
,您必须将其包装到invokeLater
中,否则自JProgressBar
将可见,但在长时间运行任务结束后不应隐藏1) 对 GUI 的所有更改都必须在 EDT 上完成
2) 您可以从 Swing 的监听器,
SwingWorker
的方法 < code>process 和done
并使用invokeLate
r 调用对 GUI 的更改(在特殊情况下invokeAndWait
)3)
Runnable#Thread
默认情况下不会调用 Swing 的方法,也不会调用 EDT,必须有封装到invokeLater
中的 GUI 输出(在特殊情况下invokeAndWait
),更多内容请参见 Swing 中的并发性,公司线程安全方法有setText()
、append()
等。any events in your case (from
Runnable#Thread
) doesn't invokeEventDispashThread
you have to wrapp that intoinvokeLater
, otherwise sinceJProgressBar
will be visible but after long running taks ended shouldn't be hidden1) all changes to the GUI must be done on EDT
2) you can invoke EDV from Swing's Listeners,
SwingWorker
's methodsprocess
anddone
and invoke changes to the GUI by usinginvokeLate
r (in special casesinvokeAndWait
)3)
Runnable#Thread
by default doesn't invoke Swing's Methods nor EDT, there must be output to the GUI wrapped intoinvokeLater
(in special casesinvokeAndWait
), more in the Concurency in Swing, inc. thread safe methods as aresetText()
,append()
etc.在线程中调用
SwingUtilities.invokeAndWait()
内的progressBar.setVisible(true);
。In your thread call the
progressBar.setVisible(true);
insideSwingUtilities.invokeAndWait()
.您发布的代码运行良好。问题是当您调用frame.pack()时,框架会调整大小以适合所有可见组件。当您将
progressBar
可见性设置为 false 时,框架会忽略此组件并相应调整大小。因此,当稍后调用progressBar.setVisible(true)
时,会显示该组件,但框架不够大,您无法看到该组件。如果您只是拖动并增加框架的大小,您可以看到progressBar
我建议您提供明确的框架大小,如
frame.setSize(200,400)
并且不要调用 <代码>frame.pack()。The code you have posted works perfectly well. The problem is when you call
frame.pack()
, the frame resizes to fit all visible component. When you haveprogressBar
visibility set to false, the frame ignores this component and sizes accordingly. So whenprogressBar.setVisible(true)
is called later, the component is shown but the frame is not big enough for you to see the component. If you just drag and increase the size of the frame, you can see theprogressBar
I suggest that you provide explicit frame size like
frame.setSize(200,400)
and dont callframe.pack()
.