Swing TextArea with Scrollbar on JDialog - java

I have a scenario like, when user clicks on a button a pop window will be opened with a text area. The text area will have some contents with scroll bar when need. To achieve this i have used JDialog and added a text area to the JDialog. In my case i am able to show the dialog on button click and the text area on dialog with contents. But i could not get the scroll bar for the text area. I have used JScrollPane for text area too.
public class DialogPanel {
public void createDialog() {
final JFrame mainFrame = new JFrame();
mainFrame.setVisible(true);
mainFrame.setSize(500, 600);
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btn = new JButton("Open Dialog");
mainFrame.add(btn, BorderLayout.SOUTH);
JTextField txtField = new JTextField();
mainFrame.add(txtField, BorderLayout.NORTH);
btn.setPreferredSize(new Dimension(100, 100));
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JDialog dialog = new JDialog(mainFrame);
dialog.setLocationByPlatform(true);
JTextArea txtArea = new JTextArea();
txtArea.setAutoscrolls(true);
txtArea.setPreferredSize(new Dimension(900, 500));
txtArea.setBorder(BorderFactory.createLineBorder(Color.BLACK));
txtArea.setFont(new Font("courier new", Font.PLAIN, 12));
txtArea.setLineWrap(true);
JScrollPane txtAreaScroll = new JScrollPane();
txtAreaScroll.setViewportView(txtArea);
txtAreaScroll.setAutoscrolls(true);
File file;
String line = null;
StringBuilder fileContents = new StringBuilder();
try {
file = new File(
"D:\\Softwares\\Apache\\apache-tomcat-7.0.47\\RUNNING.txt");
BufferedReader reader = new BufferedReader(new FileReader(
file));
while ((line = reader.readLine()) != null) {
fileContents.append(line + "\n");
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
txtArea.setText(fileContents.toString());
dialog.add(txtAreaScroll);
dialog.pack();
dialog.setVisible(true);
}
});
}
public static void main(String[] args) {
DialogPanel dialogPanel = new DialogPanel();
dialogPanel.createDialog();
}
}

Essentially, txtArea.setPreferredSize(new Dimension(900, 500)); is removing the automatic calculations employed by JTextArea that it uses to determine the amount of space it needs to display all the text. You are effectivly saying, there is only 500 pixels worth of height that will ever be needed.
You "could" set the preferred size of the scroll pane, but that's not really recommended. Instead, you want to change the value returned by getPreferredScrollableViewportSize in the JTextArea
This tells the scroll pane how big to make the viewable area ... if it can...
JTextArea txtArea = new JTextArea() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(900, 500);
}
};
Take a look at Scrollable for more details
Updated
As AndrewThompson has pointed out, a better (and preferred way) would be to simply specify the rows and columns for the JTextArea and let it figure out what that means based on the platforms rendering capabilities...
JTextArea txtArea = new JTextArea(40, 100);
Yea for simplicity...

You are using dialog.pack() see here and define own size for dialog

