[英]JComponent.revalidate() doesn't update until code finishes
**Hello, I'm trying to create an archiver in java. **您好,我正在尝试用Java创建一个存档器。 This means that I am constantly reading and writing from streams.
这意味着我一直在从流中读取和写入。 I want to be able to update a JProgressBar to show how much I have written.
我希望能够更新JProgressBar以显示我写了多少。 My code currently updates the progress bar after each entry in the archive.
我的代码当前在归档中的每个条目之后都会更新进度栏。 My variables and everything say that the code is updated, except its not showing on the screen.
我的变量和所有内容都表明代码已更新,但未在屏幕上显示。 After each entry into the archive I call the revalidate() method on the JPanel that contains the progress bar and text, but nothing happens on the screen.
每次进入存档后,我都在JPanel上调用revalidate()方法,该方法包含进度条和文本,但是屏幕上没有任何反应。 The screen doesn't update until the output stream that is writing the archive has completely finished writing.
在写入归档文件的输出流完全完成写入之前,屏幕不会更新。 Then, I see the full progress bar with "24 out of 24 files written" in the progress text.
然后,我在进度文本中看到完整的进度条,其中显示“已写入24个文件中的24个”。
Can anyone tell me how I can get the graphics to update before my code finished executing? 谁能告诉我如何在代码执行完毕之前更新图形? Thanx
谢谢
Here is my code: 这是我的代码:
WritingBox.java: WritingBox.java:
package org.apache.commons.compress;
import javax.swing.JDialog;
public class WritingBox extends javax.swing.JDialog {
/** Creates new form WritingBox */
public WritingBox(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
theprogressbar.setMaximum(1);
theprogressbar.setMinimum(0);
this.setLocation(parent.getLocationOnScreen().x+(parent.getWidth()-this.getWidth())/2, parent.getLocationOnScreen().y+(parent.getHeight()-this.getHeight())/2);
this.setVisible(true);
}
public void progressListener(Progress p) {
writtenxoutofx.setText("Written "+Integer.toString(p.doneSoFar)+" out of "+Integer.toString(p.total)+" files to the Archive");
theprogressbar.setValue(p.doneSoFar/p.total);
if (p.doneSoFar == p.total) this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
thecontainer.revalidate();
};
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
thecontainer = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
writtenxoutofx = new javax.swing.JLabel();
theprogressbar = new javax.swing.JProgressBar();
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setName("Form"); // NOI18N
thecontainer.setName("thecontainer"); // NOI18N
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(targzipmanager.TarGzipManagerApp.class).getContext().getResourceMap(WritingBox.class);
jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
jLabel1.setName("jLabel1"); // NOI18N
writtenxoutofx.setText(resourceMap.getString("writtenxoutofx.text")); // NOI18N
writtenxoutofx.setName("writtenxoutofx"); // NOI18N
theprogressbar.setName("theprogressbar"); // NOI18N
javax.swing.GroupLayout thecontainerLayout = new javax.swing.GroupLayout(thecontainer);
thecontainer.setLayout(thecontainerLayout);
thecontainerLayout.setHorizontalGroup(
thecontainerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(thecontainerLayout.createSequentialGroup()
.addContainerGap()
.addGroup(thecontainerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(theprogressbar, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE)
.addComponent(jLabel1)
.addComponent(writtenxoutofx))
.addContainerGap())
);
thecontainerLayout.setVerticalGroup(
thecontainerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(thecontainerLayout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(writtenxoutofx)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(theprogressbar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(thecontainer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(thecontainer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel thecontainer;
private javax.swing.JProgressBar theprogressbar;
private javax.swing.JLabel writtenxoutofx;
// End of variables declaration
}
Progress.java Progress.java
package org.apache.commons.compress;
public class Progress { //This is basically a Struct
public int total;
public int doneSoFar;
private Progress (){
}
public Progress(int d, int t){
total = t;
doneSoFar = t;
}
}
TarArchive.java: doSave method TarArchive.java:doSave方法
public void doSave(OutputStream output) throws ArchiveException {
// Stream initializing
//BufferedInputStream origin = null;
//out.setMethod(ZipOutputStream.DEFLATED);
//byte data[] = new byte[BUFFER];
// get a list of files from current directory
// less than one file leads to an exception
Iterator iterator = this.getEntryIterator();
if(!iterator.hasNext()) {
throw new ArchiveException("There must be at least one file to be pack.");
}
JFrame jf = targzipmanager.TarGzipManagerApp.getApplication().getMainFrame();
WritingBox wb = new WritingBox(jf, false);
TarOutputStream out = null;
int x = 0;
try {
out = new TarOutputStream(new BufferedOutputStream(output));
while(iterator.hasNext()) {
x++;
ArchiveEntry archiveEntry = (ArchiveEntry)iterator.next();
InputStream fInputStream = archiveEntry.getStream();
TarEntry entry = new TarEntry(archiveEntry.getName());
entry.setModTime( 0 );
entry.setSize( fInputStream.available() );
entry.setUserID( 0 );
entry.setGroupID( 0 );
entry.setUserName( "avalon" );
entry.setGroupName( "excalibur" );
entry.setMode( 0100000 );
out.putNextEntry( entry );
out.copyEntryContents( fInputStream );
out.closeEntry();
wb.progressListener(new Progress(x, entries.size()));
}
} catch (IOException e) {
throw new ArchiveException("Creation of this archive failed cause of IOExceptions.", e);
} finally {
try {
out.close();
} catch (IOException e1) {
throw new ArchiveException("Creation of this archive failed cause of IOExceptions.", e1);
}
}
}
Can anyone help me? 谁能帮我? Even though I'm calling revalidate() after each entry, it only updates when the code stops and it starts waiting.
即使我在每个条目之后都调用revalidate(),它仅在代码停止并开始等待时才更新。 **
**
Sounds like you are doing the file I/O on the AWT Event Dispatch Thread (EDT). 听起来您正在执行AWT事件调度线程(EDT)上的文件I / O。 This blocks any repaints or event handling.
这会阻止所有重绘或事件处理。 Run the I/O on a different thread, and update the GUI through
java.awt.EventQueue.invokeLater
. 在其他线程上运行I / O,并通过
java.awt.EventQueue.invokeLater
更新GUI。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.