How to display a text in a JTextField ot jLabel with 2 colors.
for example:
1 0 0 0 1 1 1 0 1
textField.setForeground(Color.RED ,BLUE);
Positioning individual RED for example
Different font color in a JTextField
You can't achieve it with JTextField instead use JEditorPane or JTextPane.
Read more about How to Use Editor Panes and Text Panes
Sample code using JTextPane directly from HERE
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class StylesExample12 {
public static void main(String[] args) {
JFrame f = new JFrame("Styles Example 1");
// Create the StyleContext, the document and the pane
StyleContext sc = new StyleContext();
final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
JTextPane pane = new JTextPane(doc);
// Create and add the style
final Style heading2Style = sc.addStyle("Heading2", null);
heading2Style.addAttribute(StyleConstants.Foreground, Color.red);
heading2Style.addAttribute(StyleConstants.FontSize, new Integer(16));
heading2Style.addAttribute(StyleConstants.FontFamily, "serif");
heading2Style.addAttribute(StyleConstants.Bold, new Boolean(true));
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
// Add the text to the document
doc.insertString(0, text, null);
// Finally, apply the style to the heading
doc.setParagraphAttributes(0, 1, heading2Style, false);
} catch (BadLocationException e) {
}
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
System.exit(1);
}
f.getContentPane().add(new JScrollPane(pane));
f.setSize(400, 300);
f.setVisible(true);
}
public static final String text = "Attributes, Styles and Style Contexts\n"
+ "The simple PlainDocument class that you saw in the previous "
+ "chapter is only capable of holding text. The more complex text "
+ "components use a more sophisticated model that implements the "
+ "StyledDocument interface. StyledDocument is a sub-interface of "
+ "Document that contains methods for manipulating attributes that "
+ "control the way in which the text in the document is displayed. "
+ "The Swing text package contains a concrete implementation of "
+ "StyledDocument called DefaultStyledDocument that is used as the "
+ "default model for JTextPane and is also the base class from which "
+ "more specific models, such as the HTMLDocument class that handles "
+ "input in HTML format, can be created. In order to make use of "
+ "DefaultStyledDocument and JTextPane, you need to understand how "
+ "Swing represents and uses attributes.\n";
}
snapshot:
EDIT
As per your question try this sample code: (change it as per your requirement)
// Create and add the style
final Style redStyle = sc.addStyle("RED", null);
redStyle.addAttribute(StyleConstants.Foreground, Color.red);
redStyle.addAttribute(StyleConstants.FontSize, new Integer(16));
final Style blueStyle = sc.addStyle("BLUE", null);
blueStyle.addAttribute(StyleConstants.Foreground, Color.blue);
blueStyle.addAttribute(StyleConstants.FontSize, new Integer(14));
blueStyle.addAttribute(StyleConstants.Bold, new Boolean(true));
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
String[] text = { "1a", "0b", "0c", "0d", "1e", "1f", "1g", "0h", "1i" };
for (int i = 0; i < text.length; i++) {
String s = text[i];
// Finally, apply the style to the heading
int start = pane.getText().length();
Style style = null;
if (i % 2 == 0) {
style = redStyle;
} else {
style = blueStyle;
}
// Add the text to the document
doc.insertString(start, s + " ", style);
}
} catch (BadLocationException e) {
}
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
System.exit(1);
}
snapshot:
Related
This question already has answers here:
How to redirect console content to a textArea in Java?
(5 answers)
Closed 1 year ago.
I am new to java and trying following example. With the code below, I can print all nodes of a XML file. Now I would like to use Swing and put it out in a simple Swing window.
I understand how to create a window, but how can I connect the console output to a JTextArea? I searched for it on Stack Overflow, but did not get the right idea.
public static void main(String[] args) throws IOException
{
try
{
File file = new File("dum.xml");
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.parse(file);
System.out.println("Root element: "+ document.getDocumentElement().getNodeName());
if (document.hasChildNodes())
{
printNodeList(document.getChildNodes());
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
private static void printNodeList(NodeList nodeList)
{
for (int count = 0; count < nodeList.getLength(); count++)
{
Node elemNode = nodeList.item(count);
if (elemNode.getNodeType() == Node.ELEMENT_NODE)
{
// get node name and value
System.out.println("\nZeilenname =" + elemNode.getNodeName()+ " [Anfang]");
System.out.println("Zeileninhalt =" + elemNode.getTextContent());
if (elemNode.hasAttributes())
{
NamedNodeMap nodeMap = elemNode.getAttributes();
for (int i = 0; i < nodeMap.getLength(); i++)
{
Node node = nodeMap.item(i);
System.out.println("Attributname : " + node.getNodeName());
System.out.println("Attributwert : " + node.getNodeValue());
}
}
if (elemNode.hasChildNodes())
{
//recursive call if the node has child nodes
printNodeList(elemNode.getChildNodes());
}
System.out.println("Zeilenname =" + elemNode.getNodeName()+ " [Ende]");
}
}
}
This is how to create the main frame for a Java Swing application following best practices (i.e. use SwingUtilities#invokeLater(...) to run your Swing application.
public class SwingDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame f = new JFrame("Swing Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(250,250);
f.setVisible(true);
}
}
Now you need to add the component to display text. JLabel, JTextField, and JTextAreaare the main candidates. Since you mentioned text area, let use that component. For that, all you need to do is add these two lines at the end:
String text = "Hello World!";
JTextArea textarea = new JTextArea();
textarea.setText(text);
f.add(textarea);
textarea.append("\nI added this later"); // UPDATE
You can then modify this sample code so it looks better. For example, you can instead put the text area in a JPanel and you could then use layouts to control the placement and size of the panel in order to prevent the text area to expand to the size of the entire JFrame. But this minimalist code does exactly what you wanted, which is to set text in a Java Swing GUI.
UPDATE: You could use the append() method to add lines to your GUI. For example:
NamedNodeMap nodeMap = elemNode.getAttributes();
for (int i = 0; i < nodeMap.getLength(); i++)
{
Node node = nodeMap.item(i);
textarea.append("\nAttributname : " + node.getNodeName());
}
Create a JTextArea. Replace all calls to System.out.println with JTextArea.append. Below code demonstrates.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XmlSwing {
private JTextArea textArea;
private void createAndDisplayGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTextArea(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createTextArea() {
textArea = new JTextArea(20, 40);
createTextAreaText();
JScrollPane scrollPane = new JScrollPane(textArea);
return scrollPane;
}
private void createTextAreaText() {
try {
File file = new File("dum.xml");
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.parse(file);
textArea.append("Root element: " + document.getDocumentElement().getNodeName() + "\n");
if (document.hasChildNodes()) {
printNodeList(document.getChildNodes());
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
private void printNodeList(NodeList nodeList) {
for (int count = 0; count < nodeList.getLength(); count++) {
Node elemNode = nodeList.item(count);
if (elemNode.getNodeType() == Node.ELEMENT_NODE) {
// get node name and value
textArea.append("\nZeilenname =" + elemNode.getNodeName() + " [Anfang]\n");
textArea.append("Zeileninhalt =" + elemNode.getTextContent() + "\n");
if (elemNode.hasAttributes()) {
NamedNodeMap nodeMap = elemNode.getAttributes();
for (int i = 0; i < nodeMap.getLength(); i++) {
Node node = nodeMap.item(i);
textArea.append("Attributname : " + node.getNodeName() + "\n");
textArea.append("Attributwert : " + node.getNodeValue() + "\n");
}
}
if (elemNode.hasChildNodes()) {
// recursive call if the node has child nodes
printNodeList(elemNode.getChildNodes());
}
textArea.append("Zeilenname =" + elemNode.getNodeName() + " [Ende]\n");
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new XmlSwing().createAndDisplayGui());
}
}
Refer to Creating a GUI With Swing
There are few styles in the preview mode but can't find where I can set the preferred design. Is there any option?
Check screen
Examples:
Programmatically:
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
Command line:
java -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel MyApp
You can find more info about this on the Oracle docs.
A complete demo (from the docs):
public class LookAndFeelDemo implements ActionListener {
private static String labelPrefix = "Number of button clicks: ";
private int numClicks = 0;
final JLabel label = new JLabel(labelPrefix + "0 ");
// Specify the look and feel to use by defining the LOOKANDFEEL constant
// Valid values are: null (use the default), "Metal", "System", "Motif",
// and "GTK"
final static String LOOKANDFEEL = "Metal";
// If you choose the Metal L&F, you can also choose a theme.
// Specify the theme to use by defining the THEME constant
// Valid values are: "DefaultMetal", "Ocean", and "Test"
final static String THEME = "Test";
public Component createComponents() {
JButton button = new JButton("I'm a Swing button!");
button.setMnemonic(KeyEvent.VK_I);
button.addActionListener(this);
label.setLabelFor(button);
JPanel pane = new JPanel(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
pane.setBorder(BorderFactory.createEmptyBorder(
30, //top
30, //left
10, //bottom
30) //right
);
return pane;
}
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}
private static void initLookAndFeel() {
String lookAndFeel = null;
if (LOOKANDFEEL != null) {
if (LOOKANDFEEL.equals("Metal")) {
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
// an alternative way to set the Metal L&F is to replace the
// previous line with:
// lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
}
else if (LOOKANDFEEL.equals("System")) {
lookAndFeel = UIManager.getSystemLookAndFeelClassName();
}
else if (LOOKANDFEEL.equals("Motif")) {
lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
}
else if (LOOKANDFEEL.equals("GTK")) {
lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
}
else {
System.err.println("Unexpected value of LOOKANDFEEL specified: "
+ LOOKANDFEEL);
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
}
try {
UIManager.setLookAndFeel(lookAndFeel);
// If L&F = "Metal", set the theme
if (LOOKANDFEEL.equals("Metal")) {
if (THEME.equals("DefaultMetal"))
MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
else if (THEME.equals("Ocean"))
MetalLookAndFeel.setCurrentTheme(new OceanTheme());
else
MetalLookAndFeel.setCurrentTheme(new TestTheme());
UIManager.setLookAndFeel(new MetalLookAndFeel());
}
}
catch (ClassNotFoundException e) {
System.err.println("Couldn't find class for specified look and feel:"
+ lookAndFeel);
System.err.println("Did you include the library in the class path?");
System.err.println("Using the default look and feel.");
}
catch (UnsupportedLookAndFeelException e) {
System.err.println("Can't use the specified look and feel ("
+ lookAndFeel
+ ") on this platform.");
System.err.println("Using the default look and feel.");
}
catch (Exception e) {
System.err.println("Couldn't get specified look and feel ("
+ lookAndFeel
+ "), for some reason.");
System.err.println("Using the default look and feel.");
e.printStackTrace();
}
}
}
private static void createAndShowGUI() {
//Set the look and feel.
initLookAndFeel();
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("SwingApplication");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
LookAndFeelDemo app = new LookAndFeelDemo();
Component contents = app.createComponents();
frame.getContentPane().add(contents, BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I have created an application that runs fine but when made into a jar file the image doesn't show. I'm using JAVAFX for the GUI.
Part of the code
#FXML
private ImageView weatherIconId;
public void setLocation(){
WeatherToday wT = new WeatherToday();
File file = new File("src\\weatherIcons\\"+ wT.getIcon() + ".png");
Image image = new Image(file.toURI().toString());
try {
weatherIconId.setImage(image);
loc.setText(wT.getDescription().substring(0, 1).toUpperCase() + wT.getDescription().substring(1) + " " + wT.getCels());
}catch(Exception e){
loc.setText("Error News");
}
}
Image show in executable
Image not showing in JAR File
Full code for class
public class LabelController {
#FXML
private TextArea lblN;
#FXML
private Label lblTime;
#FXML
private Label loc;
#FXML
private Label trainUpdate;
#FXML
private Label monthDay;
#FXML
private Label TFLline;
#FXML
private Label BBCL;
#FXML
private ImageView weatherIconId;
static String i;
static int num;
public void getAndSetData(){
setTime();
setNews();
setLocation();
setTrainStatus();
}
public void setTime(){
try {
LocalTime watch = LocalTime.now();
DateTimeFormatter shortTime = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
i = shortTime.format(watch);
LocalDate now = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM, dd");
String formatDate = now.format(formatter);
System.out.println("After : " + formatDate);
lblTime.setText(i);
monthDay.setText(formatDate);
}catch(Exception e){
lblTime.setText("Error T");
}
}
public void setNews(){
BBCL.setTextFill(Color.web("#ff270f"));
try {
String news = "";
for(String n: new News().getHeadLine()){
news += "- " + n + "\n";
}
//Scroll bar in the textArea
ScrollBar scrollBarv = (ScrollBar)lblN.lookup(".scroll-bar:vertical");
//Hide scrollbar
scrollBarv.setDisable(true);
lblN.setWrapText(true);
//New information.
lblN.setText(news);
lblN.appendText("\n"+ "\n"+ "\n"+ "\n");
//Automatic scrolling function
slowScrollToBottom(scrollBarv);
}catch(Exception e){
lblN.setText("Error News");
}
}
static void slowScrollToBottom(ScrollBar scrollPane) {
scrollPane.setValue(1.5);
Animation animation = new Timeline(
new KeyFrame(Duration.seconds(7),
new KeyValue(scrollPane.valueProperty(), 0)));
animation.play();
}
public void setLocation(){
WeatherToday wT = new WeatherToday();
File file = new File("src\\weatherIcons\\"+ wT.getIcon() + ".png");
Image image = new Image(file.toURI().toString());
try {
weatherIconId.setImage(image);
loc.setText(wT.getDescription().substring(0, 1).toUpperCase() + wT.getDescription().substring(1) + " " + wT.getCels());
}catch(Exception e){
loc.setText("Error News");
}
}
public void setTrainStatus(){
TFLStatus tS = new TFLStatus();
LocateMyCity lo = new LocateMyCity();
int sizeOfService = tS.getTFL().size();
int countGS = 0;
if(lo.getmyCityLocation().equalsIgnoreCase("London")) {
try {
for (Map.Entry<String, String> entry : tS.getTFL().entrySet()) {
//Line NOT equal to Good Service - Delay lines
if (!entry.getValue().equalsIgnoreCase("Good Service")) {
TFLline.setFont(new Font("Arial", 30));
TFLline.setStyle("-fx-font-weight: bold");
TFLline.setTextFill(Color.web("#ff270f"));
TFLline.setText("Services delays:");
trainUpdate.setFont(new Font("Arial", 32));
trainUpdate.setStyle("-fx-font-weight: bold");
trainUpdate.setTextFill(Color.web("#ffffff"));
trainUpdate.setText(entry.getKey() + ": " + entry.getValue() + "\n");
System.out.println("Name of Service: " + entry.getKey() + " " + entry.getValue() + "\n");
++countGS;
}
}
if (countGS == 0) {
TFLline.setFont(new Font("Arial", 35));
TFLline.setStyle("-fx-font-weight: bold");
TFLline.setTextFill(Color.web("#25d039"));
TFLline.setText("Good Services: Underground & DLR");
}
System.out.println(countGS);
//tS.getTFL().forEach((k,v)-> System.out.println(v));
} catch (Exception e) {
loc.setText("Error News");
}
}else{
TFLline.setText(lo.getmyCityLocation());
}
}
#FXML
public void initialize() {
Timeline timeline = new Timeline(new KeyFrame(
Duration.millis(8000),
ae -> getAndSetData()));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
// getAndSetTheCurrentTime();
// lblN.textProperty().bind(i);
}
}
You can try this to laod the image
private Image image1 =
new Image(this.getClass().getResourceAsStream("/src/weatherIcons/image1.png"));
First of all, change image patches from "src/image.jpg" to "/image.jpg" and load image with help of classloader getClass().gerResource("/image.jpg") because after building jar and move it to somewhere it does not able to see src folder and your images does not shown. If it does not work check presence of images in your jar (open it with winRar or 7z file managers) and see in classpath (folder with class files) they must be there.
I also faced this issue once, and I solved like this way:
I made a img folder that consists of images. I gave the path of image to button or label etc like this way.
Now I follow this directory structure to attach images.
buttonORLabel.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("/image.jpg"))));
I have an assignment from my university to continue a JAVA card project from the students from last semester, which happens to be sucked. Because we have to carry on with someones work instead ours..
So my first step is to make an window image icon and tray icon for the application`s window.
The thing is, this code below is based on extended FrameView instead of JWindow.
My idea is to wrap the extended FrameView up into a Window.
Can someone help me with that?
Thanks much I would appreciate that.
CODE:
public class DesktopApplication1View extends FrameView implements IProgressDialogObserver
{
//============================================================
// Fields
// ===========================================================
private Connection connection = new Connection();
private ProgressDialogUpdater pbu = ProgressDialogUpdater.getInstance();
private Vector<CourseFromCard> courseListFromCard = new Vector<CourseFromCard>();
private Vector<School> schoolList = new Vector<School>();
private Vector<CourseFromFile> courseList = new Vector<CourseFromFile>();
private int cardReaderRefreshHelper = 0;
private Student student = null;
JLabel jLabelBilkaImage = null;
final String ICON = new File("").getAbsolutePath() + System.getProperty("file.separator") + "src" + System.getProperty("file.separator") + "resources" + System.getProperty("file.separator") + "image" + System.getProperty("file.separator") + "BilKa_Icon_32.png";
final String PIC = new File("").getAbsolutePath() + System.getProperty("file.separator") + "src" + System.getProperty("file.separator") + "resources" + System.getProperty("file.separator") + "image" + System.getProperty("file.separator") + "BilKa_Icon_128.png";
private JLabel getJLabelBilkaImage() {
if (jLabelBilkaImage == null) {
Icon image = new ImageIcon(PIC);
jLabelBilkaImage = new JLabel(image);
jLabelBilkaImage.setName("jLabelBilkaImage");
}
return jLabelBilkaImage;
}
//============================================================
// Constructors
// ===========================================================
public DesktopApplication1View(SingleFrameApplication app)
{
super(app);
pbu.registriere(this);
app.getMainFrame().setIconImage(Toolkit.getDefaultToolkit().getImage("icon.png"));
initComponents();
refreshConnectionState();
readFilesFromLocalHDD();
ResourceMap resourceMap = getResourceMap();
int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
messageTimer = new Timer(messageTimeout, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
statusMessageLabel.setText("");
}
});
messageTimer.setRepeats(false);
int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
for (int i = 0; i < busyIcons.length; i++)
{
busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
}
busyIconTimer = new Timer(busyAnimationRate, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
}
});
idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
// connecting action tasks to status bar via TaskMonitor
TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener()
{
public void propertyChange(java.beans.PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if ("started".equals(propertyName))
{
if (!busyIconTimer.isRunning())
{
statusAnimationLabel.setIcon(busyIcons[0]);
busyIconIndex = 0;
busyIconTimer.start();
}
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
}
else if ("done".equals(propertyName))
{
busyIconTimer.stop();
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
progressBar.setValue(0);
}
else if ("message".equals(propertyName))
{
String text = (String) (evt.getNewValue());
statusMessageLabel.setText((text == null) ? "" : text);
messageTimer.restart();
}
else if ("progress".equals(propertyName))
{
int value = (Integer) (evt.getNewValue());
progressBar.setVisible(true);
progressBar.setIndeterminate(false);
progressBar.setValue(value);
}
}
});
}
.........
SingleFrameApplication provides the method getMainFrame(), which returns the JFrame used to display a particular view. The code you listed in your question is one such view. If you need to operate on the frame, it's probably better to do it in code subclassing SingleFrameApplication than the code you posted.
There's a tutorial on using the Swing Application Framework, which might provide more help.
I am attempting to implmement smart autoscrolling on a JScrollPane containing a JTextPane. The JTextPane is used for logging my app in color. However I'm running into a wall trying to do smart autoscrolling. By smart autoscrolling I don't mean blindly autoscrolling every time something changes, I mean checking to see if your scrolled all the way down, then autoscroll. However no matter what I do it either always autoscrolls or doesn't at all
As a test script, here's the setup (the JFrame has been left out)
final JTextPane textPane = new JTextPane();
textPane.setEditable(false);
final JScrollPane contentPane = new JScrollPane(textPane);
contentPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
And here's the ugly auto add test loop
while (true)
try {
Thread.sleep(1000);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
JScrollBar scrollBar = scroll;
boolean preCheck = ((scrollBar.getVisibleAmount() != scrollBar.getMaximum()) && (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum()));
System.out.println("Value: " + scroll.getValue()
+ " | Visible: " + scrollBar.getVisibleAmount()
+ " | Maximum: " + scrollBar.getMaximum()
+ " | Combined: " + (scrollBar.getValue() + scrollBar.getVisibleAmount())
+ " | Vis!=Max : " + (scrollBar.getVisibleAmount() != scrollBar.getMaximum())
+ " | Comb=Max: " + (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum())
+ " | Eval: " + preCheck);
StyledDocument doc = textPane.getStyledDocument();
doc.insertString(doc.getLength(), "FAGAHSIDFNJASDKFJSD\n", doc.getStyle(""));
if (!preCheck)
textPane.setCaretPosition(doc.getLength());
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
Its not pretty, but it gets the job done.
Here's though the relevant check
boolean preCheck = ((scrollBar.getVisibleAmount() != scrollBar.getMaximum()) && (scrollBar.getValue() + scrollBar.getVisibleAmount() == scrollBar.getMaximum()));
if (preCheck)
textPane.setCaretPosition(doc.getLength());
Thats the part thats been giving me trouble. There is first a check to see if the bar is visible but unusable (not enough text, making the bar the full length), then if the bottom of the bar is equal to the maximum. In theory, that should work. However nothing, including moving the check around, has gotten the results I would like.
Any suggestions?
NOT A DUPLICATE of this or this, as they are wanting it to always scroll, not just sometimes.
Edit:
I replaced the following code with a more flexible version that will work on any component in a JScrollPane. Check out: Smart Scrolling.
import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.text.*;
public class ScrollControl implements AdjustmentListener
{
private JScrollBar scrollBar;
private JTextComponent textComponent;
private int previousExtent = -1;
public ScrollControl(JScrollPane scrollPane)
{
Component view = scrollPane.getViewport().getView();
if (! (view instanceof JTextComponent))
throw new IllegalArgumentException("Scrollpane must contain a JTextComponent");
textComponent = (JTextComponent)view;
scrollBar = scrollPane.getVerticalScrollBar();
scrollBar.addAdjustmentListener( this );
}
#Override
public void adjustmentValueChanged(final AdjustmentEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
checkScrollBar(e);
}
});
}
private void checkScrollBar(AdjustmentEvent e)
{
// The scroll bar model contains information needed to determine the
// caret update policy.
JScrollBar scrollBar = (JScrollBar)e.getSource();
BoundedRangeModel model = scrollBar.getModel();
int value = model.getValue();
int extent = model.getExtent();
int maximum = model.getMaximum();
DefaultCaret caret = (DefaultCaret)textComponent.getCaret();
// When the size of the viewport changes there is no need to change the
// caret update policy.
if (previousExtent != extent)
{
// When the height of a scrollpane is decreased the scrollbar is
// moved up from the bottom for some reason. Reposition the
// scrollbar at the bottom
if (extent < previousExtent
&& caret.getUpdatePolicy() == DefaultCaret.UPDATE_WHEN_ON_EDT)
{
scrollBar.setValue( maximum );
}
previousExtent = extent;
return;
}
// Text components will not scroll to the bottom of a scroll pane when
// a bottom inset is used. Therefore the location of the scrollbar,
// the height of the viewport, and the bottom inset value must be
// considered when determining if the scrollbar is at the bottom.
int bottom = textComponent.getInsets().bottom;
if (value + extent + bottom < maximum)
{
if (caret.getUpdatePolicy() != DefaultCaret.NEVER_UPDATE)
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
}
else
{
if (caret.getUpdatePolicy() != DefaultCaret.UPDATE_WHEN_ON_EDT)
{
caret.setDot(textComponent.getDocument().getLength());
caret.setUpdatePolicy(DefaultCaret.UPDATE_WHEN_ON_EDT);
}
}
}
private static void createAndShowUI()
{
JPanel center = new JPanel( new GridLayout(1, 2) );
String text = "1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n";
final JTextArea textArea = new JTextArea();
textArea.setText( text );
textArea.setEditable( false );
center.add( createScrollPane( textArea ) );
System.out.println(textArea.getInsets());
final JTextPane textPane = new JTextPane();
textPane.setText( text );
textPane.setEditable( false );
center.add( createScrollPane( textPane ) );
textPane.setMargin( new Insets(5, 3, 7, 3) );
System.out.println(textPane.getInsets());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(center, BorderLayout.CENTER);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(2000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
Date now = new Date();
textArea.getDocument().insertString(textArea.getDocument().getLength(), "\n" + now.toString(), null);
textPane.getDocument().insertString(textPane.getDocument().getLength(), "\n" + now.toString(), null);
}
catch (BadLocationException e1) {}
}
});
timer.start();
}
private static JComponent createScrollPane(JComponent component)
{
JScrollPane scrollPane = new JScrollPane(component);
new ScrollControl( scrollPane );
return scrollPane;
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}