当包含在 GridBagLayout 中时,如何使我的面板换行文本并增加高度而不是宽度?
How can I make my Panel wrap text and increase in height instead of width when contained in a GridBagLayout?
[最终编辑]
好的伙计们。
我不知道为什么它在我的聊天程序中不起作用...但我设法修复了 SSCCE.. 使用它现在可以使用的可滚动实现。谢谢大家!
代码:
package de.sky.cjat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.UIManager;
public class MyKskb {
private int row;
class SomethingPanel extends JPanel implements Scrollable {
public SomethingPanel(LayoutManager manager){
super(manager);
}
@Override
public Dimension getPreferredScrollableViewportSize(){
return getPreferredSize();
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
@Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
@Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
}
public MyKskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final SomethingPanel content = new SomethingPanel(new GridBagLayout());
// final JPanel empty = new JPanel();
// empty.setPreferredSize(new Dimension(0, 0));
// GridBagConstraints gbc = new GridBagConstraints();
// content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
p.setBackground(Color.GRAY);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridx = 0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
// content.remove(empty);
// gbc.gridy = row;
// gbc.weighty = 1.0;
// content.add(empty, gbc);
JTextArea text = new JTextArea(
Math.random() > 0.5 ?
"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC" :
"FFFFFFFFFFFFABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap(true);
p.add(text);
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new MyKskb();
}
}
[结束]
[问题]
我正在写一个聊天程序,布局是这样的:
带有消息的面板有一个 GridBagLayout 并包装在一个 JScrollPane 中。
问题是,如果消息太长,消息面板会拉伸并变得太大:
所以我想要实现的是限制面板的大小,它包裹在 JScrollPane 中 - 我希望带有消息文本的灰色面板增加它们的高度,如果文本变长,而不是变宽. IE。环绕文本,不增加面板宽度。
有没有办法通过网格包布局实现这一点,还是我遗漏了什么?或者我应该使用另一个布局管理器?
编辑:完整层次结构:
JScrollPane
JPanel (gbl)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
....
编辑:我试过这样实现 Scrollable:
@Override
public Dimension getPreferredScrollableViewportSize(){
return new Dimension(100, getHeight());
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
@Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
@Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
但如果文本太长,也会发生同样的事情...我不知道 getPreferredScrollableViewportSize
应该 return,而且 getSize()
也不起作用。 .
编辑:这是一个 SSCCE,它显示了我的 GUI 的基本结构:(按回车键添加新组件)
package de.sky.cjat;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Kskb {
private int row;
public Kskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
final JPanel content = new JPanel(new GridBagLayout());
final JPanel empty = new JPanel();
empty.setPreferredSize(new Dimension(0, 0));
GridBagConstraints gbc = new GridBagConstraints();
content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel();
p.setBackground(Color.GRAY);
JLabel text = new JLabel("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
p.add(text);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTHWEST;
content.add(p, gbc);
content.remove(empty);
gbc.gridy = row;
gbc.weighty = 1.0;
content.add(empty, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
我觉得你可以做到。
Jpanel.setPreferredSize(new Dimension(x size, y size));
Jframe.add(Jpanel);
我认为大多数布局管理器使用 setPreferredSize 比使用 setSize 效果更好。
这是JScrollPane与其内容交互的效果。滚动窗格将(默认情况下)提供所需的内容 space。
从这个意义上说,布局非常完美。
要让滚动窗格中显示的组件实际控制它显示的容器的大小,包含的组件可以实现接口 javax.swing.Scrollable
。
尝试这样的事情:
public class MyVerticalPanel extends JPanel implements Scrollable {
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
// other method and implementation
}
此处提供更多文档:https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#scrollable
我设法让一些东西按照你想要的方式工作:
public class Chatter extends JFrame {
JTextField enterTextField = new JTextField("This is a lot of text it's way too loooooooooooooooong to fit in one line but it is used to check for wrapping by words and characters some more text just for fun no punctuation");
JPanel historyPanel = new JPanel();
public Chatter() {
enterTextField.addActionListener(new enterTextActionListener());
historyPanel.setLayout(new BoxLayout(historyPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(historyPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(enterTextField, BorderLayout.PAGE_END);
getContentPane().add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private class enterTextActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JTextArea textArea = new JTextArea(enterTextField.getText());
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.RED, 5));
scrollPane.setPreferredSize(textArea.getPreferredSize());
historyPanel.add(scrollPane);
historyPanel.add(Box.createRigidArea(new Dimension(0,10)));
historyPanel.revalidate();
// enterTextField.setText(""); // Commented out for convenience while testing.
}
}
public static void main(String args[]) {
new Chatter();
}
}
解释:
我使用 JTextArea
s 来显示文本,因为它支持文本换行。每个文本区域都在 JScrollPane
内,以便在 space 不足以显示文本时允许垂直滚动作为最后的手段。
备注:
- 我使用了
JTextField
作为文本输入法,您可以改用多行文本组件。
- 初始文本仅供测试。
- 测试的每个条目都不会清除文本(请参阅代码中的注释行)。
- 我将
BoxLayout
用于保存短信的面板,因为它看起来更简单自然。 GridBagLayout
肯定可以代替。
- 我设置
setWrapStyleWord(true)
是因为用文字换行可能是正确的行为。如果您想按字符换行,请删除此行。
- 我添加了边框和 spaces 用于测试。使用您想要的任何样式。
根据@durandal 的建议,问题出在 JLabel 上。 JLabel 不换行文本。所以你需要使用不同的组件。这是使用 JTextArea 修改的代码:
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.*;
public class Kskb {
private int row;
public Kskb()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final ScrollablePanel content = new ScrollablePanel(new GridBagLayout());
content.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
final GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "");
content.getActionMap().put("", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e)
{
JPanel p = new JPanel( new BorderLayout() );
p.setBorder( new EmptyBorder(10, 10, 10, 10) );
p.setBackground(Color.GRAY);
JTextArea text = new JTextArea();
text.append("ABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCA BCABCABCABCABCABCABCAB CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap( true );
p.add(text);
gbc.gridy = row++;
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
关键是 Scrollable
实现,它强制调整面板宽度和调整框架。此代码使用 Scrollable Panel,它只是 Scrollable
接口的可重用实现,您可以使用方法对其进行配置,而不是创建新的 class 并覆盖方法。
[最终编辑]
好的伙计们。
我不知道为什么它在我的聊天程序中不起作用...但我设法修复了 SSCCE.. 使用它现在可以使用的可滚动实现。谢谢大家!
代码:
package de.sky.cjat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.UIManager;
public class MyKskb {
private int row;
class SomethingPanel extends JPanel implements Scrollable {
public SomethingPanel(LayoutManager manager){
super(manager);
}
@Override
public Dimension getPreferredScrollableViewportSize(){
return getPreferredSize();
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
@Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
@Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
}
public MyKskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final SomethingPanel content = new SomethingPanel(new GridBagLayout());
// final JPanel empty = new JPanel();
// empty.setPreferredSize(new Dimension(0, 0));
// GridBagConstraints gbc = new GridBagConstraints();
// content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
p.setBackground(Color.GRAY);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridx = 0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
// content.remove(empty);
// gbc.gridy = row;
// gbc.weighty = 1.0;
// content.add(empty, gbc);
JTextArea text = new JTextArea(
Math.random() > 0.5 ?
"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC" :
"FFFFFFFFFFFFABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap(true);
p.add(text);
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new MyKskb();
}
}
[结束]
[问题]
我正在写一个聊天程序,布局是这样的:
带有消息的面板有一个 GridBagLayout 并包装在一个 JScrollPane 中。
问题是,如果消息太长,消息面板会拉伸并变得太大:
所以我想要实现的是限制面板的大小,它包裹在 JScrollPane 中 - 我希望带有消息文本的灰色面板增加它们的高度,如果文本变长,而不是变宽. IE。环绕文本,不增加面板宽度。
有没有办法通过网格包布局实现这一点,还是我遗漏了什么?或者我应该使用另一个布局管理器?
编辑:完整层次结构:
JScrollPane
JPanel (gbl)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
JPanel (custom painting)
JComponent (JLabel but it can vary)
....
编辑:我试过这样实现 Scrollable:
@Override
public Dimension getPreferredScrollableViewportSize(){
return new Dimension(100, getHeight());
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
return 5;
}
@Override
public boolean getScrollableTracksViewportHeight(){
return false;
}
@Override
public boolean getScrollableTracksViewportWidth(){
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
return 1;
}
但如果文本太长,也会发生同样的事情...我不知道 getPreferredScrollableViewportSize
应该 return,而且 getSize()
也不起作用。 .
编辑:这是一个 SSCCE,它显示了我的 GUI 的基本结构:(按回车键添加新组件)
package de.sky.cjat;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Kskb {
private int row;
public Kskb(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
final JPanel content = new JPanel(new GridBagLayout());
final JPanel empty = new JPanel();
empty.setPreferredSize(new Dimension(0, 0));
GridBagConstraints gbc = new GridBagConstraints();
content.add(empty, gbc);
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
content.getActionMap().put("§", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e){
JPanel p = new JPanel();
p.setBackground(Color.GRAY);
JLabel text = new JLabel("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
p.add(text);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.weightx = 1.0;
gbc.gridy = row++;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTHWEST;
content.add(p, gbc);
content.remove(empty);
gbc.gridy = row;
gbc.weighty = 1.0;
content.add(empty, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
我觉得你可以做到。
Jpanel.setPreferredSize(new Dimension(x size, y size));
Jframe.add(Jpanel);
我认为大多数布局管理器使用 setPreferredSize 比使用 setSize 效果更好。
这是JScrollPane与其内容交互的效果。滚动窗格将(默认情况下)提供所需的内容 space。
从这个意义上说,布局非常完美。
要让滚动窗格中显示的组件实际控制它显示的容器的大小,包含的组件可以实现接口 javax.swing.Scrollable
。
尝试这样的事情:
public class MyVerticalPanel extends JPanel implements Scrollable {
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
// other method and implementation
}
此处提供更多文档:https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#scrollable
我设法让一些东西按照你想要的方式工作:
public class Chatter extends JFrame {
JTextField enterTextField = new JTextField("This is a lot of text it's way too loooooooooooooooong to fit in one line but it is used to check for wrapping by words and characters some more text just for fun no punctuation");
JPanel historyPanel = new JPanel();
public Chatter() {
enterTextField.addActionListener(new enterTextActionListener());
historyPanel.setLayout(new BoxLayout(historyPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(historyPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(enterTextField, BorderLayout.PAGE_END);
getContentPane().add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private class enterTextActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JTextArea textArea = new JTextArea(enterTextField.getText());
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.RED, 5));
scrollPane.setPreferredSize(textArea.getPreferredSize());
historyPanel.add(scrollPane);
historyPanel.add(Box.createRigidArea(new Dimension(0,10)));
historyPanel.revalidate();
// enterTextField.setText(""); // Commented out for convenience while testing.
}
}
public static void main(String args[]) {
new Chatter();
}
}
解释:
我使用 JTextArea
s 来显示文本,因为它支持文本换行。每个文本区域都在 JScrollPane
内,以便在 space 不足以显示文本时允许垂直滚动作为最后的手段。
备注:
- 我使用了
JTextField
作为文本输入法,您可以改用多行文本组件。- 初始文本仅供测试。
- 测试的每个条目都不会清除文本(请参阅代码中的注释行)。
- 我将
BoxLayout
用于保存短信的面板,因为它看起来更简单自然。GridBagLayout
肯定可以代替。 - 我设置
setWrapStyleWord(true)
是因为用文字换行可能是正确的行为。如果您想按字符换行,请删除此行。 - 我添加了边框和 spaces 用于测试。使用您想要的任何样式。
根据@durandal 的建议,问题出在 JLabel 上。 JLabel 不换行文本。所以你需要使用不同的组件。这是使用 JTextArea 修改的代码:
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.*;
public class Kskb {
private int row;
public Kskb()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setPreferredSize(new Dimension(800, 600));
// final JPanel content = new JPanel(new GridBagLayout());
final ScrollablePanel content = new ScrollablePanel(new GridBagLayout());
content.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
final GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "");
content.getActionMap().put("", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e)
{
JPanel p = new JPanel( new BorderLayout() );
p.setBorder( new EmptyBorder(10, 10, 10, 10) );
p.setBackground(Color.GRAY);
JTextArea text = new JTextArea();
text.append("ABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCA BCABCABCABCABCABCABCAB CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
text.setLineWrap( true );
p.add(text);
gbc.gridy = row++;
content.add(p, gbc);
content.revalidate();
}
});
JScrollPane scrollPane = new JScrollPane(content);
f.pack();
f.setLocationRelativeTo(null);
f.add(scrollPane);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new Kskb();
}
}
关键是 Scrollable
实现,它强制调整面板宽度和调整框架。此代码使用 Scrollable Panel,它只是 Scrollable
接口的可重用实现,您可以使用方法对其进行配置,而不是创建新的 class 并覆盖方法。