GUI-Aktualisierungs-Probleme

jf

Bekanntes Mitglied
Hallo, ich möchte an dieser Stelle nochmal eine Ergänzung zu meiner alten Diskussion starten, da diese aufgrund der Länge eingeschlafen ist.

Es geht dabei darum, dass die Fortschrittsanzeige nicht durchgehen und kontinuierlich aktualisiert wird, sobald parallel sehr viele Elemente in eine JList geschrieben werden. Mich interessieren an dieser Stelle die Hintergründe dafür und ob es evtl. Techniken gibt, welche meiner Herangehensweise überlegen sind.

Ein weiteres Problem ist, dass das ganze Haupt-Fenster während des Ladevorgangs nicht aktualsiert wird, wenn ich zuvor einen Dialog öffne. Sicherlich ist mir hier ein Konzept-Fehler unterlaufen - ich würde gerne erfahren, wie man das richtig löst.

Ich habe meine Anwendung mal zu einer Demo abgespeckt, welche diese beiden Probleme aufzeigt:
Java:
package progress_bar;


import javax.swing.*;

import common.ui.files.FileDrop;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.*;


@SuppressWarnings("serial")
public class Demo extends JFrame {
    
	// singleton variable
	private static Demo m_instance;
    
	private JTabbedPane  m_TabsPane    = null;
    private JProgressBar m_progress    = null;
    private KeyListener  m_keyListener = null;
    
    private static final String APP_TITLE = "Demo";
    private final int DEF_WIDTH           = 800;
    private final int DEF_HEIGHT          = 600;


