0

I have a JXTaskPaneContainer on the right hand side of my JFrame which contains hyperlinks and labels. The window's main parts should be:

  • a large area on the left for the text
  • a smaller area on the right with the messages and the actions

Now, the problem is that adding a lot of new elements causes the container to grow to the left and over the text:

enter image description here

It gets even weirder when having the JXTaskPaneContainer inside a javax.swing.JScrollPane (video/yt).

The problem seems to lie with the JXLabel. I suspect it's the word wrap? Any ideas how to fix this?

[Example] Self-contained example as per request. Full source on github.

package layoutproblemSSCEC;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXLabel;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.JXTaskPaneContainer;

public class SwingWindow {

    private JFrame frame;
    String dolorem = "Sed ut perspiciatis unde omnis iste natus error sit "
            + "voluptatem accusantium doloremque laudantium, totam rem aperiam, "
            + "eaque ipsa quae ab illo inventore veritatis et quasi architecto "
            + "beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem "
            + "quia voluptas sit aspernatur aut odit aut fugit, sed quia "
            + "consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. "
            + "Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, "
            + "consectetur, adipisci velit, sed quia non numquam eius modi tempora "
            + "incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut "
            + "enim ad minima veniam, quis nostrum exercitationem ullam corporis "
            + "suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? "
            + "Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse "
            + "quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat "
            + "quo voluptas nulla pariatur?";

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    SwingWindow window = new SwingWindow();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public SwingWindow() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JXTaskPaneContainer panels = new JXTaskPaneContainer();
        JScrollPane scrollpanel = new JScrollPane(panels);

        Container content = frame.getContentPane();
        content.add(new JTextArea(dolorem), BorderLayout.CENTER);
        content.add(scrollpanel, BorderLayout.EAST);
        content.add(new JXButton(new AbstractAction("Click me") {

            public void actionPerformed(ActionEvent arg0) {
                JXTaskPane panel = new JXTaskPane("test");
                JXLabel lbl = new JXLabel(dolorem);
                lbl.setLineWrap(true);
                panel.add(lbl);
                panels.add(panel);
            }
        }), BorderLayout.NORTH);

        panels.add(new JXTaskPane("Click the button, then resize"));
    }

}
Jonny
  • 1,453
  • 16
  • 25
  • 1
    check the layoutManager - taskPane (or container, forgot the details) needs a manager that respects prefSize. If that doesn't help, please post a SSCCE to demonstrate the problem – kleopatra Feb 23 '14 at 12:25
  • Thanks. I'll have a go trying GridBagLayout. – Jonny Feb 23 '14 at 20:04
  • repeating: show a SSCCE that demonstrates the problem - I'm pretty sure you'll get a concise answer ;-) – kleopatra Feb 24 '14 at 00:08
  • Done. :) See the full code after the link. That's as concise as I could manage. I think Maven will take care of the dependency (swingx-all-1.6.5-1) if you clone it in Eclipse. – Jonny Feb 24 '14 at 03:05
  • no, that's not SSCCE: it's neither short nor standalone nor posted _here_ ;-) Shouldn't take more than 50 - 80 lines of code to reproduce a simple layout problem. Good to know your swingx version, though, so I can run your future SSCCE against the correct one. – kleopatra Feb 24 '14 at 07:56
  • Alright, posted the full 76 lines. The interesting bits are still near initialize(). – Jonny Feb 24 '14 at 11:48
  • cool- but now I'm really confused ;-) The example doesn't fit your description of your problem: where is the text to the _left_ of the taskpanes? and the taskpane isn't growing on resizing, just the contrary ... – kleopatra Feb 24 '14 at 11:57
  • You can't see the growing because the taskPane is already too big when the program starts up. Also I believe that both the unexpected growing and the shrinking are rooted in the same underlying issue. And I suspect it is the word wrapping JXLabel. – Jonny Feb 24 '14 at 12:34
  • loosing patience (I trivially couldn't see the text in your first example because it wasn't there before your last edit ;-) And now the textArea isn't wrapping because you didn't configure it to do it ... And why are you focusing your question on the taskPane when you have a problem with the label? – kleopatra Feb 24 '14 at 12:40
  • Thanks for sticking with me this far. I updated the code a final time. It now has a button. Click the button, then resize the window. You should see the problem exactly as advertised. – Jonny Feb 24 '14 at 12:45
  • I tried, but I'm not able to influence the dimensions of the label in any way. Anyway, I care about the size of the taskPanel, which behaves odd if the label has lineWrap turned on. I'm quite lost here. – Jonny Feb 26 '14 at 18:02

