Hallo, ich habe ein Programm, das Daten von einem Server herunter läd und verarbeitet. Diese beiden Vorgänge erzeugen Logeinträge, die verschiedenfarbig in einem Fenster angezeigt werden. Da der gesammte Prozess biszu 10min dauern kann, wird eine Progressbar angezeigt, damit der User weiß, dass das Programm noch läuft. Es gibt jeweils eine Klasse für den Download, das LogWindow und die Progressbar. Jede Klasse wird vom Main Programm als eingenständiger Thread gestartet. Das klappt auch alles sehr gut, jedoch wird am Ende der Inhalt des LogWindows fast immer gelöscht bzw. übermahlt. Ich komme einfach nicht dahinter, wiso das so ist. Ich hoffe jemand kann mir helfen. Zu Testzwecken habe ich das Programm stark verkürzt und den Download-Teil durch einen einfachen Counter ersetzt. Hier der Code:
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import java.math.BigInteger;
import info.clearthought.layout.TableLayout;
// Calculate the power of 0 too 1000 and show the result of every step in a log window.
// While the calculation is running, a progress bar is shown in an additional window.
public class LogWindowTest
{
private static myProgressBar tProgress; // A progress bar
private static counter tCounter; // A counter, to waste some time
private static LogWindow lw; // Shows the log in a window
// For alternately changing the color of a log entry
private static boolean lastEntryWasBlack = false;
public static void main( String args[] ) throws Exception
{
newRun(); // Do a run on program start
}
// Create and start the threads
public static void newRun()
{
// Create new progress bar
tProgress = new myProgressBar();
// Create new counter thread
tCounter = new counter();
tCounter.setMax(1000);
// Create and start new log window
lw = new LogWindow();
lw.setData();
lw.start();
lw.showWindow();
// Start the progress bar and the counter thread
tProgress.start();
tCounter.start();
System.out.println("New run started...");
}
// Stop the counter thread
public static void stopCounter()
{
tCounter.brake();
}
public static void stopProgressBar()
{
tProgress.close();
}
// Refresh the log window
public static void refreshWin()
{
lw.refreshWindow();
}
// Reduce BigInteger b to a maximum of 10 digits
// & add it to the log
public static void addToLog(BigInteger b, int x)
{
String bAsString="";
// Reduce BigInteger b to a maximum of 10 digits
if (b.bitLength() > 10 )
{
byte[] bArray = b.toByteArray();
int max = bArray.length;
if (max > 10){
max = 10;
}
for (int i=0; i<max; i++)
{
bAsString = bAsString + bArray[i];
}
bAsString = bAsString + "...";
}
else{
bAsString = b.toString();
}
// Create output text
String text = ( x + "^" + x + " = " + bAsString );
// Add text to log, alternately in black or blue
if (lastEntryWasBlack){
lw.newLogListEntry(text, Color.BLUE);
lastEntryWasBlack = false;
}
else{
lw.newLogListEntry(text, Color.BLACK);
lastEntryWasBlack = true;
}
}
}
// Creates a window (JFrame) and add a progress bar to it.
class myProgressBar extends Thread implements ActionListener
{
private JProgressBar progressBar;
private JLabel label = new JLabel ("Download process:");
private JButton btnCancel = new JButton("Cancel");
private JFrame frame = new JFrame();
// The main method, that creates the frame for the progress bar
public void run()
{
// set title and add action listener for the button
frame.setTitle("Loading System Dump. Please wait...");
this.btnCancel.addActionListener(this);
// Set the TableLayout for the frame
double size[][] =
{{ 0.04, TableLayout.FILL, TableLayout.FILL, TableLayout.FILL, 0.04,}, // 5 columns
{ 0.04, TableLayout.FILL, 0.04, TableLayout.FILL, 0.04, TableLayout.FILL, 0.04 } }; // 7 rows
frame.setLayout (new TableLayout(size));
// set icon and screen size
frame.setSize(350, 100);
// Create the progress bar
this.progressBar = new JProgressBar();
// the progress bar is always running from left to right and back
this.progressBar.setIndeterminate(true);
this.progressBar.setSize(100, 50);
// add all elements to the frame
frame.add(label, "1, 1, 3, 1");
frame.add(progressBar, "1, 3, 3, 1" );
frame.add(btnCancel, "2, 5, 1, 1");
// set screen position and show the frame
frame.setLocation(150, 150);
frame.setVisible(true);
}
// Close the update progress bar
public void close()
{
System.out.println("... run completed");
frame.dispose();
}
// If button 'cancel' gets pushed: call 'close()'
public void actionPerformed(ActionEvent arg0)
{
close();
LogWindowTest.stopCounter();
}
}
// The counter thread, that waist the time and create the output
class counter extends Thread
{
private myProgressBar p = null;
private int max = 0;
private boolean boBrake = false;
// Set the maximum
public void setMax(int newMax){
max = newMax;
}
// Calculation
public void run()
{
int i=0;
while ( i<max && !boBrake ){
BigInteger a = BigInteger.valueOf(i).pow(i);
LogWindowTest.addToLog(a, i); // add to log
i++;
}
LogWindowTest.refreshWin();
}
// Stop the calculation (caused by the cancel button of the progress bar)
public void brake()
{
boBrake = true;
}
// Stop/close the progress bar
public void stopProgBar()
{
LogWindowTest.stopProgressBar();
}
}
// The window, that show the update progress
class LogWindow extends Thread
{
private JList logList;
private JMenuItem jmiEnde, jmiNewRun;
private Listener al;
private Container lfwContainer;
private JPanel panlogListe;
private JFrame fLog;
private DefaultListModel model;
private LogListEntry entry;
// Prepare the needed elements
public void setData()
{
logList = new JList();
al = new Listener();
fLog = new JFrame();
model = new DefaultListModel();
}
// create a new window on start()
public void run(){
createWindow();
}
// Create a new window
public void createWindow(){
// Create a new JList & add 'model'
logList.setModel(model); // 'model' contains the log data
logList.setCellRenderer( new LogListCellRenderer() );
lfwContainer = fLog.getContentPane(); // get the container of fLog
lfwContainer.add(logList);
// Create new JPanel AND add the List
panlogListe = new JPanel( new BorderLayout() );
panlogListe.add(new JScrollPane(logList), BorderLayout.CENTER);
// Creates MenuBar, Menu AND Menu-Items
JMenuBar jmb = new JMenuBar();
JMenu jmFile = new JMenu("File");
jmiEnde = new JMenuItem("Close");
jmiNewRun = new JMenuItem("New run");
// Add action-listener to Menu-Items
jmiEnde.addActionListener(al);
jmiNewRun.addActionListener(al);
// Add every thing to MenuBar
jmFile.add(jmiNewRun);
jmFile.addSeparator();
jmFile.add(jmiEnde);
jmb.add(jmFile);
// Add every thing to window and set the properties
fLog.setJMenuBar(jmb);
fLog.setTitle("Update Status");
fLog.add(panlogListe);
fLog.setLocation(520, 120);
fLog.setSize(500, 600);
}
// Show the window (visibility is set to true)
public void showWindow()
{
fLog.setVisible(true);
}
// Close the window
public void closeWindow()
{
fLog.dispose();
}
// Refresh the window
public void refreshWindow()
{
fLog.repaint();
fLog.validate();
}
// Creates a new log entry, that will have the content 'text'
// and will be shown in color 'col'
public void newLogListEntry(String text, Color col)
{
entry = new LogListEntry(text, col);
model.addElement(entry);
}
// ActionListener for Menu-Items 'New run' & 'End'
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == jmiNewRun)
{
fLog.dispose(); // Close the log window
createWindow(); // Create a new one
LogWindowTest.newRun(); // Start a new run
}
if (e.getSource() == jmiEnde) // Exit the program
{
fLog.dispose();
}
}
}
// Definition of object: 'LogListEntry'
// to create use: LogListEntry(String content, Color fontcolor)
public class LogListEntry {
private String content;
private Color fontcolor;
public LogListEntry(String content, Color fontcolor){
this.content = content;
this.fontcolor = fontcolor;
}
public String getContent()
{
return content;
}
public void setContent(String content)
{
this.content = content;
}
public Color getFontcolor()
{
return fontcolor;
}
public void setFontcolor(Color fontcolor)
{
this.fontcolor = fontcolor;
}
}
// Change some features of ListCellRenderer for a better color-handling in the log-output
public class LogListCellRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 1977L;
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
// Cast a LogListValue as LogFileWindow.LogListEntry
LogListEntry entry = (LogListEntry) value;
// set text to entry-content
this.setText(entry.getContent());
// Activate 'this.setBackground'
this.setOpaque(true);
// If List-Item is Selected:
if(isSelected){
// Font-Color
this.setForeground(Color.MAGENTA);
// Background-Color
this.setBackground(Color.LIGHT_GRAY);
}
// If List-Item is NOT Selected:
else{
// Font-Color
this.setForeground(entry.getFontcolor());
// Background-Color
this.setBackground(UIManager.getColor("logList.background"));
}
// Return this Label
return this;
}
}
}