hisoka56
Messages postés17Date d'inscriptionlundi 7 juillet 2003StatutMembreDernière intervention22 juillet 2008
-
18 mai 2006 à 15:40
uhrand
Messages postés491Date d'inscriptionsamedi 20 mai 2006StatutMembreDernière intervention15 juillet 2012
-
20 mai 2006 à 22:19
Bonjour, je suis pas qur que ce soit bien la place de ce message, mais bon je le poste tout de même.
Je suis en train de realiser un editeur de texte et j'aimerai afficher les Numéro dse lignes juste avant celle ci.
Dans mon editeur j'ai un JScrollPane qui contient un JEditorPane et je ne sais pas comment m'y prendre...
Au debut je pensais mettre un autre JEditorPane non editable dans le JScroll mais apprement il ne peut contenir qu"un seul Jeditor d'ou mon probleme.
Voila j'espere avoit été assez clair sur ma requete.
j'ai egalement pensé à faire un autre Jscrolpane contenant le nouveau jeditor mais dans ce cas, si l'un des textes créait des ascenseurs (dus à sa longueur, l'autre ne suit pas donc cela ne va pas)
uhrand
Messages postés491Date d'inscriptionsamedi 20 mai 2006StatutMembreDernière intervention15 juillet 20129 20 mai 2006 à 22:19
/*
* EditorpaneLineHighlight.java
*/
//package text;
import java.awt.*;
import javax.swing.*;
public class EditorpaneLineHighlight extends JFrame {
public EditorpaneLineHighlight() {
super("EditorpaneLineHighlight");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(400, 300);
setLocationRelativeTo(null);
scroller = new JScrollPane();
editorPane = new JEditorPane();
scroller.setViewportView(editorPane);
getContentPane().add(scroller, BorderLayout.CENTER);
//add the LineNumber component:
scroller.setRowHeaderView( new LineNumber( editorPane ) );
//activate Line_Highlight:
new Line_Highlight(editorPane,new Color(255,255,220));
}
public static void main(String args[]) {
new EditorpaneLineHighlight().setVisible(true);
}
public JScrollPane scroller;
public JEditorPane editorPane;
}
//package text;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;
public class LineNumber extends JComponent {
private final static Color DEFAULT_BACKGROUND = new Color(235, 230, 225);
private final static Color DEFAULT_FOREGROUND = Color.black;
private final static Font DEFAULT_FONT = new Font("monospaced", Font.PLAIN, 12);
// LineNumber height (abends when I use MAX_VALUE)
private final static int HEIGHT = Integer.MAX_VALUE - 1000000;
// Set right/left margin
private final static int MARGIN = 5;
// Variables for this LineNumber component
private FontMetrics fontMetrics;
private int lineHeight;
private int currentDigits;
// Metrics of the component used in the constructor
private JComponent component;
private int componentFontHeight;
private int componentFontAscent;
/**
* Convenience constructor for Text Components
*/
public LineNumber(JComponent component) {
if (component == null) {
setFont( DEFAULT_FONT );
this.component = this;
} else {
setFont( component.getFont() );
this.component = component;
}
setBackground( DEFAULT_BACKGROUND );
setForeground( DEFAULT_FOREGROUND );
setPreferredWidth( 99 );
}
/**
* Calculate the width needed to display the maximum line number
*/
public void setPreferredWidth(int lines) {
int digits = String.valueOf(lines).length();
// Update sizes when number of digits in the line number changes
if (digits != currentDigits && digits > 1) {
currentDigits = digits;
int width = fontMetrics.charWidth( '0' ) * digits;
Dimension d = getPreferredSize();
d.setSize(2 * MARGIN + width, HEIGHT);
setPreferredSize( d );
setSize( d );
}
}
/**
* Reset variables that are dependent on the font.
*/
public void setFont(Font font) {
super.setFont(font);
fontMetrics = getFontMetrics( getFont() );
componentFontHeight = fontMetrics.getHeight();
componentFontAscent = fontMetrics.getAscent();
}
/**
* The line height defaults to the line height of the font for this
* component.
*/
public int getLineHeight() {
if (lineHeight == 0)
return componentFontHeight;
else
return lineHeight;
}
/**
* Override the default line height with a positive value.
* For example, when you want line numbers for a JTable you could
* use the JTable row height.
*/
public void setLineHeight(int lineHeight) {
if (lineHeight > 0)
this.lineHeight = lineHeight;
}
public int getStartOffset() {
return component.getInsets().top + componentFontAscent;
}
public void paintComponent(Graphics g) {
int lineHeight = getLineHeight();
int startOffset = getStartOffset();
Rectangle drawHere = g.getClipBounds();
// Paint the background
g.setColor( getBackground() );
g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);
// Determine the number of lines to draw in the foreground.
g.setColor( getForeground() );
int startLineNumber = (drawHere.y / lineHeight) + 1;
int endLineNumber = startLineNumber + (drawHere.height / lineHeight);
int start = (drawHere.y / lineHeight) * lineHeight + startOffset;
for (int i = startLineNumber; i <= endLineNumber; i++) {
String lineNumber = String.valueOf(i);
int stringWidth = fontMetrics.stringWidth( lineNumber );
int rowWidth = getSize().width;
g.drawString(lineNumber, rowWidth - stringWidth - MARGIN, start);
start += lineHeight;
}
int rows = component.getSize().height / componentFontHeight;
setPreferredWidth( rows );
}
public static void main(String[] args) {
JFrame frame = new JFrame("LineNumberDemo");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel panel = new JPanel();
frame.setContentPane( panel );
panel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
panel.setLayout(new BorderLayout());
JTextArea textPane = new JTextArea();
textPane.setFont( new Font("monospaced", Font.PLAIN, 12) );
textPane.setText("abc");
JScrollPane scrollPane = new JScrollPane(textPane);
panel.add(scrollPane);
scrollPane.setPreferredSize(new Dimension(300, 250));
LineNumber lineNumber = new LineNumber( textPane );
new Line_Highlight(textPane,new Color(255,255,220));
scrollPane.setRowHeaderView(lineNumber );
frame.pack();
frame.setVisible(true);
}
}
/*
* Line_Highlight.java
*/
//package text;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
class Line_Highlight extends
DefaultHighlighter.DefaultHighlightPainter implements
CaretListener, MouseListener, MouseMotionListener, KeyListener {
private JTextComponent component;
private DefaultHighlighter highlighter;
private Object lastHighlight;
public Line_Highlight(JTextComponent component, Color color) {
super(color);
this.component = component;
// "highlighter" is responsible to make the "highlights"
highlighter = (DefaultHighlighter) component.getHighlighter();
/*
with "true" the "highlights" will be painted in the method "paintLayer",
before the text is painted.
*/
highlighter.setDrawsLayeredHighlights(true);
// Add listener so we know when to change highlighting
component.addKeyListener(this);
component.addCaretListener(this);
component.addMouseListener(this);
component.addMouseMotionListener(this);
// Initially highlight the first line
addHighlight(0);
}
//"paintLayer" overrides the corresponding method of the class "DefaultHighlightPainter"
public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
JTextComponent c, View view) {
try {
// Only use the first offset to get the line to highlight
Rectangle r = c.modelToView(offs0);
r.x = 0;
r.width = c.getSize().width;
// --- render ---
g.setColor(getColor());
g.fillRect(r.x, r.y, r.width, r.height);
return r;
} catch (BadLocationException e) {
return null;
}
}
/*
* Remove/add the highlight to make sure it gets repainted
*/
private void resetHighlight() {
/*
"SwingUtilities.invokeLater(...)":
The run() method contained in the "Runnable" is only called, when all pending
events are processed (KeyEvent, MouseEvent, CaretEvent, ...).
According to the dokumentation the mthode "invokeLater(...)" should be used when a
programm modifies the GUI, which is here the case.
*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
highlighter.removeHighlight(lastHighlight);
/*
The "Document" contains the data structure of the "JEditorPane".
The structure is hierarchically and always has a"root"-element.
*/
Element root = component.getDocument().getDefaultRootElement();
/*
Takes the number from the Child-element(that is the line) which is next to the specified "offset".
The "offset" is specified relative to the beginning of the Document. Here the "offset" is equal to the
position of the "text insertion caret", that is the position where the text is inserted.
In short: here the current linenumber is fetched.
*/
int line = root.getElementIndex(component.getCaretPosition());
//Gets the Child-element(that is the line) with the specified number.
Element lineElement = root.getElement(line);
/*Gets the position where thos element(that is this line) begins,
relative to the beginning of the Document*/
int start = lineElement.getStartOffset();
addHighlight(start);
}
});
}
private void addHighlight(int offset) {
try {
lastHighlight = highlighter.addHighlight(offset, offset + 1,
this);
} catch (BadLocationException ble) {
}
}
// Removes our private highlights
public void removeHighlight() {
highlighter.removeHighlight(lastHighlight);
}
// Implement CaretListener
public void caretUpdate(CaretEvent e) {
resetHighlight();
}
// Implement MouseListener
public void mousePressed(MouseEvent e) {
resetHighlight();
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {
component.repaint();
}
public void mouseMoved(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {
removeHighlight();
}
// Implement KeyListener
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}