如何让我的用户界面自适应 JPanel 的显示和隐藏? [英] How to make my user-interface self adapt to the show and hide of JPanel?

查看:51
本文介绍了如何让我的用户界面自适应 JPanel 的显示和隐藏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我正在使用 Java 编写邮件系统客户端(我选择 Swing 编写 GUI 并使用 IDEA 对我的 GUI 进行硬编码).在撰写模块中,我想在单击相应按钮时显示或隐藏抄送和密送的文本字段.

所以我在网上搜索并浏览了以下问题和文档:

最后,我选择了 JScrollPane 来实现它.

我的简化示例代码如下(原代码繁琐):

import java.awt.CardLayout;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 javax.swing.*;导入 javax.swing.ImageIcon;导入 javax.swing.JFrame;导入 javax.swing.SwingUtilities;公共类 Demo 扩展 JFrame 实现 ActionListener {private static final long serialVersionUID = 1L;私人 JLabel lbl1;私人 JTextField txf1;私人 JLabel lbl2;私有 JTextField txf2;//lbl2 和 txf2 的容器,应该能够显示或隐藏私人 JPanel pnlContainer2;私人 JLabel lbl3;私人 JTextField txf3;//lbl3 和 txf3 的容器私人 JPanel pnlContainer3;私人 JButton btnShow;//单击 btnShow 时要移动的容器私人 JPanel pnlBody;//放置我的卡片"的面板//在这个例子中,我包含它只是为了显示我的界面上有哪些控件.私人 JPanel pnlContent;私人 JPanel pnlContainer;//在这里,我想使用 JScrollPane 使我的 pnlContainer 可滚动//适应我的界面私人 JScrollPane 滚动窗格;公共演示(){在里面();}私有无效初始化(){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 = 新 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 = 新 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 = 新 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(演示");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);}@覆盖public void actionPerformed(ActionEvent e) {//TODO 自动生成的方法存根对象 src = e.getSource();if (src instanceof JButton) {JButton btn = (JButton) src;boolean showSelected = false;字符串 altText;如果(btn == btnShow){showSelected = btnShow.getText() == "show";altText = showSelected ?隐藏":显示";btnShow.setText(altText);}重新布局(showSelected);}}私人无效重新布局(布尔显示选择){int x = pnlBody.getX();int y = pnlBody.getY();如果(显示选择){pnlContainer2.setVisible(true);pnlBody.setBounds(x, y + 50, 180, 90);} 别的 {pnlContainer2.setVisible(false);pnlBody.setBounds(x, y - 50, 180, 90);}}公共静态无效主(字符串 [] args){SwingUtilities.invokeLater(() -> new Demo());}}

但是,无论我将 JScrollPane 应用到哪个 JPanel,我都无法使我的界面适应 JContainer2 的隐藏和显示.
我该如何修改它,或者使用什么控件来替换 JScrollPane?欢迎提出任何建议.

这是我的平台信息:

<块引用>

java -version
java版本1.8.0_212"Java(TM) SE 运行时环境(构建 1.8.0_212-b10)
Java HotSpot(TM) 64 位服务器 VM(构建 25.212-b10,混合模式)

<块引用>

操作系统:win10 1909
拱:amd64

解决方案

我重写了你的代码.后面会出现说明.

import java.awt.BorderLayout;导入 java.awt.EventQueue;导入 java.awt.GridBagConstraints;导入 java.awt.GridBagLayout;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 javax.swing.JButton;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 javax.swing.JScrollPane;导入 javax.swing.JTextField;导入 javax.swing.ScrollPaneConstants;导入 javax.swing.WindowConstants;公共类 Demo2 实现 ActionListener, Runnable {private static final String HIDE = "HIDE";private static final String SHOW = "SHOW";私人 JButton 按钮;私人 JLabel lbl2;私人 JFrame 框架;私有 JTextField txf2;@覆盖公共无效运行(){showGui();}@覆盖公共无效 actionPerformed(ActionEvent 事件){布尔值可见;字符串文本;String actionCommand = event.getActionCommand();开关(动作命令){案例隐藏:文字 = 显示;可见 = 假;休息;案例展示:文字 = 隐藏;可见 = 真;休息;默认:文字=???";可见 = 假;}button.setText(text);lbl2.setVisible(可见);txf2.setVisible(可见);}私人 JPanel createButtonsPanel() {JPanel buttonPanel = new JPanel();button = new JButton(SHOW);button.addActionListener(this);buttonPanel.add(button);返回按钮面板;}私人 JScrollPane createForm() {JPanel 表单 = 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 = 新 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 = 新 JTextField(6);form.add(txf3, gbc);返回新的 JScrollPane(表单,ScrollPaneConstants.VERTICAL_SCROLLBAR_​​ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_​​AS_NEEDED);}私有无效 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);框架.pack();frame.setLocationByPlatform(true);frame.setVisible(true);}/*** 从这里开始.*/公共静态无效主(字符串 [] args){EventQueue.invokeLater(new Demo2());}}

您应该始终尝试使用布局管理器.上面的代码使用了 GridBagLayout但是还有其他几个布局管理器擅长处理表单,包括 <代码>GroupLayoutSpringLayout 以及第三方布局管理器,如 MiG LayoutFormLayout.

为了展示"和隐藏"在表单中的中间行,只需将可见属性设置为 truefalse.如果按钮的文本是 SHOW,那么当用户单击它时,我将按钮文本更改为 HIDE,并使 lbl2txf2 都可见.如果按钮文本是 HIDE,那么当用户单击按钮时,我将文本更改为 SHOW,并使 lbl2txf2 可见.

因为我使用布局管理器,所以每当 JPanel 的内容发生变化时,它都会处理调整 JPanel 的大小.当您不使用布局管理器时,您必须编写处理调整大小的代码,当然您的代码不会,因此您的问题.

Recently I'm writing a mail system client using Java (I chose swing to write the GUI and use IDEA to hardcode my GUI). In the Compose module, I want to show or hide the textfield for CC and Bcc when I click the corresponding buttons.

So I googled and browsed the following questions and doc on the web:

Finally, I chose the JScrollPane to implement it.

My simplified sample code is as follows (the original code is tedious):

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());
    }

}

However, no matter which JPanel I apply JScrollPane to, I cannot make my interface adaptive to the hide and show of my JContainer2.
How can I modify it, or what control to use to replace JScrollPane? Any suggestions will be welcome.

And here is my platform information:

java -version
java version "1.8.0_212" Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)

OS: win10 1909
arch: amd64

解决方案

I rewrote your code. Explanations appear after it.

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());
    }
}

You should always try to use a layout manager. The code above uses GridBagLayout but there are several other layout managers that are good at handling forms, including GroupLayout and SpringLayout as well as third party layout managers like MiG Layout and FormLayout.

In order to "show" and "hide" the middle row in your form, simply set the visible property to true or false. If the text of the button is SHOW, then when the user clicks on it, I change the button text to HIDE and make lbl2 and txf2 both visible. If the button text is HIDE, then when the user clicks the button I change the text to SHOW and make lbl2 and txf2 not visible.

Because I use a layout manager, it handles resizing the JPanel whenever the contents of the JPanel are changed. When you don't use a layout manager, then you have to write code that handles the resizing and of-course your code does not, hence your problem.

这篇关于如何让我的用户界面自适应 JPanel 的显示和隐藏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