    // constructor
    public Demo() {
    	
        //-----------------------------------------------------------------------------
        // Creating the tabbed pane
        m_TabsPane = new JTabbedPane();
        
        // Creating the progress bar
        m_progress = new JProgressBar();
        m_progress.setVisible(false);
        
		// Adding the TabRowJacket
        this.getContentPane().setLayout(new BorderLayout());
		this.getContentPane().add(m_TabsPane, BorderLayout.CENTER);
		this.getContentPane().add(m_progress, BorderLayout.SOUTH);
        //-----------------------------------------------------------------------------
		
		// define hot keys
		m_TabsPane.addKeyListener( getArrowKeyListener() );
        
		// for drag'n'drop feature
        new FileDrop(this, new FileDrop.Listener() {
			public void filesDropped(final File[] files) {
				if(files.length > 1) {
					String msg = "Hey du Workaholic!\n=> Immer schön eins nach dem anderen... ;)";
					JOptionPane.showMessageDialog(Demo.this, msg);
				} else {
					Thread openFileThread = new Thread(new Runnable() {
						@Override
						public void run() {
							checkFile(files[0]);
						}
					});
					openFileThread.start();
				}
			}
        });
        
        // window should be centered on the primary monitor
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        int posX = (int)(dim.getWidth()-DEF_WIDTH) / 2;
        int posY = (int)(dim.getHeight()-DEF_HEIGHT) / 2;
        
        this.setSize(DEF_WIDTH, DEF_HEIGHT);
        this.setLocation(posX, posY);

        // defining close operation
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

	public KeyListener getArrowKeyListener() {
		if(m_keyListener == null) {
			m_keyListener = new KeyListener() {
				@Override public void keyTyped(KeyEvent ev) {}
				@Override public void keyReleased(KeyEvent ev) {}
				@Override
				public void keyPressed(KeyEvent ev) {
					switch(ev.getKeyCode()) {
						case KeyEvent.VK_LEFT:	Demo.this.prevTab();
						case KeyEvent.VK_RIGHT:	Demo.this.nextTab();
					}
				}
			};
		}
		return m_keyListener;
	}

	
    //========================================================================================

	
	// previous tab
	public void prevTab() {
		int index = m_TabsPane.getSelectedIndex();
		
		if(index > 0) {
			m_TabsPane.setSelectedIndex(index-1);
		}
	}
	
	// next tab
	public void nextTab() {
		int index = m_TabsPane.getSelectedIndex();
		
		if(index < m_TabsPane.getTabCount()-1) {
			m_TabsPane.setSelectedIndex(index);
		}
	}
	
	// loading file
    private void loadFile(File logFile) {
		if(logFile != null) {
			this.setTitle( APP_TITLE + ": beim Laden..." );
			final MyList newList = new MyList();
			m_TabsPane.add(logFile.getName(), newList);
			m_TabsPane.setSelectedComponent(newList);
			
			final double factor = (double)logFile.length() / 100;			

			try {
				m_progress.setValue(0);
				m_progress.setVisible(true);
				
				BufferedReader in = new BufferedReader(new FileReader(logFile));
	    		String line       = null;
	    		double percent    = 0;
	    		
	    		while((line = in.readLine()) != null) {
	    			percent += ((line.length() + 2) / factor);
	    			newList.addItem(line);	    	    				
    				m_progress.setValue( (int)percent );
  	 			}
	    		
	    		m_progress.setVisible(false);
			} catch(Exception ex) {
				String msg = "Beim Lesen der Datei ist folgender Fehler aufgetreten:\n" + ex.toString();
				JOptionPane.showMessageDialog(this, msg);
				return;
			}
			
			this.setTitle(APP_TITLE);
		}
    }
    
    private void checkFile(final File logFile) {
		if(logFile != null) {
			int ret = JOptionPane.showOptionDialog(this, "Soll das Fenster angezeigt werden.", "Test", 0, 0, null, null, null);
			
			if(ret == 0) {
				MyWindow win = MyWindow.getInstance();
				win.addComponentListener(new ComponentListener() {
					@Override public void componentMoved(ComponentEvent arg0) {}
					@Override public void componentResized(ComponentEvent arg0) {}
					@Override public void componentShown(ComponentEvent arg0) {}
					@Override
					public void componentHidden(ComponentEvent arg0) {
						loadFile(logFile);
					}
				});
				win.addWindowListener(new WindowListener() {
					@Override public void windowActivated(WindowEvent arg0) {}
					@Override public void windowClosing(WindowEvent arg0) {}
					@Override public void windowDeactivated(WindowEvent arg0) {}
					@Override public void windowDeiconified(WindowEvent arg0) {}
					@Override public void windowIconified(WindowEvent arg0) {}
					@Override public void windowOpened(WindowEvent arg0) {}
					@Override public void windowClosed(WindowEvent arg0) {
						loadFile(logFile);
					}
				});
				win.setVisible(true);
			} else {
				loadFile(logFile);
			}
		}
    }   

    //========================================================================================

    
    // singleton
    public static Demo getInstance() {
    	if(m_instance == null) {
    		m_instance = new Demo();
    	}
    	return m_instance;
    }
    
    // main routine
    public static void main(final String[] arg) throws IOException {
		System.out.println("Java-Version: " + System.getProperty("java.version"));

		try {
			UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
		}
		catch (ClassNotFoundException e) { e.printStackTrace(); }
		catch (InstantiationException e) { e.printStackTrace(); }
		catch (IllegalAccessException e) { e.printStackTrace(); }
		catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); }

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                	Demo win = Demo.getInstance();
                    win.setVisible(true);
                    
            		if(arg.length > 0) {
            			win.loadFile(new File(arg[0]));
            		} else {
            			win.setTitle(APP_TITLE + ": Datei einfach hereinziehen");
            		}
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
    }
}



@SuppressWarnings("serial")
class MyList extends JScrollPane {

	private JList m_listComponent = null;
	private DefaultListModel m_listModel = null;
	
	public MyList() {
		// Add listbox with the ability to handle tabulator characters 
		m_listComponent = new JList();		
		super.add(m_listComponent);
		
		// Define list model
		m_listModel = new DefaultListModel();
		m_listComponent.setModel(m_listModel);

		// Define viewport for the JScrollPane (this class is extending JScrollPane)
		this.setViewportView(m_listComponent);
	}
	
