Gå til innhold

Får ikke JTextArea til å scrolle


Anbefalte innlegg

Hei

 

Har laget en subklasse av JTextArea som tegner linjetall på venstre side av området. I en klientklasse legger jeg til denne i en JTabbedPane, men scrollingen fungerer ikke da.. En tidligere versjon brukte JPanel som superklasse, og innholdt bare et JTextArea, men da måtte jeg skrive alle metodene for JTextArea og JTextComponent, så fant ut at jeg heller ville prøve å bruke JTextArea som superklasse. Men nå fungerer altså ikke scrollingen lenger..

 

Klassen er her: http://pastebin.com/m4a4fac45

evt:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;

import javax.accessibility.AccessibleContext;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.Document;
import javax.swing.text.BadLocationException;


/**
*
* @author Torstein
* @author Daniel Sjöblom
*/
public class JNumberedTextArea2 extends JTextArea {

private final static String uiClassID = "NumberedTextArea2UI";


JScrollPane scrollPane;

public JNumberedTextArea2() {
	this(null);
}

/**
 * Constructs a new <code>JNumberedTextArea</code> with the text in
 * the JTextArea
 *
 * @param text the text is added to the JTextArea
 */
public JNumberedTextArea2(String text) {
	super(text);
	setMinimumSize(new Dimension(30, 30));
	setPreferredSize(new Dimension(30, 30));
	setMinimumSize(new Dimension(30, 30));

	scrollPane = new JScrollPane(this);
}

@Override
public void paint(Graphics g) {
	super.paint(g);

	int charWidth = g.getFontMetrics(this.getFont()).charWidth('0');
	int antDigits = (int) Math.log10(this.getLineCount()) + 1;

	Insets margin = this.getMargin();
	margin.left = (charWidth * antDigits + 3);
	margin.top = 0;
	this.setMargin(margin);

	int start = this.viewToModel(scrollPane.getViewport().getViewPosition());
	int end = this.viewToModel(new Point(
			scrollPane.getViewport().getViewPosition().x + this.getWidth(),
			scrollPane.getViewport().getViewPosition().y + this.getHeight()
			));

	Document doc = this.getDocument();
	int startline = doc.getDefaultRootElement().getElementIndex(start) + 1;
	int endline = doc.getDefaultRootElement().getElementIndex(end) + 1;

	int fontheight = g.getFontMetrics(this.getFont()).getHeight();
	int fontdesc = g.getFontMetrics(this.getFont()).getDescent();
	int starting_y = -1;

	try {
		starting_y = this.modelToView(start).y -
				scrollPane.getViewport().getViewPosition().y + fontheight - fontdesc;
	} catch(BadLocationException e1) {
		e1.printStackTrace();
	}

	for(int line = startline, y = starting_y; line <= endline; y += fontheight, line++) {
		g.drawString(Integer.toString(line) + ":", 0, y);
	}
	this.repaint();
}
}

 

og klienten er her: http://pastebin.com/m2bc38e07

evt:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;

import java.awt.event.KeyEvent;


import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ScrollPaneConstants;


class JNumberedTextArea22Client {
 JNumberedTextArea2 textArea;
 JFrame frame;

 public static void main(String[] args) {
JNumberedTextArea2 textArea;
JFrame frame;
JTabbedPane tabbedPane;

String content = "Dette er en streng\nDen har flere linjer\nJada.. det har den..";
textArea = new JNumberedTextArea2(content);
JNumberedTextArea2 textArea2 = new JNumberedTextArea2(content + content);
tabbedPane = new JTabbedPane();
frame = new JFrame("JNumberedTextArea2Client") {};
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container innholdsrute = frame.getContentPane();

tabbedPane.addTab("textArea", textArea);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.addTab("textArea2", textArea2);
tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);
JNumberedTextArea2 comp = new JNumberedTextArea2(content + "\njadda\ntextArea3");
tabbedPane.addTab("textArea3", comp.scrollPane);


innholdsrute.setLayout(new BorderLayout());
innholdsrute.add(tabbedPane, BorderLayout.CENTER);
frame.pack();
frame.setSize(new Dimension(400, 400));
frame.setVisible(true);
 }

}

 

 

Takker for all hjelp!

Lenke til kommentar
Videoannonse
Annonse

Med mindre jeg missforstår hva du mener med scrollskit er jo dette mer eller mindre den vanlige måten å gjøre dette på.. Det har jeg allerede prøvd. For du mente at koden over skal legges til i klient-klassen?

 

Problemet er at JSsrollPane'et ikke merker at texten er så stor at den må aktiveres. Og jeg må ha et scrollpane i klassen for tekstområdet for at denne måten å gjøre det på skal virke..

 

EDIT:

Er det mulig at en av metodene som er gitt av Scrollable lager rot når den blir arvet?

Endret av toss
Lenke til kommentar

Har du i det hele tatt lest innlegget mitt?

 

Jeg vil ha en subklasse av JTextArea som håndterer linjetall på siden..

Klassen du har skrevet her gjør ingen av delene.. Scrolling fungerer, ja, men det i seg selv er ikke problemet..

 

Men har funnet en annen løsning nå.. Bruker rowHeader for å legge til linjeskift.. Da blir alt nesten slik jeg ønsker det..

Lenke til kommentar

Har sett den, ja.. Problemet er at JTextArea, eller JTextPane som den bruker, ikke er superklassen, og jeg må derfor skrive over alle metodene som setText(), append() osv.. Det er jo for så vidt ikke noe stort problem, og kan også løses ved å ha tekstkomponenten deklarert public. Men jeg ville likevel prøve å se om jeg kunne løse dette på en litt mer elegant måte..

 

Det nærmeste jeg kommer er dette:

 

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;

import javax.accessibility.AccessibleContext;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.text.Document;
import javax.swing.text.BadLocationException;


/**
*
* @author Torstein
* @author Daniel Sjöblom
*/
public class JNumberedTextArea2 extends JTextArea {

private final static String uiClassID = "NumberedTextArea2UI";


JScrollPane scrollPane;

public JNumberedTextArea2() {
	this(null, null);
}

/**
 * Constructs a new <code>JNumberedTextArea</code> with the text in
 * the JTextArea
 *
 * @param text the text is added to the JTextArea
 */
public JNumberedTextArea2(String text, JScrollPane scrollPane) {
	super(text);

	this.scrollPane = scrollPane;
}

@Override
public void paint(Graphics g) {
	super.paint(g);

	int charWidth = g.getFontMetrics(this.getFont()).charWidth('0');
	int antDigits = (int) Math.log10(this.getLineCount()) + 1;

	Insets margin = this.getMargin();
	margin.left = (charWidth * antDigits + 3);
	margin.top = 0;
	this.setMargin(margin);

	int start = this.viewToModel(scrollPane.getViewport().getViewPosition());
	int end = this.viewToModel(new Point(
			scrollPane.getViewport().getViewPosition().x + this.getWidth(),
			scrollPane.getViewport().getViewPosition().y + this.getHeight()
			));

	Document doc = this.getDocument();
	int startline = doc.getDefaultRootElement().getElementIndex(start) + 1;
	int endline = doc.getDefaultRootElement().getElementIndex(end) + 1;

	int fontheight = g.getFontMetrics(this.getFont()).getHeight();
	int fontdesc = g.getFontMetrics(this.getFont()).getDescent();
	int starting_y = -1;

	try {
		starting_y = this.modelToView(start).y -
				scrollPane.getViewport().getViewPosition().y + fontheight - fontdesc;
	} catch(BadLocationException e1) {
		e1.printStackTrace();
	}

	for(int line = startline, y = starting_y; line <= endline; y += fontheight, line++) {
		g.drawString(Integer.toString(line) + ":", 0, y);
	}
	this.repaint();
}

public static void main(String[] args) {
  JFrame frame = new JFrame("JNumberedTextArea2");
  Container contPane = frame.getContentPane();
  JTabbedPane tabbedPane = new JTabbedPane();
  JScrollPane scrollPane = new JScrollPane();

  JNumberedTextArea2 textArea = new JNumberedTextArea2("This is a string\nit contains several lines\nindeed", scrollPane);
  scrollPane.setViewportView(textArea);
  tabbedPane.addTab("textArea", scrollPane);
  contPane.add(tabbedPane);

  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.pack();
  frame.setSize(new Dimension(400, 400));
  frame.setVisible(true);
}
}

 

 

Problemet her blir at det kjører en evig loop, siden paint-metoden kaller repaint(), og likevel klarer den ikke å få med linjenummer når teksten blir lang nok..

 

Så nå har jeg egentlig gitt opp å få det til slik jeg tenkte, og baserer meg på å bruke rowHeader i JScrollPane..

 

Tror jeg lander på noe lignende dette:

http://forums.sun.com/thread.jspa?forumID=...974&start=2

Det fungerer egentlig akkurat slik jeg ønsker det, med bare litt ekstra skriving..

Lenke til kommentar
Har sett den, ja.. Problemet er at JTextArea, eller JTextPane som den bruker, ikke er superklassen, og jeg må derfor skrive over alle metodene som setText(), append() osv..
Det sees sjeldent på som et problem (se composition).
Det er jo for så vidt ikke noe stort problem, og kan også løses ved å ha tekstkomponenten deklarert public.
Nei, det er ikke en god løsning og du bør ikke gjøre det.
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...