JTextArea 与 JScrollPAne 在具有空布局的框架内
JTextArea with JScrollPAne within Frame with null Layout
我正在尝试将这个带有 JScrollPane(带有垂直滚动条但没有水平滚动条)的 JTextArea 添加到我的框架中,但结果只是右侧带有滚动条的灰色区域...我可能正在做某事真的很愚蠢,但我对 JPanel 做了同样的事情并且它起作用了
public class Chats {
public static int height = 600;
public static int length = 400;
public static void init(String me, String you){
JFrame frame = new JFrame ("Chat");
frame.setSize(larguraframe, alturaframe);
frame.setLocation(620, 100);
frame.setResizable(false);
frame.setLayout(null);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
JTextArea chat = new JTextArea();
chat.setColumns(10);
chat.setLineWrap(true);
chat.setWrapStyleWord(true);
JScrollPane scrollpane = new JScrollPane(chat, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;
scrollpane.setBounds(length/8 - 27, height/9 + 27, 350, 380);
chat.setPreferredSize(new Dimension(lenght-15, 7*height/8-27));
frame.add(chat);
frame.add(scrollpane);
frame.setVisible(true);
}
}
我不介意更改相框的布局,但我真的想要一个可以让我把东西准确地放在我想要的地方的布局。谢谢
编辑
好的,它现在显示在我的框架上,但 TextArea 仍然无法调整大小。当我使用 JTextfield 和带有监听器的 JButton 在其中写入内容时,监听器将 JTextfield 的文本附加到 JTextArea,然后将 JTextField 中的文本设置为“”,它只接受一定数量的行。在那之后它看起来是一样的。
不需要添加chat
,因为它是由scrollPane
改编的。
删除此行:frame.add(chat);
尝试设置这样的布局:
frame.setLayout(new BorderLayout());
并将滚动窗格添加到中心:
frame.add(scrollpane, BorderLayout.CENTER);
同时删除 Jire 在他的回答中指出的那一行。
添加
chat.setBounds(length/8 - 27, height/9 + 27, 330, 360);
看到奇迹发生了...但是请调整此处的参数以获得正确的尺寸。
对于可调整大小的框架,只需执行 frame.setResizable(true);
而不是 frame.setResizable(false);
我知道你已经 "accepted" 回答了,但我觉得如果我不给出一个重要的答案,那是我的失职,那些在很长一段时间内 运行 将允许您创建更好、更健壮(即更容易调试、修改和增强)的应用程序。
再次,
- 永远不要设置 JTextArea 的 preferredSize,因为这将创建一个 JTextArea,其大小设置不灵活,在需要时不会添加额外的行。而是设置 JTextArea 的行和列属性。
- 虽然空布局和
setBounds()
对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用时 运行 遇到的困难就越严重他们。它们不会在 GUI 调整大小时调整您的组件的大小,它们是皇家 来增强或维护的,它们在放置在滚动窗格中时完全失败,它们在所有平台或屏幕分辨率上查看时看起来 gawd-awful和原来的不一样。
- 最好使用 JPanel,或者更常见的是多个嵌套的 JPanel,每个 JPanel 都使用自己的布局管理器,使您可以更简单地创建灵活、强大、复杂但美观的 GUI。
- 使用布局管理器时,您需要在添加所有组件后
pack()
JFrame,以便所有布局管理器都能适当地完成其工作和布局组件。
我在下面展示了一个示例程序,
- 带有居中大文本的标题 JLabel
- 一个 JTextArea,称为 chatViewArea,具有指定的行和列大小,保存在 JScrollPane 中,用于查看聊天。它是 non-focusable,因此用户无法直接与其交互。
- 另一个 JTextArea,称为 textEntryArea,用于输入文本。您可以为此使用一个简单的 JTextField 并为其提供一个 ActionListener 以便它响应回车键,但是如果您想要一个行为相似的 multi-lined 文本组件,您需要更改 JTextArea 的键绑定回车键。我在此处完成了此操作,以便回车键 "submits" 文本保存在 textEntryArea JTextArea 中,而 control-enter 组合键的作用与用于创建新行的回车键相同。
- 主要的 JPanel 仅使用 BorderLayout 来允许将标题放置在顶部,将聊天视图 JTextArea 放置在中间,将文本条目 JTextArea 放置在底部。请注意,如果您需要查看更多组件,例如显示其他聊天记录的 JList,这可以通过嵌套 JPanel 并在需要时使用更多布局来完成。
例如:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class Chat2 extends JPanel {
private static final int ROWS = 25; // rows in the chat view JTextArea
private static final int COLS = 40; // columns in the chat view JTextArea
// and text entry area
private static final int ENTRY_ROWS = 4; // rows in the text entry JTextArea
private static final int BL_HGAP = 10; // horizontal gap for our
// BorderLayout
private static final int BL_VGAP = 5; // vertical gap for our BorderLayout
private static final int EB_GAP = 15; // gap for empty border that goes
// around entire app
private static final String TITLE_TEXT = "My Chat Application";
private static final float TITLE_POINTS = 32f; // size of the title jlabel
// text
private JTextArea chatViewArea = new JTextArea(ROWS, COLS);
private JTextArea textEntryArea = new JTextArea(ENTRY_ROWS, COLS);
public Chat2() {
// label to display the title in bold large text
JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, TITLE_POINTS));
// set up the chat view JTextArea to have word wrap
// and to not be focusable
chatViewArea.setWrapStyleWord(true);
chatViewArea.setLineWrap(true);
chatViewArea.setFocusable(false);
// add it to a JScrollPane, and give the scrollpane vertical scrollbars
JScrollPane viewScrollPane = new JScrollPane(chatViewArea);
viewScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// set up the text entry JTextArea
textEntryArea.setWrapStyleWord(true);
textEntryArea.setLineWrap(true);
// key bindings so that control-enter will act as enter and the enter key will "submit"
// the user input to the chat window and the chat server
// will allow us to use a multilined text entry area if desired instead
// of a single lined JTextField
setEnterKeyBinding(textEntryArea);
JScrollPane entryScrollPane = new JScrollPane(textEntryArea);
entryScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// add an empty border around entire application
setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
// make the main layout a BorderLayout
setLayout(new BorderLayout(BL_HGAP, BL_VGAP));
// add our components to the GUI
add(titleLabel, BorderLayout.PAGE_START);
add(viewScrollPane, BorderLayout.CENTER);
add(entryScrollPane, BorderLayout.PAGE_END);
}
// Again, use key bindings so that control-enter JTextArea will act as enter key
// and the enter key will "submit" the user input to the chat window and the chat server.
// When ctrl-enter is pushed the Action originally bound to the enter key will be called
// and when enter is pushed a new Action, the EnterKeyAction, will be called
private void setEnterKeyBinding(JTextArea textArea) {
int condition = JComponent.WHEN_FOCUSED; // only for focused entry key
InputMap inputMap = textArea.getInputMap(condition);
ActionMap actionMap = textArea.getActionMap();
KeyStroke entryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
KeyStroke ctrlEntryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK);
// first give ctrl-enter the action held by enter
Object entryKey = inputMap.get(entryKeyStroke);
Action entryAction = actionMap.get(entryKey);
inputMap.put(ctrlEntryKeyStroke, ctrlEntryKeyStroke.toString());
actionMap.put(ctrlEntryKeyStroke.toString(), entryAction);
// now give enter key a new Action
EnterKeyAction enterKeyAction = new EnterKeyAction();
inputMap.put(entryKeyStroke, entryKeyStroke.toString());
actionMap.put(entryKeyStroke.toString(), enterKeyAction);
}
public void appendToChatArea(final String text) {
if (SwingUtilities.isEventDispatchThread()) {
chatViewArea.append(text + "\n");
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
chatViewArea.append(text + "\n");
}
});
}
}
private class EnterKeyAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
String text = textEntryArea.getText();
textEntryArea.setText("");
chatViewArea.append("User: " + text + "\n");
// TODO send text to the chat server!
}
}
private static void createAndShowGui() {
Chat2 mainPanel = new Chat2();
JFrame frame = new JFrame("My Chat Window");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
// pack the JFrame so that it will size itself to its components
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
我正在尝试将这个带有 JScrollPane(带有垂直滚动条但没有水平滚动条)的 JTextArea 添加到我的框架中,但结果只是右侧带有滚动条的灰色区域...我可能正在做某事真的很愚蠢,但我对 JPanel 做了同样的事情并且它起作用了
public class Chats {
public static int height = 600;
public static int length = 400;
public static void init(String me, String you){
JFrame frame = new JFrame ("Chat");
frame.setSize(larguraframe, alturaframe);
frame.setLocation(620, 100);
frame.setResizable(false);
frame.setLayout(null);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
JTextArea chat = new JTextArea();
chat.setColumns(10);
chat.setLineWrap(true);
chat.setWrapStyleWord(true);
JScrollPane scrollpane = new JScrollPane(chat, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;
scrollpane.setBounds(length/8 - 27, height/9 + 27, 350, 380);
chat.setPreferredSize(new Dimension(lenght-15, 7*height/8-27));
frame.add(chat);
frame.add(scrollpane);
frame.setVisible(true);
}
}
我不介意更改相框的布局,但我真的想要一个可以让我把东西准确地放在我想要的地方的布局。谢谢
编辑
好的,它现在显示在我的框架上,但 TextArea 仍然无法调整大小。当我使用 JTextfield 和带有监听器的 JButton 在其中写入内容时,监听器将 JTextfield 的文本附加到 JTextArea,然后将 JTextField 中的文本设置为“”,它只接受一定数量的行。在那之后它看起来是一样的。
不需要添加chat
,因为它是由scrollPane
改编的。
删除此行:frame.add(chat);
尝试设置这样的布局:
frame.setLayout(new BorderLayout());
并将滚动窗格添加到中心:
frame.add(scrollpane, BorderLayout.CENTER);
同时删除 Jire 在他的回答中指出的那一行。
添加
chat.setBounds(length/8 - 27, height/9 + 27, 330, 360);
看到奇迹发生了...但是请调整此处的参数以获得正确的尺寸。
对于可调整大小的框架,只需执行 frame.setResizable(true);
而不是 frame.setResizable(false);
我知道你已经 "accepted" 回答了,但我觉得如果我不给出一个重要的答案,那是我的失职,那些在很长一段时间内 运行 将允许您创建更好、更健壮(即更容易调试、修改和增强)的应用程序。
再次,
- 永远不要设置 JTextArea 的 preferredSize,因为这将创建一个 JTextArea,其大小设置不灵活,在需要时不会添加额外的行。而是设置 JTextArea 的行和列属性。
- 虽然空布局和
setBounds()
对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用时 运行 遇到的困难就越严重他们。它们不会在 GUI 调整大小时调整您的组件的大小,它们是皇家 来增强或维护的,它们在放置在滚动窗格中时完全失败,它们在所有平台或屏幕分辨率上查看时看起来 gawd-awful和原来的不一样。 - 最好使用 JPanel,或者更常见的是多个嵌套的 JPanel,每个 JPanel 都使用自己的布局管理器,使您可以更简单地创建灵活、强大、复杂但美观的 GUI。
- 使用布局管理器时,您需要在添加所有组件后
pack()
JFrame,以便所有布局管理器都能适当地完成其工作和布局组件。
我在下面展示了一个示例程序,
- 带有居中大文本的标题 JLabel
- 一个 JTextArea,称为 chatViewArea,具有指定的行和列大小,保存在 JScrollPane 中,用于查看聊天。它是 non-focusable,因此用户无法直接与其交互。
- 另一个 JTextArea,称为 textEntryArea,用于输入文本。您可以为此使用一个简单的 JTextField 并为其提供一个 ActionListener 以便它响应回车键,但是如果您想要一个行为相似的 multi-lined 文本组件,您需要更改 JTextArea 的键绑定回车键。我在此处完成了此操作,以便回车键 "submits" 文本保存在 textEntryArea JTextArea 中,而 control-enter 组合键的作用与用于创建新行的回车键相同。
- 主要的 JPanel 仅使用 BorderLayout 来允许将标题放置在顶部,将聊天视图 JTextArea 放置在中间,将文本条目 JTextArea 放置在底部。请注意,如果您需要查看更多组件,例如显示其他聊天记录的 JList,这可以通过嵌套 JPanel 并在需要时使用更多布局来完成。
例如:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class Chat2 extends JPanel {
private static final int ROWS = 25; // rows in the chat view JTextArea
private static final int COLS = 40; // columns in the chat view JTextArea
// and text entry area
private static final int ENTRY_ROWS = 4; // rows in the text entry JTextArea
private static final int BL_HGAP = 10; // horizontal gap for our
// BorderLayout
private static final int BL_VGAP = 5; // vertical gap for our BorderLayout
private static final int EB_GAP = 15; // gap for empty border that goes
// around entire app
private static final String TITLE_TEXT = "My Chat Application";
private static final float TITLE_POINTS = 32f; // size of the title jlabel
// text
private JTextArea chatViewArea = new JTextArea(ROWS, COLS);
private JTextArea textEntryArea = new JTextArea(ENTRY_ROWS, COLS);
public Chat2() {
// label to display the title in bold large text
JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, TITLE_POINTS));
// set up the chat view JTextArea to have word wrap
// and to not be focusable
chatViewArea.setWrapStyleWord(true);
chatViewArea.setLineWrap(true);
chatViewArea.setFocusable(false);
// add it to a JScrollPane, and give the scrollpane vertical scrollbars
JScrollPane viewScrollPane = new JScrollPane(chatViewArea);
viewScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// set up the text entry JTextArea
textEntryArea.setWrapStyleWord(true);
textEntryArea.setLineWrap(true);
// key bindings so that control-enter will act as enter and the enter key will "submit"
// the user input to the chat window and the chat server
// will allow us to use a multilined text entry area if desired instead
// of a single lined JTextField
setEnterKeyBinding(textEntryArea);
JScrollPane entryScrollPane = new JScrollPane(textEntryArea);
entryScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// add an empty border around entire application
setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
// make the main layout a BorderLayout
setLayout(new BorderLayout(BL_HGAP, BL_VGAP));
// add our components to the GUI
add(titleLabel, BorderLayout.PAGE_START);
add(viewScrollPane, BorderLayout.CENTER);
add(entryScrollPane, BorderLayout.PAGE_END);
}
// Again, use key bindings so that control-enter JTextArea will act as enter key
// and the enter key will "submit" the user input to the chat window and the chat server.
// When ctrl-enter is pushed the Action originally bound to the enter key will be called
// and when enter is pushed a new Action, the EnterKeyAction, will be called
private void setEnterKeyBinding(JTextArea textArea) {
int condition = JComponent.WHEN_FOCUSED; // only for focused entry key
InputMap inputMap = textArea.getInputMap(condition);
ActionMap actionMap = textArea.getActionMap();
KeyStroke entryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
KeyStroke ctrlEntryKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK);
// first give ctrl-enter the action held by enter
Object entryKey = inputMap.get(entryKeyStroke);
Action entryAction = actionMap.get(entryKey);
inputMap.put(ctrlEntryKeyStroke, ctrlEntryKeyStroke.toString());
actionMap.put(ctrlEntryKeyStroke.toString(), entryAction);
// now give enter key a new Action
EnterKeyAction enterKeyAction = new EnterKeyAction();
inputMap.put(entryKeyStroke, entryKeyStroke.toString());
actionMap.put(entryKeyStroke.toString(), enterKeyAction);
}
public void appendToChatArea(final String text) {
if (SwingUtilities.isEventDispatchThread()) {
chatViewArea.append(text + "\n");
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
chatViewArea.append(text + "\n");
}
});
}
}
private class EnterKeyAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
String text = textEntryArea.getText();
textEntryArea.setText("");
chatViewArea.append("User: " + text + "\n");
// TODO send text to the chat server!
}
}
private static void createAndShowGui() {
Chat2 mainPanel = new Chat2();
JFrame frame = new JFrame("My Chat Window");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
// pack the JFrame so that it will size itself to its components
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}