Swing Sichtbaren teil eines JTextPane herausbekommen (mit JScrollPane)

Purgator

Aktives Mitglied
Aloha,
ich wollte gerne eine Möglichkeit haben, mit der ich in einem Programm mitloggen kann welcher Teil eines JTextPane's gerade für den Nutzer sichtbar ist.
Wenn er die JScrollPane (welche das JTextPane enthält) dann verschiebt ist ja ein neuer Teil sichtbar.
Dazu habe ich sogar schon ein tolle Lösung gefunden gehabt:
Java:
private static void viewVisibleText() {
		int offSet = 0;
		int end = 0;
		try {
			JViewport viewPort = scrollPane.getViewport();
			offSet = textPane.viewToModel(viewPort.getViewRect().getLocation());
			int x = (int) viewPort.getViewRect().getWidth();
			int y = (int) viewPort.getViewRect().getLocation().getY()
					+ (int) viewPort.getVisibleRect().getHeight();
			if (y > textPane.getHeight()) {
				y = textPane.getHeight();
			}
			Point endPoint = new Point(x, y);
			end = textPane.viewToModel(endPoint);
			System.out.println("offSet: " + offSet + "- end: " + end +"- end-offSet: " + (end-offSet));
			try {
				System.out.println(textPane.getText(offSet, end - offSet));				
			} catch(BadLocationException ble) {
				System.out.println("feheler...");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
(bis auf den try-catch Block um das syso hatte ich das so übernommen).
Leider kommt bei mir nun wenn ich das Programm starte immer die BadLocationException (nur einmal am anfang, ansonsten funktioniert es wie gewollt), was daran liegt, dass textPane.viewToModel(...) am Anfang -1 zurück gibt.
Dies soll ja nur passieren, wenn die Komponente noch keine positive Größe hat.
Genau dies kann ich aber nicht nachvollziehen. Ich setze den Listener ganz zum Schluss, d.h. die ganze GUI initialisierung passiert vorher.

Hier der gesamte Quelltext (da er nicht so lang ist und als ausführbares Prog evtl. hilfreich ist):

Java:
public class MainFrame extends JFrame {	

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFrame frame = new MainFrame();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public MainFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		JPanel contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));
		
		JTextPane textPane = new JTextPane();		
		textPane.setText("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28");		
		JScrollPane scrollPane = new JScrollPane(textPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		contentPane.add(scrollPane, BorderLayout.CENTER);
		textPane.setCaretPosition(0);
		
		ScrollLogger.setScrollLogger(scrollPane, textPane);
	}
}
Java:
public class ScrollLogger {

	private static JScrollPane scrollPane;
	private static JTextPane textPane;

	public static void setScrollLogger(JScrollPane sp, JTextPane tp) {
		scrollPane = sp;
		textPane = tp;

		scrollPane.getVerticalScrollBar().addAdjustmentListener(
				new AdjustmentListener() {
					public void adjustmentValueChanged(AdjustmentEvent arg0) {
						viewVisibleText();
						System.out.println("_____________________________");
					}
				});
	}

	private static void viewVisibleText() {
		int offSet = 0;
		int end = 0;
		try {
			JViewport viewPort = scrollPane.getViewport();
			offSet = textPane.viewToModel(viewPort.getViewRect().getLocation());
			int x = (int) viewPort.getViewRect().getWidth();
			int y = (int) viewPort.getViewRect().getLocation().getY()
					+ (int) viewPort.getVisibleRect().getHeight();
			if (y > textPane.getHeight()) {
				y = textPane.getHeight();
			}
			Point endPoint = new Point(x, y);
			end = textPane.viewToModel(endPoint);
			try {
				System.out.println(textPane.getText(offSet, end - offSet));
			} catch (BadLocationException ble) {
				System.out.println("feheler...");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
 
Hallo,

Hast du es schon mal mit einem .doLayout() vor deinem ScrollLogger probiert?

Swing ist nicht Threadsicher. D. h. die ganzen Swing-Sachen laufen in einen eigenen Thread parallel zu dem Thread von deinem Programm ab. Aber nicht synchronisiert.
Evtl. mußt du den ScrollLogger in einem .invokeandwait() ablaufen lassen.

Schau dir mal diesen Link an:
Lesson: Concurrency in Swing (The Java™ Tutorials > Creating a GUI With JFC/Swing)


MfG
hansmueller
 
Aloha,
du scheinst tatsächlich recht zu haben.
Ich habe zu Testzwecken den code in der Main nur leicht abgeändert:
Java:
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFrame frame = new MainFrame();
					frame.setVisible(true);
					ScrollLogger.setScrollLogger(scrollPane, textPane);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
und schon kommt der Fehler nicht mehr.
Ich muss zwar nochmal genau durchlesen wie das ganze zusammenhängt um das so hinzubauen wie ich es genau haben will, aber prinzipiell scheinst du mit dem nicht-threadsicheren-Swing richtig gelegen zu haben.

Danke dir!
 

Neue Themen


Zurück
Oben