	public void addItem(Object obj) {
		final Object finalObj = obj;
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				m_listModel.addElement(finalObj);
			}
		});
	}
}


@SuppressWarnings("serial")
class MyWindow extends JDialog {
	private static MyWindow m_instance = null;
	
	private MyWindow() {
		super(Demo.getInstance(), false);
		
		JButton but1 = new JButton("Ausblenden");
		but1.setPreferredSize(new Dimension(100, 20));
		but1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MyWindow.this.setVisible(false);
			}
		});
		JButton but2 = new JButton("Schließen");
		but2.setPreferredSize(new Dimension(100, 20));
		but2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MyWindow.this.dispose();
			}
		});
		
		this.setLayout( new FlowLayout() );
		this.add(but1);
		this.add(but2);
		this.pack();
		this.setVisible(true);
		centerTo(Demo.getInstance());
	}
	
	public static MyWindow getInstance() {
		if(m_instance == null) {
			m_instance = new MyWindow();
		}
		return m_instance;
	}
	
	private void centerTo(JFrame owner) {
		int x = owner.getLocation().x + (owner.getWidth() - this.getWidth()) / 2;
		int y = owner.getLocation().y + (owner.getHeight() - this.getHeight()) / 2;
		
		this.setLocation(x, y);
	}
}
Um die Probleme zu sehen, solltet ihr eine möglichst große (~10...50MB) Textdatei in das Hauptfenster ziehen. Dann erscheint eine Abfrage, ob ein Fenster angezeigt werden soll. Bitte Nein ankicken, um das erste Problem darzustellen. Wenn Ja angeklickt wird, wird ein weiterer Dialog angezeigt. Dieser kann dann nur ausgeblendet (setVisible), oder aber ganz geschlossen (dispose) werden - egal was man wählt, die Aktualisierung des UI erfolgt erst mit Abschluss des Ladevorgangs.

Ich füge diesem Dialog einen Component/WindowListener hinzu, in welchem der Ladevorgang gestartet wird, sobald der Nutzer eine Auswahl getroffen und somit den Dialog geschlossen hat. - Kann es sein, dass damit der Ladevorgang selber im EDT läuft? Wie kann man so etwas besser machen?

Vielen Dank für eure Unterstützung! :)
 

bERt0r

Top Contributor
"percent += ((line.length() + 2) / factor);" Was willst du denn damit ausrechnen? Eine Fortschrittsanzeige wird daraus jedenfalls nicht. Ich hab dir in deinem anderen Thread ein Beispiel reingestellt wo das eigentlich erklärt sein sollte. Mehrere Threads für das gleiche Problem zu öffnen wird normalerweise nicht gern gesehen.
 

jf

Bekanntes Mitglied
"percent += ((line.length() + 2) / factor);" Was willst du denn damit ausrechnen? Eine Fortschrittsanzeige wird daraus jedenfalls nicht. Ich hab dir in deinem anderen Thread ein Beispiel reingestellt wo das eigentlich erklärt sein sollte.
Ja, das hat mir sehr geholfen. Danke.

Die Formel passt:
factor ist die Dateigröße geteilt durch 100 (da die JProgressBar standardmäßig auf einen Maximalwert von 100 eingestellt ist).
In der Formel addiere ich die Längen der einzelnen Zeilen aus der Datei zusammen und dividiere das ganze durch factor, um den aktuellen Prozentwert zu erhalten.
Die +2 ist für den Zeilenumbruch unter Windows. - Gibt es evtl. eine Möglichkeit, über den BufferedReader die Art des Zeilenumbruchs herauszufinden? Ich fände es irgendwie hässlich, die Datei zunächst daraufhin zu untersuchen und anschließend erneut für das zeilenweise Lesen zu öffnen...

