Working on mixer app with multiple sliders. I want to create multiple instances of the same slider side by side for as many channels as I determine (1-16). This will very so I want to just create new side by side instances of VolumeControl from left to right. For now I just they can all work from the same inputs, listeners, etc. I'm just working on getting them to display. Here's what I have in order to create a single instance of JSlider (mostly taken from a demo). NOTE: I'm coming from Android development so I could be going the complete wrong, complicated way!
public class VolumeControl extends JPanel implements ChangeListener {
...
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(VolumeControl::createAndShowGUI);
}
public VolumeControl () {
super(new BorderLayout());
...
JSlider volumeControl = new JSlider(JSlider.VERTICAL,
VOLUME_MIN, VOLUME_MAX, currentVolume);
volumeControl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
add(volumeControl, BorderLayout.LINE_START);
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Volume Control");
VolumeControl animator = new VolumeControl();
frame.add(animator, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
Simply create one or more factory methods which you can use to create and configure the sliders the way you want...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new VolmeControlPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class VolmeControlPane extends JPanel {
protected static final int VOLUME_MIN = 0;
protected static final int VOLUME_MAX = 100;
protected static final String SLIDER_CONTROL_KEY = "Slider.controlKey";
public VolmeControlPane() {
setLayout(new GridBagLayout());
JSlider[] sliders = makeSliders(16);
for (JSlider slider : sliders) {
add(slider);
}
}
public JSlider[] makeSliders(int count) {
JSlider[] sliders = new JSlider[count];
for (int index = 0; index < count; index++) {
sliders[index] = makeSlider(VOLUME_MIN, VOLUME_MAX, VOLUME_MIN + (VOLUME_MAX / 2));
sliders[index].putClientProperty(SLIDER_CONTROL_KEY, index);
}
return sliders;
}
public JSlider makeSlider(int min, int max, int value) {
JSlider volumeControl = new JSlider(JSlider.VERTICAL,
min, max, value);
volumeControl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
return volumeControl;
}
}
}
One little trick I added was using putClientProperty to provide a key to identify the slider, you could also use setName. The idea here is when you attach a listener, you can interegate the slider for the key and identify which channel it represents, as a an idea
Related
unfortunately I can't handle the change of txt when the button is clicked, I try to write a txt and overtime that I click the button, this txt value should change and allotting seems right, the only problem is that the printed number is not obvious and it seems some part of previous txt remains with it.
package berGenerator;
import java.awt.EventQueue;
public class sscce {
private JFrame frame;
private final Action action = new SwingAction();
private static int i = 555;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
sscce window = new sscce();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public sscce() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 550, 401);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton Next = new JButton("Next");
Next.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
Next.setAction(action);
Next.setBounds(167, 290, 198, 64);
frame.getContentPane().add(Next);
}
private class SwingAction extends AbstractAction {
public SwingAction() {
putValue(NAME, "Next Timeslot/scheduler");
putValue(SHORT_DESCRIPTION, "Some short description");
}
public void actionPerformed(ActionEvent e) {
i = i+1;
frame.getContentPane().validate();
frame.getContentPane().repaint();
String from = String.valueOf(i);
System.out.println("sw is: "+from);
JTextArea TextArea11 = new JTextArea("");
TextArea11.setText(from);
TextArea11.setForeground(Color.GREEN);
TextArea11.setBounds(6, 66, 87, 16);
frame.getContentPane().add(TextArea11);
}
}
}
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify.
Layout managers are fundamental to the Swing API, you should make the time to learn how to use them, they will solve more problems than you think they create.
See Laying Out Components Within a Container for more details.
You're creating multiple instances of JTextArea and adding to the frame, but you're not removing any, you're running into a potential z-ordering problem at best and a major resource management issue at worst.
Instead, simply create a single instance of JTextArea, add it to the frame (just like you did your button) and simply update it when the Action is triggered, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import static javax.swing.Action.NAME;
import static javax.swing.Action.SHORT_DESCRIPTION;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Test {
private JFrame frame;
private final Action action = new SwingAction();
private static int i = 555;
private JTextArea textArea;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea = new JTextArea(10, 20);
textArea.setText(String.valueOf(i));
frame.add(new JScrollPane(textArea));
JButton next = new JButton("Next");
next.setAction(action);
frame.getContentPane().add(next, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
}
private class SwingAction extends AbstractAction {
public SwingAction() {
putValue(NAME, "Next Timeslot/scheduler");
putValue(SHORT_DESCRIPTION, "Some short description");
}
public void actionPerformed(ActionEvent e) {
i = i + 1;
String from = String.valueOf(i);
System.out.println("sw is: " + from);
textArea.setText(from);
textArea.setForeground(Color.GREEN);
}
}
}
I'm trying to have a JPanel of varying size (potentially much wider than the standard screen) inside of a JScrollPanel. Currently it works out great, and I have configured the scrollbars to work fine manually, however I would like the JPanel to "scroll" constantly to the left, so that over time the whole thing is displayed. All of the answers I found are specific to JTextArea and use Carets, or use rectToVisible. Neither of these will work because I'm trying to scroll internally to a single JPanel.
I've included what I believe to be all of the relevant code below.
center is the JPanel (of which Grid is a subclass, used to paint specifically a grid with some specific cells colored) with a BorderLayout that I would like to autoscroll.
public GuiViewFrame(Song playMe) {
String[][] songArray = playMe.to2DArray();
this.displayPanel = new ConcreteGuiViewPanel(playMe);
main = new JPanel();
main.setLayout(new BorderLayout());
displayPanel.setLayout(new BorderLayout());
center = new Grid(playMe);
labels = new Labels(playMe);
horiz = new Horiz(playMe);
center.setPreferredSize(new Dimension(10 * songArray.length, 10 * songArray[0].length));
horiz.setPreferredSize(new Dimension(10 * songArray.length, 10));
horiz.setVisible(true);
main.add(center, BorderLayout.CENTER);
main.add(horiz, BorderLayout.NORTH);
scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(scroll, BorderLayout.CENTER);
labels.setPreferredSize(new Dimension(20, 10 * songArray[0].length));
labels.setVisible(true);
add(labels, BorderLayout.WEST);
JScrollBar horiz = scroll.getHorizontalScrollBar();
InputMap im = horiz.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("RIGHT"), "positiveUnitIncrement");
im.put(KeyStroke.getKeyStroke("LEFT"), "negativeUnitIncrement");
im.put(KeyStroke.getKeyStroke("HOME"), "minScroll");
im.put(KeyStroke.getKeyStroke("END"), "maxScroll");
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.pack();
}
The project as a whole is to generate a view for playing music that combines MIDI and a GUI, but right now once MIDI plays enough of the song, the relevant notes are off screen. I would like to scroll at a rate to keep pace with MIDI.
You can set the value of the horizontal scrollbar to control what is currently visible:
JScrollBar horizontal = scroll.getHorizontalScrollBar();
horizontal.setValue( horizontal.getValue() + ??? );
You would need to use a Swing Timer to schedule the scrolling at an appropriate interval.
Simple example of using a Timer to scroll text:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class TimerTest extends JPanel implements ActionListener
{
JLabel timeLabel;
JLabel scrollLabel;
public TimerTest()
{
setLayout( new BorderLayout() );
timeLabel = new JLabel( new Date().toString() );
add(timeLabel, BorderLayout.NORTH);
scrollLabel = new JLabel( "Some continuously scrolling text!! " );
add(scrollLabel, BorderLayout.SOUTH);
int time = 1000;
javax.swing.Timer timer = new javax.swing.Timer(time, this);
timer.setInitialDelay(1);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
timeLabel.setText( new Date().toString() );
String oldText = scrollLabel.getText();
// Scroll right to left
String newText = oldText.substring(1) + oldText.substring(0, 1);
// Scroll left to right
// int length = oldText.length();
// String newText = oldText.substring(length-1, length)
// + oldText.substring(0, length-1);
scrollLabel.setText( newText );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TimerTest() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
One possible solution might be to take advantage of JComponent#scrollRectToVisible and a Swing Timer
For example...
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScrollTest {
public static void main(String[] args) {
new ScrollTest();
}
public ScrollTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(new TestPane()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JViewport viewport = (JViewport) getParent();
Rectangle viewRect = viewport.getViewRect();
if (viewRect.x + viewRect.width < getWidth()) {
viewRect.x += 2;
scrollRectToVisible(viewRect);
} else {
((Timer)e.getSource()).stop();
}
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawLine(0, 0, getWidth(), getHeight());
g2d.dispose();
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width <= getParent().getSize().width;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return getPreferredSize().height <= getParent().getSize().height;
}
}
}
so I have a frame 1 and frame 2 in the frame 1 by having 4 and has 1 JButton JTextField at 4 JTextField a user to input an integer value .. after the user input, the user presses a JButton and JFrame will feature 2 ..
and in the second frame I have 1 JTextArea which will print out a value that a user input
so how to send values from frame 1 to frame 2?
actually in this project I've given constructor in which I made into a class and in Jframe1 "coba.java" I make new objeck with this code:
coba ar = new coba();
in a Jframe1 I have a method in which DDA has a code:
double X0 = Double.parseDouble (x0.getText ());
double X1 = Double.parseDouble (x1.getText ());
double Y0 = Double.parseDouble (y0.getText ());
double Y1 = Double.parseDouble (y1.getText ());
int no = 1;
ar.X0 = X0;
ar.X1 = X1;
ar.Y0 = Y0;
ar.Y1 = Y1;
You can make a thread that can check some static variables for changes and update the frames accordingly. For example somewhere after showing the two frames:
new Thread(new Runnable(){
public void run(){
try{
while(true){
if(coba.HASNEWVALUE){
updateFrame(); // some function that does the updating and communicating
coba.HASNEWVALUE = false;
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}).start();
Whenever you want to pass a new value, set the appropriate values and set coba.HASNEWVALUE to true, this way your frame will fetch the required update automatically through the updateFrame() function everytime coba.HASNEWVALUE is TRUE.
Basically, Frame 1 will need a reference to Frame 2 either directly or indirectly via some kind of observer implementation...
This way, all you need to do is provide some kind of method in Frame 2 that will allow you to pass the information you need to it so it can update the text area in question.
Personally, I prefer to use interfaces for this, as it prevents the caller from messing with things it shouldn't
Oh, and you might also want to have a read through The Use of Multiple JFrames: Good or Bad Practice?
For example...
The NotePad interface prevents SecretaryPane from making changes to the underlying implementation, because the only method it actually knows about is the addNote method
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CrossCalling {
public static void main(String[] args) {
new CrossCalling();
}
public CrossCalling() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
NotePadPane notePadPane = new NotePadPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SecretaryPane(notePadPane));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JFrame noteFrame = new JFrame("Testing");
noteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
noteFrame.setLayout(new BorderLayout());
noteFrame.add(notePadPane);
noteFrame.pack();
noteFrame.setLocation(frame.getX(), frame.getY() + frame.getHeight());
noteFrame.setVisible(true);
}
});
}
public interface NotePad {
public void addNote(String note);
}
public class SecretaryPane extends JPanel {
private NotePad notePad;
public SecretaryPane(NotePad pad) {
this.notePad = pad;
setLayout(new GridBagLayout());
JButton btn = new JButton("Make note");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pad.addNote(DateFormat.getTimeInstance().format(new Date()));
}
});
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class NotePadPane extends JPanel implements NotePad {
private JTextArea ta;
public NotePadPane() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void addNote(String note) {
ta.append(note + "\n");
}
}
}
I've seen a number of questions that ask how to rotate a JLabel or image at an arbitrary angle. All I need to do is rotate my text field 90 degrees, but I haven't found an easier way specifically for that angle. I thought I copied the answers correctly, but my text field is not rotating.
Here's an SSCCE of what I'm doing:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class VerticalRotationSSCCE {
private static class VerticalTextField extends JTextField {
private static final long serialVersionUID = 1L;
public VerticalTextField(String text) {
super(text);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int cx = getWidth() / 2;
int cy = getHeight() / 2;
g2.rotate(1/2 * Math.PI, cx, cy);
super.paintComponent(g2);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.getContentPane().add(new VerticalTextField("Foo"));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
What am I missing from the answers on how to rotate components?
Actually, yes, it can be done, but will require some additional libraries and access to some source code which has vanished off the net.
Using JXLayer, it is possible to transform live components at runtime...
public class JLayerTransform {
public static void main(String[] args) {
new JLayerTransform();
}
public JLayerTransform() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ExamplePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ExamplePane extends JPanel {
private JSlider slider;
private FieldPane fieldPane;
private DefaultTransformModel transformModel;
public ExamplePane() {
setLayout(new BorderLayout());
slider = new JSlider(0, 360);
slider.setValue(0);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
transformModel.setRotation(Math.toRadians(slider.getValue()));
}
});
fieldPane = new FieldPane();
transformModel = new DefaultTransformModel();
transformModel.setRotation(Math.toRadians(0));
transformModel.setScaleToPreferredSize(true);
JXLayer<JComponent> rotatePane = TransformUtils.createTransformJXLayer(fieldPane, transformModel);
add(slider, BorderLayout.NORTH);
add(rotatePane);
}
}
public class FieldPane extends JPanel {
public FieldPane() {
setLayout(new GridBagLayout());
JTextField field = new JTextField(10);
field.setText("Hello world");
add(field);
}
}
}
Caveats
This requires JXLayer (I was using version 3), SwingX (I was using version 1.6.4) and Piet Blok's excellent examples, which no longer seem to be available on the net...
I've put all the source code of JXLayer (version 3) and Piet's examples into a single zip and I would suggest, if you are interested, you grab a copy and store it some where safe.
You can't usefully rotate interactive components without also transforming the mouse coordinates, but you can rotate the graphics context to render non-interactive components like JLabel, as shown here.
In your example, 1/2 * Math.PI != Math.PI / 2.
I start off by creating a JTextArea of a specific size. The user can add text within it but it will get cut off if it becomes too long (vertically or horizontally). I want the JTextArea to automatically expand or contract (for deletion of text).
I may allow users to change font and font size in the future, so it would be good if I could avoid making things increase/decrease by a certain size.
I am currently using bounds to size my JTextArea. Perhaps I should size by rows and columns and use a listener and act appropriately?
thanks in advance!
I can't imagine why you'd want to do this, why not put a JTextArea in a JScrollPane, but ok, i'll play along... Maybe something like this:
import java.awt.Container;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
public class Expander extends JFrame {
private final JTextArea area;
private int hSize = 1;
private int vSize = 1;
public Expander() {
Container cp = getContentPane();
cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
cp.add(Box.createHorizontalGlue());
area = new JTextArea(vSize, hSize);
cp.add(area);
cp.add(Box.createHorizontalGlue());
area.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
adjust();
}
#Override
public void removeUpdate(DocumentEvent e) {
adjust();
}
#Override
public void changedUpdate(DocumentEvent e) {
adjust();
}
});
pack();
}
private void adjust() {
int maxColumns = getMaxColumns();
if ((area.getLineCount() != vSize) || (maxColumns != hSize)) {
hSize = maxColumns;
vSize = area.getLineCount();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
area.setColumns(hSize);
area.setRows(vSize);
Expander.this.doLayout();
Expander.this.pack();
}
});
}
}
private int getMaxColumns() {
int startOffset = 0;
int maxColumns = 0;
for (int i = 0; i < area.getLineCount(); i++) {
try {
int endOffset = area.getLineEndOffset(i);
int lineSize = endOffset - startOffset;
if (lineSize > maxColumns) {
maxColumns = lineSize;
}
startOffset = endOffset;
} catch (BadLocationException ble) {
}
}
return maxColumns;
}
public static void main(String[] args) {
Expander e = new Expander();
e.setLocationRelativeTo(null);
e.setVisible(true);
}
}
I second the advice to simply put the JTextArea in a JScrollPane and let this take care of extra text. Also and perhaps most importantly, don't set the bounds of the JTextArea because if you do this, you constrain it to be a certain size and that's not what you want to have happen. Instead initialize your JTextArea with two int constants to represent the number of rows and columns that should be visualized and then place it in a JScrollPane. Also be sure to read up on using the layout managers so you can avoid setting the size of your JScrollPane too!
Edit: on testing, it seems that setPreferredSize is more dangerous to a JTextArea than setSize.
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
public class ConstrainedTextArea extends JPanel {
private JTextArea textArea1, textArea2, textArea3;
public ConstrainedTextArea() {
textArea1 = new JTextArea(20, 30);
textArea2 = new JTextArea();
textArea3 = new JTextArea();
textArea2.setPreferredSize(new Dimension(300, 300));
textArea3.setSize(textArea3.getPreferredSize());
setLayout(new GridLayout(1, 0));
add(new JScrollPane(textArea1));
add(new JScrollPane(textArea2));
add(new JScrollPane(textArea3));
}
private static void createAndShowUI() {
JFrame frame = new JFrame("ConstrainedTextArea");
frame.getContentPane().add(new ConstrainedTextArea());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
also, see GrowingTextAreaExample