我有一個自定義的佈局,其中的主要行爲是在JScrollPane寬度變化時增長和縮小子JTextArea。滾動窗格的水平滾動條被禁用,並且文本區域應該展開和收縮,以避免需要horz滾動條。幾個月來,我使用其中一個標準佈局管理器來解決此問題,但現在我需要一些不同的功能。JTextArea不會收縮在佈局管理器內JPanel
發生了什麼事情是,當用戶水平擴展滾動窗格時,將調用佈局管理器layoutContainer方法。它會調整文本區域的大小並正確重排文本。但是,縮小滾動窗格時,不會調用layoutContainer,並且文本區域保持不變。我已經在layoutContainer方法中放置了一些printlns,以便它在工作時顯而易見。
重要的是要注意的問題是JTextArea setColumns被調用。我可以對它進行註釋,並在調整大小時調用layoutContainer。 (當然,那麼文本區域不會調整大小。)我也嘗試使用JTextArea.setSize,結果相同。
在此先感謝您的任何想法。
下面的代碼:
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
@SuppressWarnings("serial")
class XTextArea extends JTextArea
{
XTextArea (String text)
{
super (text);
}
public int getColumnWidth()
{
return super.getColumnWidth();
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class PackLeftLayout implements LayoutManager
{
Component viewPort;
Component flexWidthComponent;
int preferredWidth = 0;
int preferredHeight = 0;
//----------------------------------------------------------------------------
// viewPort - if null, compute width as sum of component's preferred width;
// otherwise width will be the viewPort's width.
// flexWidthComponent - if not null, this component width will be sized to right
// justify rightmost component.
public PackLeftLayout (Component viewPort, Component flexWidthComponent)
{
super();
this.viewPort = viewPort;
this.flexWidthComponent = flexWidthComponent;
}
//----------------------------------------------------------------------------
public void addLayoutComponent(String name, Component comp)
{
}
//----------------------------------------------------------------------------
public void removeLayoutComponent(Component comp)
{
}
//----------------------------------------------------------------------------
// Calculates the preferred size dimensions for the specified container, given the
// components it contains.
// parent - the container to be laid out
// Components layed out left-to-right with no additional spacing.
public Dimension preferredLayoutSize (Container parent)
{
Insets insets = parent.getInsets();
int width = 0;
int height = 0; // will become max of all component's preferred height
// calculate sum of fixed width components - skip the flexwidth component
width = insets.left + insets.right;
for (int i = 0, limit = parent.getComponentCount(); i < limit; i++)
{
Component c = parent.getComponent(i);
if (c.isVisible())
{
if (c != flexWidthComponent)
{
Dimension size = c.getPreferredSize();
if (size.height > height)
height = size.height;
width += size.width;
}
}
}
// determine width of flex width component
if (flexWidthComponent != null)
{
int flexWidth = viewPort.getWidth() - width;
if (flexWidth < 1)
flexWidth = 1;
if (flexWidthComponent instanceof XTextArea)
{
// some trickery here to get the xtextarea to tell us its preferred height
// given a specific width.
int colWidth = ((XTextArea)flexWidthComponent).getColumnWidth();
// the following line causes the failure:
((XTextArea)flexWidthComponent).setColumns (flexWidth/colWidth);
Dimension taSize = flexWidthComponent.getPreferredSize();
width += taSize.width;
if (taSize.height > height)
height = taSize.height;
}
else
{
Dimension size = flexWidthComponent.getPreferredSize();
width += flexWidth;
if (size.height > height)
height = size.height;
}
}
preferredWidth = width; // already include insets
preferredHeight = height + insets.top + insets.bottom;
return new Dimension (preferredWidth, preferredHeight);
}
//----------------------------------------------------------------------------
// Calculates the minimum size dimensions for the specified container, given the
// components it contains.
// parent - the component to be laid out
public Dimension minimumLayoutSize(Container parent)
{
return new Dimension (10, 10); //???
}
static int k = 0;
//----------------------------------------------------------------------------
public void layoutContainer(Container parent)
{
System.out.println ("layout" + (k++));
Insets insets = parent.getInsets();
int left = insets.left;
if (preferredWidth == 0 || preferredHeight == 0)
preferredLayoutSize (parent);
for (int i = 0, limit = parent.getComponentCount(); i < limit; i++)
{
Component c = parent.getComponent(i);
Dimension size = c.getPreferredSize();
c.setBounds (left, insets.top, size.width, preferredHeight);
left += size.width;
}
// force another layout calc
preferredWidth = 0;
}
}
public class ResizablePane extends JFrame
{
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(
new Runnable() {public void run()
{
new ResizablePane();
}});
}
ResizablePane()
{
super ("ResizableDemo");
// put a button and text area into a panel, then into a scroll pane
JButton button = new JButton ("button");
XTextArea text = new XTextArea (
"For three years I ran as fast as I could, trying to live and love and learn at " +
"double speed to make up for what Anne-Marie lost. Trying to anesthetize myself " +
"from what Id lost. When I decided to read a book a day and write about it, Id " +
"finally stopped running away.");
text.setLineWrap (true);
text.setWrapStyleWord (true);
JScrollPane scroll = new JScrollPane();
JPanel panel = new JPanel();
panel.setLayout (new PackLeftLayout(scroll.getViewport(), text));
panel.add (button);
panel.add (text);
scroll.setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setViewportView (panel);
getContentPane().add(scroll);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
*「最重要的是要注意的是」*這些詞彙中毫無疑問。 –
另請參見['TextPanePerfectSize'](http://stackoverflow.com/questions/3315681/how-can-i-measure-calculate-the-size-a-document-needs-to-render-itself/3318949#3318949 )。 – trashgod
我認爲這可能是文本區域和JScrollPane之間的交互中的某處的錯誤。我發現如果允許水平滾動條,ta會縮小。換句話說,在我的原始代碼中,我有行 setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 如果我刪除這條線,ta開始工作...有點。只要滾動條被隱藏,它就會工作。 –