Mehrere Threads für das gleiche Problem zu öffnen wird normalerweise nicht gern gesehen.
Im anderen Thread ging es anfangs nur um die Fortschrittsanzeige, das Newline-Problem (siehe Frage vorher) und um ein KeyListener/KeyBinding-Problem. Hier geht es eher um das Problem der Aktualisierung, wenn ich zuvor ein Fenster öffene. - Ich habe auch schon eine Vermutung geäußert, woran das liegen könnte. Allerdings habe ich keine Idee, wie ich es anders machen kann, wenn der Dialog unbedingt modeless sein soll. Um das ganze besser zu verdeutlichen habe ich eine Demo gemacht, welche auch die Darstellung des Progressbar-Problems hergibt, weshalb ich nun an dieser Stelle nochmals darauf eingegangen bin.

[TIPP]Das Problem mit der Fortschrittsanzeige konnte durch bERt0r bereits gelöst werden. Vielen Dank hierfür.[/TIPP]
 

jf

Bekanntes Mitglied
Das stimmt aber nicht. Um beim 20. Teil von 200 auf die 10% zu kommen musst du 20 / 200 * 100 rechnen. Nicht 20 / 200 / 100.
Ich bin mir ziemlich sicher, dass es funktioniert, da es immer genau bis 100% läuft.
Wenn ich die +2 weg lasse, dann bleibt die Fortschrittsanzeige immer ein Stück vor 100% stehen.

Die Rechnung ist folgende:

200MB / 100% = 2MB/%
20MB / (2MB/%) = 10%
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
XWing Swing Image anzeigen und probleme mit klassen AWT, Swing, JavaFX & SWT 3
E repaint Probleme AWT, Swing, JavaFX & SWT 13
mananana Mögliche probleme die in einer GUI passieren Können AWT, Swing, JavaFX & SWT 6
S GridBagLayout - Probleme mit Bilderanzeige AWT, Swing, JavaFX & SWT 3
I Probleme beim Drucken auf einen PDF-Drucker AWT, Swing, JavaFX & SWT 8
J Probleme mit idividueller Tablecell AWT, Swing, JavaFX & SWT 0
D JavaFX Probleme beim nachtäglichen hinzufügen der jfx dependency AWT, Swing, JavaFX & SWT 7
J Probleme mit InputDialog AWT, Swing, JavaFX & SWT 4
D JavaFX TextArea Probleme bei langen Zeilen AWT, Swing, JavaFX & SWT 1
G JavaFX SplitPane Anwendung - Controller Probleme AWT, Swing, JavaFX & SWT 5
K Probleme bei der Erstellung und Ausführung einer Jar Datei AWT, Swing, JavaFX & SWT 2
B Probleme Action Listener Taschenrechner AWT, Swing, JavaFX & SWT 27
pph080560 JavaFX Probleme mit FX AWT, Swing, JavaFX & SWT 3
M Probleme mit OpenJDK AWT, Swing, JavaFX & SWT 6
B 2D-Grafik paintcomponent Probleme beim zeichnen AWT, Swing, JavaFX & SWT 10
B Swing Probleme mit dem Layout AWT, Swing, JavaFX & SWT 1
L JavaFX Probleme beim Installieren JavaFX11 / JavaFX12 -- Eclipse 2019-03 AWT, Swing, JavaFX & SWT 3
Fiedlerdan Image-Pfad Probleme nach Export aus Eclipse AWT, Swing, JavaFX & SWT 31
H JFreeChart - DemoDataSetFactory Probleme AWT, Swing, JavaFX & SWT 1
H LayoutManager Probleme mit Positionierung/Abständen der Komponenten AWT, Swing, JavaFX & SWT 14
A Probleme mit gridheight (GridBagLayout) AWT, Swing, JavaFX & SWT 6
U Opaque Probleme AWT, Swing, JavaFX & SWT 3
H JavaFX Probleme Beim Wechseln der scene als .fxml AWT, Swing, JavaFX & SWT 7
F JavaFX Probleme beim automatischen Konvertieren AWT, Swing, JavaFX & SWT 4
S Probleme mit JComboboxen(?) AWT, Swing, JavaFX & SWT 18
S Swing Probleme mit MigLayout AWT, Swing, JavaFX & SWT 2
C Probleme mit createImage AWT, Swing, JavaFX & SWT 1
J Probleme mit contex Menu (javafx) AWT, Swing, JavaFX & SWT 1
J Probleme bei GameofLife AWT, Swing, JavaFX & SWT 24
S JavaFx - Button ActionEvent Probleme AWT, Swing, JavaFX & SWT 3
T Swing Probleme mit repaint() bzw. JScrollPane AWT, Swing, JavaFX & SWT 7
ImperatorMing JavaFX Probleme mit WindowEvent AWT, Swing, JavaFX & SWT 0
ImperatorMing JavaFX Probleme mit WindowEvent AWT, Swing, JavaFX & SWT 5
J LayoutManager GridBagLayout, probleme mit Anordnung von Objekten AWT, Swing, JavaFX & SWT 6
T Java FX Probleme beim befüllen eines Tableviews AWT, Swing, JavaFX & SWT 5
S AWT Probleme beim Zeichnen AWT, Swing, JavaFX & SWT 3
A Swing Probleme mit dem adden von JButtons zur JScrollPane AWT, Swing, JavaFX & SWT 2
D Swing Probleme mit dem Resizing AWT, Swing, JavaFX & SWT 7
G Probleme mit TextArea AWT, Swing, JavaFX & SWT 5
G JFrame Probleme AWT, Swing, JavaFX & SWT 2
K Probleme beim JPasswordField AWT, Swing, JavaFX & SWT 11
G Cardlayout Refresh Probleme AWT, Swing, JavaFX & SWT 2
J Swing Probleme mit ListSelectionListener(), Inhalte der JList werden gelöscht? AWT, Swing, JavaFX & SWT 6
D JavaFX Probleme bei Service-Klasse beim ändern der GUI AWT, Swing, JavaFX & SWT 8
K Probleme beim zeichnen mit paintComponent() AWT, Swing, JavaFX & SWT 1
M JButton Probleme AWT, Swing, JavaFX & SWT 14
L Probleme mit Programm AWT, Swing, JavaFX & SWT 13
blazingblade komischerweise probleme mit jtextfield.gettext() AWT, Swing, JavaFX & SWT 9
Xanny 2D-Grafik Beginner! Probleme mit Swing, Gprahics class und paint AWT, Swing, JavaFX & SWT 13
Sin137 LayoutManager GridBagLayout Probleme AWT, Swing, JavaFX & SWT 6
H Netbeans Designer: Probleme mit JPanel und JFrame AWT, Swing, JavaFX & SWT 2
M Swing Probleme mit Frame.pack() AWT, Swing, JavaFX & SWT 1
C Java FX Probleme beim Schließen einer Stage AWT, Swing, JavaFX & SWT 11
M Swing JProgressbar und Outoputstream probleme AWT, Swing, JavaFX & SWT 2
S Swing Probleme mit transparenz der Hintergrundfarbe und JRadioButtons AWT, Swing, JavaFX & SWT 2
Z Probleme mit JPanel's AWT, Swing, JavaFX & SWT 6
T Probleme mit Anzeige von Elementen im JPanel AWT, Swing, JavaFX & SWT 1
Shams Probleme bei dem Hinzufügen von Komponenten zu einem JFrame AWT, Swing, JavaFX & SWT 3
A Swing Probleme mit JScrollPane AWT, Swing, JavaFX & SWT 6
M Layout-Probleme unter Swing AWT, Swing, JavaFX & SWT 5
H Swing Probleme beim erstellen eines neuen Objektes durch einen Button AWT, Swing, JavaFX & SWT 10
J JavaFX JavaFX Probleme bei der Anzeige von Text AWT, Swing, JavaFX & SWT 18
A Probleme mit TilledBorder("***") AWT, Swing, JavaFX & SWT 4
F Bildschirmschoner Probleme mit Preview AWT, Swing, JavaFX & SWT 8
X Panel Probleme (Tetris) AWT, Swing, JavaFX & SWT 8
N JTable probleme AWT, Swing, JavaFX & SWT 5
B Probleme bei ImageIO.read (?!) AWT, Swing, JavaFX & SWT 9
P JFrame Location-/Size-Probleme AWT, Swing, JavaFX & SWT 5
U LayoutManager Probleme mit Layouts AWT, Swing, JavaFX & SWT 5
C 3 kleine Probleme... AWT, Swing, JavaFX & SWT 13
L NullpointerException und Probleme mit repaint() AWT, Swing, JavaFX & SWT 11
A Probleme mit 2 JFrames in einem Programm AWT, Swing, JavaFX & SWT 7
K LayoutManager Probleme mit 2 Komponenten AWT, Swing, JavaFX & SWT 9
C Probleme mit Buttons und einem ActionListener AWT, Swing, JavaFX & SWT 2
M Probleme mit Verkleinern eines GUI AWT, Swing, JavaFX & SWT 7
B Swing label.setText() macht probleme AWT, Swing, JavaFX & SWT 5
B ImageIcon - Probleme mit dem Dateipfad AWT, Swing, JavaFX & SWT 5
H JTree Probleme AWT, Swing, JavaFX & SWT 9
F Probleme mit (Graphics g) II AWT, Swing, JavaFX & SWT 4
F Probleme mit (Graphics g) AWT, Swing, JavaFX & SWT 3
K 2D-Grafik .GIF macht mir Probleme AWT, Swing, JavaFX & SWT 14
B Probleme bei Sortierung einer Tabelle mit DefaultTableModel AWT, Swing, JavaFX & SWT 6
T JTable Graphik probleme AWT, Swing, JavaFX & SWT 3
H GridBagLayout macht Probleme... AWT, Swing, JavaFX & SWT 4
vandread Swing Probleme mit jTextField im zusammenspiel mit einem Einblendeffekt (inkl. KSKB) AWT, Swing, JavaFX & SWT 6
S Swing Lauftext Performance Probleme, in größerer Anwendung AWT, Swing, JavaFX & SWT 6
B Infolabel Probleme mit Paint() ? AWT, Swing, JavaFX & SWT 8
P Probleme mit setIconImage AWT, Swing, JavaFX & SWT 8
U Swing Probleme mit Asynchronen Prozessen und Swing: AWT, Swing, JavaFX & SWT 3
das-mo Probleme mit GridBagLayout AWT, Swing, JavaFX & SWT 6
N 2D-Grafik 2 Probleme beim zeichnen AWT, Swing, JavaFX & SWT 18
L Probleme mit JPanel AWT, Swing, JavaFX & SWT 8
D Probleme bei Übertrag von ArrayList in Jtable AWT, Swing, JavaFX & SWT 2
G kleinere Probleme mit GUI AWT, Swing, JavaFX & SWT 2
G Mehrere Probleme mit Java's GUI AWT, Swing, JavaFX & SWT 6
M Swing Erste Schritte mit der GUI, viele Probleme AWT, Swing, JavaFX & SWT 36
B Performance-Probleme AWT, Swing, JavaFX & SWT 17
I Probleme if-Anweisung AWT, Swing, JavaFX & SWT 26
D Swing Probleme bei transparenten Hintergrund im JTextField AWT, Swing, JavaFX & SWT 6
N 2D-Grafik BufferedImage, Line2D, Swing und die Probleme AWT, Swing, JavaFX & SWT 5

Ähnliche Java Themen

Neue Themen


Oben