This way youu can use text area with scroll :
JTextArea txtArea = new JTextArea(40,100);
txtArea.setAutoscrolls(true);
txtArea.setBorder(BorderFactory.createLineBorder(Color.BLACK));
txtArea.setFont(new Font("courier new", Font.PLAIN, 12));
txtArea.setLineWrap(true);
txtArea.setText(j);
JScrollPane txtAreaScroll = new JScrollPane (txtArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
txtAreaScroll.setViewportView(txtArea);
txtAreaScroll.setAutoscrolls(true);
// now add scroll pane in frame

Related

How to make JTextArea autoscroll

i have problem with my JTextArea i java. When i print output in the text area, it doesn't automatically scroll to the bottom. And when it reaches the bottom of text area i cannot scroll it with scroll panel. Here is my GUI Code:
public void initializeWindow()
{
JPanel pan;
JPanel colorBox;
JPanel consolePanel;
JLabel panText;
JFrame frame = new JFrame();
JScrollPane scroll;
gridPanels = new JPanel[sizeX][sizeY];
boardPanel = new JPanel();
legend = new JPanel();
consolePanel = new JPanel();
consoleOutput = new JTextArea(25,20);
consoleOutput.setEditable(false);
consoleOutput.setPreferredSize(new Dimension( 200,300));
consoleOutput.setAutoscrolls(true);
scroll = new JScrollPane(this.consoleOutput, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
consolePanel.setBorder(BorderFactory.createLineBorder(Color.black));
consolePanel.add(consoleOutput);
consolePanel.add(scroll);
boardPanel.setBorder(BorderFactory.createEmptyBorder(30,30,10,30));
boardPanel.setLayout(new GridLayout(sizeX,sizeY));
legend.setBorder(BorderFactory.createEmptyBorder(30,30,10,30));
legend.setPreferredSize( new Dimension(300,boardPanel.getHeight()));
PrintStream printStream = new PrintStream(new CustomOutputStream(consoleOutput));
for (Organizm org: legendOrgs)
{
pan = new JPanel();
colorBox = new JPanel();
panText = new JLabel();
pan.setMaximumSize(new Dimension(100,70));
pan.setAlignmentX(Component.LEFT_ALIGNMENT);
pan.setLayout(new FlowLayout(FlowLayout.LEADING));
colorBox.setBackground(org.getOrgColor());
colorBox.setAlignmentX(Component.LEFT_ALIGNMENT);
colorBox.setPreferredSize(new Dimension(30,30));
colorBox.setMaximumSize(new Dimension(30,30));
panText.setPreferredSize(new Dimension(100,15));
panText.setText(" - " + org.getName());
panText.setAlignmentX(Component.RIGHT_ALIGNMENT);
pan.add(colorBox);
pan.add(panText);
legend.add(pan);
}
legend.add(consolePanel);
for(int i=0; i<sizeY; i++)
{
for(int j=0; j<sizeX; j++)
{
gridPanels[i][j] = new JPanel();
if(organizmy[i][j]!=null)
gridPanels[i][j].setBackground(organizmy[i][j].getOrgColor());
else gridPanels[i][j].setBackground(Color.white);
boardPanel.add(gridPanels[i][j]);
}
}
System.setOut(printStream);
System.setErr(printStream);
frame.add(boardPanel);
frame.add(legend,BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Wirtualny świat");
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
worldFrame = frame;
}
And here is my Custom output Stream class which is used to print everything i print via System.out.println to my text Area:
public class CustomOutputStream extends OutputStream
{
private final JTextArea textArea;
public CustomOutputStream(JTextArea textArea)
{
this.textArea = textArea;
}
#Override
public void write(int b)
{
textArea.append(String.valueOf((char)b));
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}
Here is link to image what it looks like in GUI:
You need to remove this line from your code:
consoleOutput.setPreferredSize(new Dimension( 200,300));
Unfortunately, it prevents your JTextArea from being scrollable because you set static size to that element.
P.S. Stay away from Swing - there are better options in Java
It works for me.
import javax.swing.*;
public class Scrollin{
public static void main(String[] args){
JFrame frame = new JFrame("scrolling");
JTextArea area = new JTextArea(20, 20);
frame.add(new JScrollPane(area));
frame.setVisible(true);
frame.pack();
Timer t = new Timer( 150, evt->{
area.setCaretPosition( area.getDocument().getLength() );
area.append("word is born\n");
});
t.start();
}
}
As text is added, the window will scroll to the end provided the cursor is at the end of the document.
Maybe you can start with something as short as this to demonstrate your issue?

Scrollbar is not appearing

I have added some code for scrollbar which I got from questions asked by some other people on stackoverflow but I am not getting any scrollbar added to my JTextArea. I want to add scrollbar to JTextArea area2 in f2 frame.
import javax.swing.*;
import java.io.*;
import java.awt.event.*;
public class TextAreaExample implements ActionListener {
JFrame f1 = new JFrame("INPUT WINDOW");
JFrame f2 = new JFrame("FILE DATA OUTPUT");
JTextArea area1;
JTextArea area2;
JButton b;
TextAreaExample() {
area1 = new JTextArea();
area2 = new JTextArea();
JScrollPane scroll = new JScrollPane (area2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
b = new JButton("click Me");
b.setBounds(100, 95, 80, 30);
f1.add(b);
area1.setBounds(10, 30, 200, 60);
area2.setBounds(5, 5, 480, 480);
f1.add(area1);
f2.add(area2);
f2.add(scroll);
f1.setSize(300,140);
f2.setSize(510, 510);
f1.setLayout(null);
f2.setLayout(null);
f1.setVisible(true);
f2.setVisible(true);
b.addActionListener(this);
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b) {
String s1 = area1.getText();
String s2 = "";
try {
FileInputStream fin = new FileInputStream(s1);
BufferedInputStream bin = new BufferedInputStream(fin);
int i;
while((i = bin.read()) != -1) {
s2 = s2 + (char)i;
}
bin.close();
fin.close();
}catch(Exception a) {
System.out.println(a);
}
area2.setText(s2);
}
}
public static void main(String args[]) {
new TextAreaExample();
}
}
JScrollPane scroll = new JScrollPane (area2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
b = new JButton("click Me");
b.setBounds(100, 95, 80, 30);
f1.add(b);
area1.setBounds(10, 30, 200, 60);
area2.setBounds(5, 5, 480, 480);
f1.add(area1);
f2.add(area2);
First you create a JScrollPane using the JTextArea as a parameter, which is correct.
But then you add the text area to the frame, which is incorrect. Swing components can only have a single parent so the text area is removed from the scroll pane.
The scroll pane must be added to the frame.
f1.add(scroll);
Also, get rid of all the null layouts and setBounds() statements. Swing was designed to be used with layout managers. Read the section from the Swing tutorial on Layout Manager for more information and examples to get your started.
Now when you create the text area you can use:
JTextArea textArea = new JTextArea(5, 20);
to suggest the original size for the text area. Scrollbars will then appear when more than 5 lines of data is added.

JButton not responsive - have to click twice

I created a GUI using java swing and in a specific situation, the JButton is unresponsive and I have to click it twice. On the click, it takes the info in the textArea and sends it to a TextParser class to be parsed. If I type more stuff in the area after, and click the evaluateButton, it doesn't respond and I have to click it again to work. Does anyone know if this is a known bug or how I can fix this?
The code for the class is as follows.
/**
* Add the components to the GUI.
* #param pane - the pane for the GUI
*/
public static void addComponentsToPane(Container pane) {
pane.setLayout(new BorderLayout());
JPanel instructionsPanel = new JPanel();
JLabel instructions = new JLabel("Enter the email text below");
instructionsPanel.setBackground(Color.LIGHT_GRAY);
instructionsPanel.add(instructions);
pane.add(instructionsPanel, BorderLayout.NORTH);
JPanel textAreaPanel = new JPanel();
textAreaPanel.setBackground(Color.LIGHT_GRAY);
final JTextArea textArea = new JTextArea();
textArea.setBackground(Color.WHITE);
textArea.setMinimumSize(new Dimension(400,350));
textArea.setMaximumSize(new Dimension(400,350));
textArea.setPreferredSize(new Dimension(400,350));
textArea.setLineWrap(true);
Border border = BorderFactory.createLineBorder(Color.BLACK);
textArea.setBorder(border);
textArea.setMinimumSize(new Dimension(500, 200));
textArea.setFont(new Font("Serif", Font.PLAIN, 16));
textAreaPanel.add(textArea);
pane.add(textAreaPanel, BorderLayout.CENTER);
JPanel scoringPanel = new JPanel();
JButton evaluateButton = new JButton("Evaluate Email");
final JLabel scoreLabel = new JLabel("");
JButton uploadFileBtn = new JButton("Upload File");
JButton importTermsBtn = new JButton("Import Terms");
scoringPanel.add(evaluateButton);
scoringPanel.add(uploadFileBtn);
scoringPanel.add(importTermsBtn);
scoringPanel.add(scoreLabel);
pane.add(scoringPanel, BorderLayout.SOUTH);
evaluateButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
try {
String email = textArea.getText();
TextParser textParser = new TextParser(email);
double score = textParser.parse();
scoreLabel.setText(score+"");
} catch (Exception ex) {
System.out.println(ex);
}
}
});
uploadFileBtn.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
scoreLabel.setText("Feature not yet available.");
}
});
importTermsBtn.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
DatabaseInput d = new DatabaseInput();
d.main(null);
}
});
}
/**
* Create the GUI and show it.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("EmailGUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setLocationRelativeTo(null);
frame.setPreferredSize(new Dimension(500,500));
frame.setTitle("Email Text Input");
frame.setResizable(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setSize(screenSize.width, screenSize.height);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
My main method just calls createAndShowGUI(). I am new to StackOverflow so if I need to give more or less information in my post please let me know!
As Reimeus and Jason C said in the comments, I should have been using ActionListener which works perfectly.

JList not displaying any objects?

I've been trying to figure out how to use JList and I cant seem to get it to display an object into my GUI.
there's a class called Drawing that I'm trying to add to the JList and it just doesnt seem to show..
Any help would be greatly appreciated
here's my code:
public class DrawingDisplayer extends JPanel implements ActionListener, ListSelectionListener {
JLabel title;
JButton draw,pause,clear,
open,close,
lines,background;
JSlider speedSlider;
JProgressBar progress;
Drawing drawing;
JFileChooser chooser;
JList fileList;
DefaultListModel listModel;
JPanel drawPanel;
JScrollPane scrollPane;
public DrawingDisplayer(){
title = new JLabel("The Drawing Displayer");
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(new Font("Serif", Font.BOLD, 24));
draw = new JButton("Draw");
pause = new JButton("Pause");
clear = new JButton("Clear");
speedSlider = new JSlider();
progress = new JProgressBar();
open = new JButton("Open Drawing");
close = new JButton("Close Drawing");
listModel = new DefaultListModel();
fileList = new JList(listModel);
fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fileList.addListSelectionListener(this);
fileList.setVisibleRowCount(10);
scrollPane = new JScrollPane(fileList);
scrollPane.setPreferredSize(new Dimension(200,250));
lines = new JButton("Lines");
background = new JButton("Background");
setLayout(new BorderLayout());
//Draw Panel
drawPanel = new JPanel();
drawPanel.setBorder(BorderFactory.createTitledBorder("Drawing Area"));
//Drawing Speed
JPanel drawSpeed = new JPanel();
drawSpeed.setPreferredSize(new Dimension(300,200));
drawSpeed.setBorder(BorderFactory.createTitledBorder("Drawing Speed"));
drawSpeed.add(draw);
drawSpeed.add(pause);
drawSpeed.add(clear);
drawSpeed.add(speedSlider);
drawSpeed.add(progress);
//File Options
JPanel fileOptions = new JPanel();
fileOptions.setPreferredSize(new Dimension(300,350));
fileOptions.setBorder(BorderFactory.createTitledBorder("File Options"));
open.addActionListener(this);
close.addActionListener(this);
fileOptions.add(open);
fileOptions.add(close);
fileOptions.add(fileList);
fileOptions.add(scrollPane);
//Colour Options.
JPanel colourOptions = new JPanel();
colourOptions.setPreferredSize(new Dimension(300,200));
colourOptions.setBorder(BorderFactory.createTitledBorder("Colour Options"));
colourOptions.add(lines);
colourOptions.add(background);
//Control Panel
JPanel controlPanel = new JPanel();
controlPanel.setPreferredSize(new Dimension(325,200));
controlPanel.add(drawSpeed);
controlPanel.add(fileOptions);
controlPanel.add(colourOptions);
chooser = new JFileChooser(".");
add(title, BorderLayout.NORTH);
add(controlPanel,BorderLayout.WEST);
add(drawPanel,BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == open){
chooser = new JFileChooser(".");
if(chooser.showOpenDialog(null) == chooser.APPROVE_OPTION){
drawing = new Drawing(chooser.getSelectedFile());
fileList.add(drawing);
listModel.addElement("test");
}
}
else if (e.getSource() == close){
}
}
public void valueChanged(ListSelectionEvent e) {
}
public static void main(String[] args){
DrawingDisplayer panel = new DrawingDisplayer();
JFrame frame = new JFrame("drawing");
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
To understand the problem you're having you need to understand that a component can only reside within a single container (it can only have a single parent).
If you try and add the component to another container, it is removed from the first before been added to the second.
So, in your code you do...
fileList = new JList(listModel);
//...
// Add fileList as the view for the scrollpane...
scrollPane = new JScrollPane(fileList);
scrollPane.setPreferredSize(new Dimension(200, 250));
//...
// Remove fileList from the scrollpane and add it to fileOptions...
fileOptions.add(fileList);
fileOptions.add(scrollPane);
...So, basically, you've started out well, but ended up removing the fileList from the scrollPane and adding it to the fileOptions instead, then added the (now empty) scrollPane to the fileOptions as well...
Remove fileOptions.add(fileList); and it should work as you expect it...
You might also want to take a look at Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?.
You can control the size of the JScrollPane by using things like setVisibleRowCount and appropriate cell renderers ...
The default rendering of an object added to the ListModel is to simple display the toString() of the object.
If you are adding a custom object, then you need to provide a custom renderer. Read the section from the Swing tutorial on How to Use Lists, especially the section on Writing a Custom Cell Renderer for more information on this concept.

Make a JtextPane looks like eBook

I have a text editor with Netbeans where i load a text to a JtextPane. If text is too big u can read it with the help of an horizontal scroll.Is there any way to split the text into pages of 24 lines for example so that every page is visible without scrolling and use a next page button for changing page (like eBooks do)?
It is easier to use a JTextArea to do this because you can easily specify the number of lines to display each time you scroll to a new page.
The basic solution is to add a text area to a scroll pane than then hide the scrollbars. You can then use the defaults Actions of the vertical scrollbar to do the scrolling for you. The code below uses code from the Action Map Action blog entry to easily create an Action that you can add to a JButton:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class TextAreaScroll extends JPanel
{
private JTextArea textArea;
public TextAreaScroll()
{
setLayout( new BorderLayout() );
textArea = new JTextArea(10, 80);
textArea.setEditable( false );
JScrollPane scrollPane = new JScrollPane( textArea );
scrollPane.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_NEVER );
add(scrollPane);
JButton load = new JButton("Load TextAreaScroll.java");
load.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
FileReader reader = new FileReader( "TextAreaScroll.java" );
BufferedReader br = new BufferedReader(reader);
textArea.read( br, null );
br.close();
}
catch(Exception e2) { System.out.println(e2); }
}
});
add(load, BorderLayout.NORTH);
// Add buttons to do the scrolling
JScrollBar vertical = scrollPane.getVerticalScrollBar();
Action nextPage = new ActionMapAction("Next Page", vertical, "positiveBlockIncrement");
nextPage.putValue(AbstractAction.MNEMONIC_KEY, KeyEvent.VK_N);
JButton nextButton = new JButton(nextPage);
Action previousPage = new ActionMapAction("Previous Page", vertical, "negativeBlockIncrement");
previousPage.putValue(AbstractAction.MNEMONIC_KEY, KeyEvent.VK_N);
JButton previousButton = new JButton(previousPage);
JPanel south = new JPanel();
add(south, BorderLayout.SOUTH);
south.add( previousButton );
south.add( nextButton );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TextAreaScroll());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Categories