JScrollPanes, JTextAreas, and maximum sizes - java

Context: In a flashcard application, I have a view for a CardData (a data structure representing one side of a flashcard). It has, in its most basic form, a String text. The view (known as CardDataView) consists of the text in an uneditable JTextArea inside a JScrollPane.
At one point, I need to line up (vertically) a bunch of these CardDataViews, so I put them in a vertical Box.
Here's the problem: when I expand the window from it's "preferred" size (as determined by pack) and then size it back down, the JScrollPane adds a horizontal scroll bar and allows me to scroll horizontally in the text field. Essentially, it's sizing up the text area when it shouldn't be.
Here's my code (stripped down and simplified):
public class DebugTest {
public static void main(String[] args) {
CardDataView cdv = new CardDataView(new CardData(
"Lorem ipsum dolor sit amet filler filler filler"));
JFrame frame = new JFrame();
frame.add(new JScrollPane(cdv), BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class CardData {
private String text; // text on the card
/*
* NOTE: This class has been simplified for SSCCE purposes. It's not really
* just a String field in production; rather, it has an image and other
* properties.
*/
public CardData(String text) {
super();
this.text = text;
}
public String getText() {
return text;
}
}
class CardDataView extends Box {
private JTextArea txtrText; // the text area for the text
/*
* NOTE: As with CardData, this class has been simplified. It's not just a
* JTextArea; it's also an ImageView (custom class; works fine), among other
* things.
*/
public CardDataView(CardData data) {
super(BoxLayout.Y_AXIS);
txtrText = new JTextArea();
txtrText.setLineWrap(true);
txtrText.setRows(3);
txtrText.setEditable(false);
txtrText.setWrapStyleWord(true);
final JScrollPane scrollPane = new JScrollPane(txtrText);
add(scrollPane);
txtrText.setText(data.getText());
}
}
Now, something that really confuses me (unless I'm going about it wrong) is that if I essentially inline the data and view classes, by just creating a text area with text and a scroll pane (even with setting the same number of rows, same wrap settings, etc.), it behaves as expected. What could be happening?
Concerns:
- All imports are in order.
- If you're wondering why CardLayoutView is a Box: in production, it has more than just a text box. The same error happens when it's a JPanel and I setLayout instead of super.
- The same glitch happens if I don't use the CardData class at all (and set the text area's text manually).
Any ideas?

Putting my comment to answer :
Use GridBagLayout with GridBagConstraints.VERTICAL/NONE as the gridBagLayoutObject.fill value, instead of BoxLayout. Since when adding components to the CENTER of the JFrame, BorderLayout never respects the preferredSize() for the CENTER component. Hence try to add your stuff to a JPanel and then put this JPanel at the CENTER of the JFrame.

Related

JTextArea is repositioning and reziseing itself

i just started to use Java to build a GUI. Now i ran in an error that causes very strange behaviour with the JTextArea. I used this to create the TextArea:
`
public class gui{
JTextArea ausgabe;
public gui(){
//Some other Stuff in here
//
//
ausgabe = new JTextArea("Test \n Text",15,50);
ausgabe.setSize(110, 170);
ausgabe.setVisible(true);
mainFrame.add(ausgabe);
ausgabe.setLocation(170,20);
ausgabe.setEnabled(false);
}
}
Now until this point everything just works fine. But I want another method to change the text of the area (with ausgabe.setText("String");) the area relocates itself to x,y = 0 of the JFrame and layers itself above all other JFrame elements. Thanks for help!
I highly recommend not trying to fight the Layout Managers
For a simple fix, use the default layout manager for a JFrame like so
public class gui
{
JTextArea ausgabe;
public gui()
{
ausgabe = new JTextArea("Test \n Text");
mainFrame.add(ausgabe, BorderLayout.CENTER);
}
}
You also don't need to set Swing Components other than the JFrame itself visible.
You can then call setText() in an action listener or such and the TextArea should stay in the same position.

How to make text pane accept pastes but block typing

My Goal is :
having a text pane where user can paste text only(with OS not a button!!!) and can't type in to the pane
because: can't have submit button (this is a must requirement - I know that it's not logical)
after pasting: the text-pane becomes not editable for user, and the program will change background at specific chars.
after button "clear filed" pressed - the program clears the pane and returns to initial state
My Problem: How to make text pane accept pastes but block typing
so far I made only JPanel with the text pane itself and all the controls will be in different JPanel
public class textPanel extends JPanel{
private JTextPane text;
public textPanel ()
{
setLayout(new BorderLayout());
text = new JTextPane(); //12,81
text.setBorder(BorderFactory.createLoweredBevelBorder());
add(text,BorderLayout.CENTER);
StyledDocument doc = text.getStyledDocument();
setBackground(Color.LIGHT_GRAY);
setPreferredSize(new Dimension(1000, 210));
}
thanks for help
Override public void paste() method of your. By default your JTextPane is not editable (setEditable(false)).
The paste() method's source in JTextComponent is
public void paste() {
if (isEditable() && isEnabled()) {
invokeAction("paste", TransferHandler.getPasteAction());
}
}
So you just make it editable, call super.paste(), and set the editable=false back after the super call.

JScrollPanel JPanel and Layouts

What I have:
A split panel with a scroll panel in the right part.
In this scroll panel, I have a JPanel.
I want to have in this JPanel a series of others JPanels stacked one under the other one.
I set the Layout to be a BoxLayout. Now it stacks multiple JPanels, but I have 2 problems:
If my content from JPanel take less space then my frame, then will be lot of space between Jpanels.
If my content from JPanel it's bigger then my frame, the Pannels will go over each other and my scroll from scrollPanel wont activate.
frame = new Frame();
splitPane = new SplitPane();
scrollPane = new ScrollPane();
frame.add(splitPane);
scrollPane.setViewportView(new Lesson());
splitPane.setRightComponent(scrollPane);
splitPane.setLeftComponent(new JTree());
Where Frame, SplitPane, ScrollPane() are classes that extends JFrame, JSplitPane, JScrollPane. Atm they only have a constructor, after it will work, I want to make some customization there.
public class Lesson extends JPanel {
private static final long serialVersionUID = 1L;
public Lesson() {
customize();
String text = "text from pictures";
add(new Paragraph(text));
add(new Paragraph(text));
}
private void customize() {
BoxLayout boxLayout = new BoxLayout(this, BoxLayout.PAGE_AXIS);
setLayout(boxLayout);
}
}
public class Paragraph extends JPanel {
private static final long serialVersionUID = 1L;
public Paragraph(String text) {
setLayout(new FlowLayout(FlowLayout.LEFT));
setPreferredSize(new Dimension());
StringTokenizer splitStringTokenizer = new StringTokenizer(text, " ");
while(splitStringTokenizer.hasMoreTokens()){
add(label(splitStringTokenizer.nextToken().toString()));
}
}
private JLabel label(String string){
JLabel jlabel= new JLabel(string);
return jlabel;
}
}
Any hints about how I can resolve this ? Ty in advance.
A BoxLayout respects the maximum and minimum sizes of components added to it. You are using a FlowLayout o the Paragraph panel. The preferred size is always one line of components.
The panel will shrink until there is only one line displayed or grow to occupy all the space.
When there is more space the panels are allowed to grow.
Override the getMaximum/MinimumSize() of your Paragraph panel to return the preferred size.
The question is why are you using a panel of labels to display text. Why are you not using a text area.
Or another option may be to use the WrapLayout which will wrap components automatically and recalculate the preferred size based on the wrapping. You will still want to override the getMinimum/Maximum size calculations to return the preferred size.
I want later to add some mouse listener to some of jlabels.
Why? Again if you use a text area, you can add the MouseListener directly to the text area and then you can use the caret position (or convert the mouse position to an offset in the text area) to determine what word the mouse is over and then do your processing.

Activity Stream- Producing X amount of objects in a panel on app load

Just wondering if you could help wanting to produce an activity stream in Java, the idea was to have a JLabel and text area followed by a divider be displayed on a screen and then repeated X amount of times according to what data was in a database.
What I was wondering is how could I possibly repeat the placing the jlabel, text area, and diveder on the screen above the last rendered objects on the fly and all displayed correctly no matter the size of the text area of each set of object sort of like the image below.
Hope I made it clear as I could thanks
Just provide your own version of a JPanel containing all these things and place them in a scrollpane that will care about having a long list of these panels..
class MyPanel extends JPanel
{
ImageIcon icon;
JTextArea textArea;
MyPanel(ImageIcon icon, String text)
{
this.icon = icon;
this.setPreferredSize(/*max size of your panel */)
textArea = new JTextArea(10, 50);
textArea.append(text);
//the default manager will be a flow layout for single jpanels
this.add(icon);
JScrollPane sp = new JScrollPane(textArea);
sp.setPreferredSize(new Dimension(/* size of your text label */));
this.add(new JScrollPtextArea);
}
}
class MyContainer extends JFrame
{
JPanel container;
JScrollPane spContainer;
MyContainer()
{
container = new JPanel()
container.setGridLayout(100,1); //100 elements max
spContainer = new JScrollPane(container);
spContainer.setPreferredSize(/* max size of whole thing */)
this.add(spContainer);
pack();
}
void addElement(MyPanel panel)
{
container.add(panel);
this.pack();
}
}
It's not fully working (I just wrote it) but it should give you the idea..

JEditorPane inside JScrollPane not resizing as needed

I am implementing a Comment box facility in my application which user can resize using mouse. This comment box contains a scrollpane which instead contains a JEditorPane in which user can insert comment. I have added the editor pane inside a scroll pane for the following reason:
auto scolling of jeditorpane
When the user resizes the comment box, I am setting the desired size for JScrollPane and the JEditorPane. When the user is increasing the size of the comment box, the size of these components are increasing as desired but when the size of the comment box is decreased, the size of the JEditorPane does not decrease even after setting the size. This leads to the scrollbars inside the scrollpane.
I tried using setPreferrredSize, setSize, setMaximumSize for JEditorPane. Still the size of the editor pane is not reducing. I tried calling revalidate() or updateUI() after the setting of size but no use.
I am using Java 1.4.2.
Please provide me some insight....
I realise this is long since answered, but for future reference all you need to do is override the getScrollableTracksViewportWidth() to always return true, eg.
JEditorPane pane = new JEditorPane() {
public boolean getScrollableTracksViewportWidth() {
return true;
}
};
panel.add(new JScrollPane(pane));
Actually it is possible, luiscubal. Here is how,
To the JScrollPane add a ComponentListener for resize events
public static void main(String...args) {
//our test frame
JFrame frame = new JFrame("JEditorPane inside JScrollPane resizing");
frame.setLayout(new BorderLayout());
//our editing pane
final JEditorPane editor = new JEditorPane();
//our simple scroll pane
final JScrollPane scroller = new JScrollPane(editor);
//NOTE: this is the magic that is kind of a workaround
// you can also implement your own type of JScrollPane
// using the JScrollBar and a JViewport which is the
// preferred method of doing something like this the
// other option is to create a JEditorPane subclass that
// implements the Scrollable interface.
scroller.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
editor.setSize(new Dimension(
scroller.getWidth()-20,
scroller.getHeight()-20));
}
});
//just use up the entire frame area.
frame.add(scroller, BorderLayout.CENTER);
//quick and dirty close event handler
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(320, 240); //something not too big
frame.setLocationRelativeTo(null); //centers window on screen
frame.setVisible(true); // normally done in a SwingUtilities.invokeLater
}
Look luiscubal it is possible. Don't be so quick to announce things in Java as not possible. The swing api is quiet flexible and can do a lot of the work for you. However, if you use JComponents in ways they weren't made to be used you will end up with problems and have two options.
subclass subclass subclass basically create your own component.
find a work around, like the above solution.
Decreasing the size of a JEditorPane in a JScrollPane and then reducing it, is not possible.
You may want to use a JTextArea instead.

Categories