1 Answers1

0

I wish there was a concise answer to my question. I fear there is not. I resolved the issue by creating a new layout, based on a GridBagLayout instead of BorderLayout.

There was also the issue of setting a minimum preferred size. Without calling setMinimumSize(new Dimension(200, 127)), the container's width seemed to shrink indefinitely, despite advertising a preferred width of 600. I'm still not sure where this comes from. The numbers are from the component's initial preferred size.

The tutorial on oracle's site helped me here. The important part is finding weights which work. A weight value greater than 0 allows the component to grow and shrink.

This is what the layout code looks like now:

frmvanInput = new JFrame(); // window
// ... captions, titles, etc

frmvanInput.setContentPane(new JPanel(new GridBagLayout()));

// ... more initializing

/** 
 * LAYOUTS
 */
final Container contentPane = frmvanInput.getContentPane();

// the menu bar is on top, stretches all the way right
GridBagConstraints menuBarLayout = new GridBagConstraints();
// top left
menuBarLayout.anchor = GridBagConstraints.FIRST_LINE_START; // push to the top left
menuBarLayout.gridx = 0; 
menuBarLayout.gridy = 0;
// manage width
menuBarLayout.gridwidth = 2; // stretch
menuBarLayout.fill = GridBagConstraints.HORIZONTAL; // fill all x-space
menuBarLayout.weightx = 0.5; // a weight > 0 allows for resizing
//add
contentPane.add(menuBar, menuBarLayout);

// the text field is under the menu on the left and shares a row with the errors panel/scroll pane
GridBagConstraints textfieldLayout = new GridBagConstraints();
// top left
textfieldLayout.anchor = GridBagConstraints.FIRST_LINE_START; // push to the top left
textfieldLayout.gridx = 0; // col left
textfieldLayout.gridy = 1; // row center
// manage stretching
textfieldLayout.weightx = 0.5; // resizable
textfieldLayout.weighty = 0.5; // resizable
textfieldLayout.fill = GridBagConstraints.BOTH;
// add
contentPane.add(txtEditor, textfieldLayout);

errorScrollPane = new JScrollPane(containerTaskPanel);
// prevent indefinate shrinking
errorScrollPane.setMinimumSize(new Dimension(200, 127));

GridBagConstraints scrollpanelLayout = new GridBagConstraints();
// middle, right
scrollpanelLayout.anchor = GridBagConstraints.FIRST_LINE_END;
scrollpanelLayout.gridx = 1; // right row
scrollpanelLayout.gridy = 1; // center column
// stretch to fill
scrollpanelLayout.weightx = 0.5; // resizable
scrollpanelLayout.weighty = 0.5; // resizable
scrollpanelLayout.fill = GridBagConstraints.BOTH;
// add our controls to the visible world
contentPane.add(errorScrollPane, scrollpanelLayout);

// the emitter panel has the bottom row to itself
GridBagConstraints emitterpanelLayout = new GridBagConstraints();
// bottom left
emitterpanelLayout.anchor = GridBagConstraints.LAST_LINE_START;
emitterpanelLayout.gridx = 0; // col left
emitterpanelLayout.gridy = 2; // row bottom
// stretch width
emitterpanelLayout.weightx = 0.5;
emitterpanelLayout.gridwidth = 2;
// manage height:
emitterpanelLayout.weighty = 0.1;
emitterpanelLayout.fill = GridBagConstraints.BOTH;
// add
contentPane.add(emitterScrollPane, emitterpanelLayout);
Jonny
  • 1,453
  • 16
  • 25