我尝试过以下教程,但我一直迷路。
我需要的是一个创建并显示进度条(JProgressBar
)的类,我可以设置值,当我迭代从文件加载的数据并放入数据库内存时。我遇到的问题是,我发现的每个例子都有某种计数器,它填充进度条并从“主”函数执行。每当我改变该教程成为一个我可以随意调用的类并显示条形图时,我都没有显示条形图(IE框架出现但是条形图甚至看起来都没有被添加到框架中,直到之后迭代完成)。
我尝试使用SwingUtilities.invokeLater
和SwingWorker
(下面的课程中的最新尝试)都有同样的问题。更糟糕的是,我可以执行dbug.myMessage
(基本上发送到System.out
)并看到一条消息,显示内存中的条形图正在变化而未显示。我显然遗漏了一些可能很简单的东西,但我想不出它是什么。
另外一件事,如果我将教程保留为Java Tutorials Code Sample – ProgressBarDemo2.java,只需将main更改为createAndShow方法,它就可以正常工作,但当然它并不能满足我的需要。
我确实发布了另一个关于此的问题,但我已经改变了这个课程,我认为最好发一个新问题。
所以,这是我改变的代码似乎不起作用:
public class MyProgressBar extends JPanel implements PropertyChangeListener,
MyData,
Serializable {
/**
*
*/
private static final long serialVersionUID = -1632492668549544408L;
private MyDebug dbug = new MyDebug( MyData.MYDEBUGCHECK.MYPROGRESSBAR.getOn() );
public static final int MAX = 100;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar myBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame myFrame = new JFrame();
public Task task;
class Task extends SwingWorker<Void, Void> {
public int myValue = 0;
@Override
public Void doInBackground() {
//Initialize progress property.
setProgress(0);
while (myValue < 100) {
//Make random progress.
//myValue += random.nextInt(10);
setProgress( Math.min( myValue, 100 ) );
dbug.myMessage( "MYPROGRESSBAR", "doInBackground", "Value is %3.2f %d", myBar.getPercentComplete(), myValue );
myBar.repaint();
}
return null;
}
public void done() {
}
public void mySetValue( int percent ) {
myValue = (int)( MAX * ( (double)percent / 100.0 ) );
dbug.myMessage( "MYPROGRESSBAR", "mySetValue", "Value is %3.2f %d percent was %d", myBar.getPercentComplete(), myValue, percent );
}
}
public MyProgressBar() {
add(myBar);
int x = ( MyData.SCREEN.width / 2 ) - ( WIDTH / 2);
int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);
this.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setUndecorated(true);
myFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setVisible(false);
myFrame.getContentPane().setLayout(null);
myFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
myBar.setStringPainted( true );
myBar.setBorderPainted( true );
myBar.setValue( 0 );
myBar.setBounds( 0, 0, WIDTH, HEIGHT );
myBar.addPropertyChangeListener( this );
myFrame.add( myBar );
//Create and set up the content pane.
//JComponent newContentPane = new MyProgressBar();
JComponent newContentPane = myBar;
newContentPane.setOpaque(true); //content panes must be opaque
myFrame.setContentPane(newContentPane);
myFrame.pack();
}
public void createAndShow () {
//Display the window.
myFrame.setVisible(true);
myFrame.repaint();
}
public void hideAndClear () {
//myFrame.setVisible(false);
}
@Override
public void propertyChange(PropertyChangeEvent args) {
dbug.myMessage( "MYPROGRESSBAR", "propertyChange", "Value is %s", args.getPropertyName() );
if ( "progress" == args.getPropertyName() ) {
int progress = (Integer) args.getNewValue();
//myBar.setValue(progress);
}
}
public void start () {
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
}
答案 0 :(得分:3)
您应该调用setProgress
中提供的doInBackGround
方法,而不是在publish
方法中调用SwingWorker
。
publish
方法会将这些值传递给在事件调度线程上调用的process
方法,并且在此方法中您应该更新进度条。
在another question我已经发布了一个完全符合
的例子答案 1 :(得分:2)
以下示例可能对您有用。它假装加载一个大的XML文件,并为每个“重要数据段”添加一个Panel(在这个例子中它实际上只是一个字符串。)GUI通过SwingWorker中的PropertyChangeEvent进行更新。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class WorkerExample
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
WorkerGui gui = new WorkerGui();
JFrame frame = gui.createFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class WorkerGui
{
public static final String ADD_NEW_ROW_PROPERTY = "ADD_NEW_ROW";
private static final Dimension SUB_PANEL_SIZE = new Dimension(350, 50);
private JButton button;
private JComponent labelComponent;
private JScrollPane scroller;
int labelCount = 0;
private List<String> loadXml() {
try {
// pretend to load a large XML file...
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(WorkerGui.class.getName()).log(Level.SEVERE, null, ex);
}
List<String> dataList = new ArrayList<String>();
for (int i = 1; i <= 20; i++) {
dataList.add("Important data " + i);
}
return dataList;
}
ProgressMonitor monitor = null;
class XmlWorker extends SwingWorker<Void, Void> {
@Override protected Void doInBackground() throws Exception {
monitor.setProgress(2);
List<String> rows = loadXml();
final int denom = rows.size();
int i = 1;
Random random = new Random();
for (String string : rows) {
if (monitor.isCanceled()) {
break;
}
Thread.sleep(random.nextInt(2000));
firePropertyChange(ADD_NEW_ROW_PROPERTY, null, string);
setProgress((int)(100 * (i / (double)denom)));
i++;
}
return null;
}
@Override protected void done() {
// restore the button
button.setEnabled(true);
button.requestFocus();
}
}
final PropertyChangeListener listener = new PropertyChangeListener() {
@Override public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
monitor.setProgress((Integer)evt.getNewValue());
} else if (ADD_NEW_ROW_PROPERTY.equals(evt.getPropertyName())) {
addRow((String)evt.getNewValue());
}
}
};
private void doWork() {
monitor = new ProgressMonitor(labelComponent.getTopLevelAncestor(), "Loading XML", "", 0, 100);
monitor.setProgress(0);
monitor.setMillisToPopup(0);
monitor.setMillisToDecideToPopup(0);
XmlWorker worker = new XmlWorker();
worker.addPropertyChangeListener(listener);
worker.execute();
}
private JComponent setupGui() {
labelComponent = Box.createVerticalBox();
scroller = new JScrollPane(labelComponent,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel buttonPanel = new JPanel();
button = new JButton("Do it!");
buttonPanel.add(button);
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
clear();
doWork();
}
});
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(scroller, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
return mainPanel;
}
public JFrame createFrame() {
JFrame frame = new JFrame("Hello!");
frame.setSize(400, 400);
JComponent component = setupGui();
frame.add(component);
return frame;
}
public void clear() {
labelComponent.removeAll();
labelCount = 0;
scroller.validate();
scroller.getTopLevelAncestor().repaint();
}
/**
* Creates a JLabel out of the data and adds it to the main panel.
* Must be called on Event Dispatch Thread!!
* @param data the data to add, could be any class.
*/
public void addRow(String data) {
if (labelCount > 0) {
labelComponent.add(Box.createVerticalStrut(10));
}
labelCount++;
final JLabel label = new JLabel(data);
JPanel panel = new JPanel();
panel.add(label);
panel.setPreferredSize(SUB_PANEL_SIZE);
panel.setMaximumSize(SUB_PANEL_SIZE);
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
labelComponent.add(panel);
scroller.validate();
panel.scrollRectToVisible(panel.getBounds());
}
}
答案 2 :(得分:0)
我确实让这个工作正在发布,以防万一有人碰巧在这一步上搜索并需要工作代码。
package com.swa.fin.esaa.sgb.myclasses.myzzarchives;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
public class MyProgressBarTest {
public class MyProgressBar extends JPanel implements PropertyChangeListener,
Serializable {
private static final long serialVersionUID = -1632492668549544408L;
public static final int MAX = 100;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar myBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame myFrame = new JFrame();
public Task task;
class Task extends SwingWorker<Void, Integer> {
public int myValue = 0;
@Override
public Void doInBackground() {
//Initialize progress property.
setProgress(0);
myBar.setValue( myValue );
myBar.repaint();
return null;
}
public void done() {
}
public void mySetValue( int percent ) {
myValue = (int)( MAX * ( (double)percent / 100.0 ) );
setProgress( Math.min( myValue, 100 ) );
myBar.repaint();
}
}
public MyProgressBar() {
add(myBar);
myFrame.setUndecorated(false);
myFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setVisible(false);
myFrame.getContentPane().setLayout(null);
myFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
myBar.setStringPainted( true );
myBar.setBorderPainted( true );
myBar.setValue( 0 );
myBar.setBounds( 0, 0, WIDTH, HEIGHT );
myBar.addPropertyChangeListener( this );
myFrame.add( myBar );
//Create and set up the content pane.
//JComponent newContentPane = new MyProgressBar();
JComponent newContentPane = myBar;
newContentPane.setOpaque(true); //content panes must be opaque
myFrame.setContentPane(newContentPane);
myFrame.pack();
}
public void createAndShow () {
//Display the window.
myFrame.setVisible(true);
myFrame.repaint();
}
public void hideAndClear () {
//myFrame.setVisible(false);
}
@Override
public void propertyChange(PropertyChangeEvent args) {
if ( "progress" == args.getPropertyName() ) {
int progress = (Integer) args.getNewValue();
myBar.setValue(progress);
}
}
public void mySetValue( int percent ) {
if ( task != null ) {
task.mySetValue( percent );
}
myBar.repaint();
}
public void start () {
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
}
public class Tester {
public Tester() {
}
public void testit () {
MyProgressBar bar = new MyProgressBar();
bar.createAndShow();
bar.start();
bar.mySetValue( 0 );
try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); }
bar.mySetValue( 10 );
try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); }
bar.mySetValue( 20 );
try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); }
for ( int count = 20; count <= 100; count++ ) {
bar.mySetValue( count );
try { Thread.sleep( 100 ); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
public static void main ( String[] args ) {
MyProgressBarTest my = new MyProgressBarTest();
MyProgressBarTest.Tester test = my.new Tester();
test.testit();
}
}
但是如果我接受并从类中调用它来读取XML文件,解组它然后遍历加载的ArrayList并创建放置在JPanel上的JLabel它不会更新任何图形(其中任何一个)在所有的情况下)直到班级完全完成了它正在做的事情,尽管重新制作和东西。
对此有何看法?