最近我正在使用Java编写一个邮件系统客户端(我选择了swing来编写GUI并使用IDEA来硬编码我的GUI)。在撰写模块中,当我单击相应的按钮时,我想显示或隐藏CC和密件抄送的文本字段。
所以我在网上搜索并浏览了以下问题和文档:
最后,我选择了JScrollPane来实现它。
我的简化示例代码如下(原始代码繁琐):
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Demo extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel lbl1;
private JTextField txf1;
private JLabel lbl2;
private JTextField txf2;
// container for lbl2 and txf2, which should be able to be shown or hidden
private JPanel pnlContainer2;
private JLabel lbl3;
private JTextField txf3;
// container for lbl3 and txf3
private JPanel pnlContainer3;
private JButton btnShow;
// the container I want to move when I click btnShow
private JPanel pnlBody;
// the panel to hold my "cards"
// In this example, I include it just to show what controls are on my interface.
private JPanel pnlContent;
private JPanel pnlContainer;
// here, I want to use JScrollPane to make my pnlContainer scrollable
// to adapt to my interface
private JScrollPane scrollPane;
public Demo() {
init();
}
private void init() {
pnlContainer = new JPanel(new CardLayout(), true);
pnlContainer.setBounds(0, 0, 200, 180);
pnlContent = new JPanel(null, true);
pnlContent.setBounds(0, 0, 200, 180 + 50);
scrollPane = new JScrollPane(pnlContent, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBounds(0, 0, 200, 180);
pnlContainer.add(scrollPane);
pnlBody = new JPanel(null, true);
lbl1 = new JLabel("lbl1");
lbl1.setBounds(10, 20, 40, 30);
txf1 = new JTextField();
txf1.setBounds(60, 20, 120, 30);
pnlContent.add(lbl1);
pnlContent.add(txf1);
pnlContainer2 = new JPanel(null, true);
pnlContainer2.setBounds(0, 70, 180, 30);
lbl2 = new JLabel("lbl2");
lbl2.setBounds(10, 0, 40, 30);
txf2 = new JTextField();
txf2.setBounds(60, 0, 120, 30);
pnlContainer2.add(lbl2);
pnlContainer2.add(txf2);
pnlContainer2.setVisible(false);
pnlContent.add(pnlContainer2);
pnlBody = new JPanel(null, true);
pnlBody.setBounds(0, 70, 180, 90);
pnlContainer3 = new JPanel(null, true);
pnlContainer3.setBounds(0, 0, 180, 30);
pnlBody.add(pnlContainer3);
lbl3 = new JLabel("lbl3");
lbl3.setBounds(10, 0, 40, 30);
txf3 = new JTextField();
txf3.setBounds(60, 0, 120, 30);
pnlContainer3.add(lbl3);
pnlContainer3.add(txf3);
btnShow = new JButton("show");
btnShow.setBounds(60, 50, 80, 30);
btnShow.addActionListener(this);
pnlBody.add(btnShow);
pnlContent.add(pnlBody);
this.add(pnlContainer);
this.setLayout(null);
this.setTitle("Demo");
this.setSize(200, 200);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
// ImageIcon icon = new ImageIcon("E:\\Javarepo\\Hmail\\src\\main\\resources\\assets\\hmail.png");
// this.setIconImage(icon.getImage());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Object src = e.getSource();
if (src instanceof JButton) {
JButton btn = (JButton) src;
boolean showSelected = false;
String altText;
if (btn == btnShow) {
showSelected = btnShow.getText() == "show";
altText = showSelected ? "hide" : "show";
btnShow.setText(altText);
}
relayout(showSelected);
}
}
private void relayout(boolean showSelected) {
int x = pnlBody.getX();
int y = pnlBody.getY();
if (showSelected) {
pnlContainer2.setVisible(true);
pnlBody.setBounds(x, y + 50, 180, 90);
} else {
pnlContainer2.setVisible(false);
pnlBody.setBounds(x, y - 50, 180, 90);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Demo());
}
}
但是,无论我将JScrollPane应用到哪个JPanel,我都无法使我的界面适应我的JContainer2的隐藏和显示。
我如何修改它,或者使用什么控件来替换JScrollPane?欢迎任何建议。
这是我的平台信息:
java-version
java版本"1.8.0_212"Java(TM)SE运行时环境(build 1.8.0_212-b10)
JavaHotSpot(TM)64位服务器VM(build 25.212-b10,混合模式)
OS: win10 1909
arch:amd64
我重写了你的代码。解释出现在它之后。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
public class Demo2 implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private JButton button;
private JLabel lbl2;
private JFrame frame;
private JTextField txf2;
@Override
public void run() {
showGui();
}
@Override
public void actionPerformed(ActionEvent event) {
boolean visible;
String text;
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case HIDE:
text = SHOW;
visible = false;
break;
case SHOW:
text = HIDE;
visible = true;
break;
default:
text = "???";
visible = false;
}
button.setText(text);
lbl2.setVisible(visible);
txf2.setVisible(visible);
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
button = new JButton(SHOW);
button.addActionListener(this);
buttonsPanel.add(button);
return buttonsPanel;
}
private JScrollPane createForm() {
JPanel form = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lbl1 = new JLabel("lbl1");
form.add(lbl1, gbc);
gbc.gridx = 1;
JTextField txf1 = new JTextField(6);
form.add(txf1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
lbl2 = new JLabel("lbl2");
lbl2.setVisible(false);
form.add(lbl2, gbc);
gbc.gridx = 1;
txf2 = new JTextField(6);
txf2.setVisible(false);
form.add(txf2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
JLabel lbl3 = new JLabel("lbl3");
form.add(lbl3, gbc);
gbc.gridx = 1;
JTextField txf3 = new JTextField(6);
form.add(txf3, gbc);
return new JScrollPane(form,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
private void showGui() {
frame = new JFrame("Demo");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(createForm(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Demo2());
}
}
您应该始终尝试使用布局管理器。上面的代码使用GridBagLayout
,但还有其他几个擅长处理表单的布局管理器,包括GroupLayout
和SpringLayout
以及第三方布局管理器,如MiG Layout和FormLayout。
为了在表单中“显示”和“隐藏”中间行,只需将可见属性设置为true
或false
。如果按钮的文本是SHOW,那么当用户单击它时,我将按钮文本更改为HIDE,并使lbl2
和txf2
都可见。如果按钮文本是HIDE,那么当用户单击按钮时,我将文本更改为SHOW,并使lbl2
和txf2
不可见。
因为我使用布局管理器,所以每当JPanel
的内容发生变化时,它都会处理调整JPanel
的大小。当你不使用布局管理器时,你必须编写处理调整大小的代码,当然你的代码没有,因此你的问题。