Swing JMenuBar 无法正确呈现

Swing JMenuBar not rendering properly

第一次实际使用与 swing 相关的东西 - 对于糟糕的代码和粗糙的视觉效果深表歉意!
将 swing 用于一个非常复杂的密码检查器学校项目,当我开始加载 JMenuBar 时,它第一次没有正确呈现。一旦我 运行 首先通过其中一个选项,它就会正确重新加载,但第一次出现时是这样的: First render attempt
但是在我 运行 其中一种方法之后,通过单击我添加的其中一个按钮来检查它是否只是损坏的 JFrame 或使用损坏的菜单选项之一,它会重新加载正确,但在 JMenuBar 实际呈现的位置上方有一个小灰色条:Post-method render

视觉效果代码如下:

public void draw_menu(){
        this.parent.pack();
        this.parent.setExtendedState(JFrame.MAXIMIZED_BOTH);
        JButton check = new JButton("Check Password");
        JButton generate = new JButton("Generate Password");
        generate.addActionListener(e -> this.generator());
        check.addActionListener(e -> this.char_checker());
        check.setBounds(500,500, 170, 50);
        generate.setBounds(500, 200, 170, 50);
        this.parent.add(check);
        this.parent.add(generate);
        JMenu a = new JMenu("Check Password");
        JMenu b = new JMenu("Generate Password");
        JMenu c = new JMenu("Extra Codes");
        JMenuItem a1 = new JMenuItem("Enter password >>>");
        JMenuItem b1 = new JMenuItem("Generate >>>");
        JMenuItem c1 = new JMenuItem("Valid >>>");
        JMenuItem c2 = new JMenuItem("Why >>>");
        a1.addActionListener(e -> this.char_checker());
        b1.addActionListener(e -> this.generator());
        c1.addActionListener(e -> JOptionPane.showMessageDialog(Password.this.parent, Arrays.asList(valid_chars).toString(), "Valid Characters", JOptionPane.PLAIN_MESSAGE));
        c2.addActionListener(e -> this.why());
        a.add(a1);
        b.add(b1);
        c.add(c1);
        c.add(c2);
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(a);
        menuBar.add(b);
        menuBar.add(c);
        this.parent.setJMenuBar(menuBar);
        this.parent.add(menuBar);
        this.parent.setVisible(true);
    }

如果你想让整个文件对其进行上下文化(并且能够 运行 它),你可以在下面查看它:

import java.awt.*;
import java.util.*;
import java.lang.*;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import javax.swing.*;

public class Password {

    Scanner scanner;
    String password;
    Integer score;
    List<Character> pass;
    JFrame parent;
    JLabel frameScore;

    static Character[] valid_chars = {'!', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+'};
    static Character[] lower_alpha = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
    static Character[] upper_alpha = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    static Character[] valid_nums = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
    static String[] keyboard_combos = {"qwe", "wer", "ert", "rty", "tyu", "yui", "uio", "iop", "asd", "sdf", "dfg", "fgh", "gjh", "hjk", "jkl", "zxc", "xcv", "cvb", "vbn", "bnm"};

    boolean num = false;
    boolean upper = false;
    boolean lower = false;
    boolean character = false;

    public Password() {
    }

    public void why() throws NullPointerException {
        if (Objects.isNull(this.score)){
            JOptionPane.showMessageDialog(parent, "Try checking a password first!", "Error!", JOptionPane.ERROR_MESSAGE);
            System.out.println("Error -> this.score returns null!\t|\tTry checking a password first!");
            this.draw_menu();
        }
        String out = "Your password achieved a score of "+this.score.toString()+" because you included ";
        if (this.num){out = out.concat("at least one number, ");}
        if (this.character){out = out.concat("at least one special character, ");}
        if (this.upper){out = out.concat("at least one upper case letter, ");}
        if (this.lower){out = out.concat("at least one lower case letter, ");}
        out  = out.concat("Achieving your score of: "+this.score.toString());
        System.out.println(out);
        JOptionPane.showMessageDialog(parent, out, "Score: "+this.score.toString(), JOptionPane.PLAIN_MESSAGE);
        this.draw_menu();
    }
    public void char_checker() {
        this.password = JOptionPane.showInputDialog(this.parent, "Enter your password:", null, JOptionPane.PLAIN_MESSAGE);
        if (this.password.length() == 0) {
            System.out.println("Error <- this.password.length() returns null!\t|\tTry entering a password!");
        }
        if (this.password.length() < 8 || this.password.length() > 24) {
            System.out.println("Error <- this.password.length() exceeds bounds!\t|\t( [Bounds 7 < password < 24] String length = "+this.password.length()+")");
        } else {
            char[] pass_array = this.password.toCharArray();
            for (Character temp : pass_array) {
                if (Arrays.asList(valid_chars).contains(temp) || Arrays.asList(lower_alpha).contains(temp) || Arrays.asList(upper_alpha).contains(temp) || Arrays.asList(valid_nums).contains(temp)) {
                    System.out.print("valid placement @ temp:" + temp);
                } else {
                    System.out.println("\nError <- $temp: '" + temp + "' not found in character bank!\t|\tNot valid character (alphanumerical + valid_chars only)\nEnter valid on menu for more information.");
                    this.draw_menu();
                }
            }
            this.security_score(pass_array);
        }
        this.draw_menu();
    }

    public void security_score(char[] array){
        if (!Objects.isNull(this.frameScore)){
            this.frameScore.setText("");
        }
        this.num = false;
        this.upper = false;
        this.lower = false;
        this.character = false;
        System.out.println("\nGenerating security score...");
        this.score = 0;
        this.score = this.password.length();
        for (Character temp: array) {
            if (Arrays.asList(valid_chars).contains(temp)) {
                if (!this.character) {
                    this.score = this.score + 5;
                    this.character = true;
                }
            } else if (Arrays.asList(valid_nums).contains(temp)){
                if (!this.num){
                    this.score = this.score + 5;
                    this.num = true;
                }
            } else if (Arrays.asList(lower_alpha).contains(temp)){
                if (!this.lower){
                    this.score = this.score + 5;
                    this.lower = true;
                }
            } else if (Arrays.asList(upper_alpha).contains(temp)){
                if (!this.upper){
                    this.score = this.score + 5;
                    this.upper = true;
                }
            }
        }
        if (this.lower && this.upper && this.character && this.num){
            this.score = this.score + 10;
        } else if (!this.character && !this.num) {
            this.score = this.score - 5;
        } else if (!this.character && !this.lower && !this.upper){
            this.score = this.score - 5;
        } else if (!this.lower && !this.upper && !this.num){
            this.score = this.score - 5;
        }
        for (String temp : keyboard_combos){
            if (this.password.contains(temp)) {
                this.score = this.score - 5;
            }
        }

        if (this.score > 20){
            System.out.println("With a score of "+this.score+", your password is Strong.");
        } else if (this.score < 20 && this.score > 0){
            System.out.println("With a score of "+this.score+", your password is Average.");
        } else {
            System.out.println("With a score of "+this.score+", your password is Weak.");
        }
        System.out.println("To see why you achieved a score of "+this.score.toString()+", enter \"why\" on the menu!");
        this.frameScore = new JLabel("<html>Your previous score was: "+this.score.toString()+"<br/>with:"+this.password+"</html>", SwingConstants.CENTER);
        Dimension size = this.frameScore.getPreferredSize();
        this.frameScore.setBounds(150, 100, size.width, size.height);
        this.parent.setLayout(null);
        this.parent.add(this.frameScore);
    }

    public void generator() {
        if (!Objects.isNull(this.frameScore)){
            this.frameScore.setText("");
        }
        if (!Objects.isNull(this.score)) {
            this.frameScore = new JLabel("<html>Your previous score was: " + this.score + "<br/>with:" + this.password + "</html>", SwingConstants.CENTER);
        }
        this.pass.clear();
        System.out.println("generating password...");
        int length = ThreadLocalRandom.current().nextInt(8, 12);
        System.out.println(length);
        int count = 0;
        int item;
        while (count < length - 1){
            int choice = ThreadLocalRandom.current().nextInt(1, 4);
            switch (choice){
                case 1:
                    item = ThreadLocalRandom.current().nextInt(0, valid_chars.length);
                    this.pass.add(valid_chars[item]);
                    count++;

                case 2:
                    item = ThreadLocalRandom.current().nextInt(0, lower_alpha.length);
                    this.pass.add(lower_alpha[item]);
                    count++;

                case 3:
                    item = ThreadLocalRandom.current().nextInt(0, upper_alpha.length);
                    this.pass.add(upper_alpha[item]);
                    count++;

                case 4:
                    item = ThreadLocalRandom.current().nextInt(0, valid_nums.length);
                    this.pass.add(valid_nums[item]);
                    count++;
            }
        }
        System.out.println("Your password is:");
        char[] array = new char[this.pass.size()];
        for (char temp : this.pass){
            System.out.print(temp);
            array[this.pass.indexOf(temp)] = this.pass.get(this.pass.indexOf(temp));
        }
        this.password = String.valueOf(array);
        this.security_score(array);
        System.out.println("Generation complete!");
        if (this.score < 20){
            this.generator();
        }
        JOptionPane.showMessageDialog(parent, "<html>Generation complete!<br/>"+this.password+"</html>", "Generated!", JOptionPane.INFORMATION_MESSAGE);
        this.draw_menu();
    }

    //visual rendering code
    public void draw_menu(){
        this.parent.pack();
        this.parent.setExtendedState(JFrame.MAXIMIZED_BOTH);
        JButton check = new JButton("Check Password");
        JButton generate = new JButton("Generate Password");
        generate.addActionListener(e -> this.generator());
        check.addActionListener(e -> this.char_checker());
        check.setBounds(500,500, 170, 50);
        generate.setBounds(500, 200, 170, 50);
        this.parent.add(check);
        this.parent.add(generate);
        JMenu a = new JMenu("Check Password");
        JMenu b = new JMenu("Generate Password");
        JMenu c = new JMenu("Extra Codes");
        JMenuItem a1 = new JMenuItem("Enter password >>>");
        JMenuItem b1 = new JMenuItem("Generate >>>");
        JMenuItem c1 = new JMenuItem("Valid >>>");
        JMenuItem c2 = new JMenuItem("Why >>>");
        a1.addActionListener(e -> this.char_checker());
        b1.addActionListener(e -> this.generator());
        c1.addActionListener(e -> JOptionPane.showMessageDialog(Password.this.parent, Arrays.asList(valid_chars).toString(), "Valid Characters", JOptionPane.PLAIN_MESSAGE));
        c2.addActionListener(e -> this.why());
        a.add(a1);
        b.add(b1);
        c.add(c1);
        c.add(c2);
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(a);
        menuBar.add(b);
        menuBar.add(c);
        this.parent.setJMenuBar(menuBar);
        this.parent.add(menuBar);
        this.parent.setVisible(true);
    }


    public static void main(String[] args) {
        Password user = new Password();
        user.scanner = new Scanner(System.in);
        user.pass = new ArrayList<>();
        user.parent = new JFrame();
        user.draw_menu();
    }
}

提前致谢!

您应该将菜单的创建与内容分开。请查看以下示例。我将您的菜单、组件和事件逻辑分离为有意义的阶段。

import java.util.*;
import javax.swing.*;

public class App implements Runnable {
    private static final long serialVersionUID = 6924949643971067836L;

    private static final Character[] VALID_CHARS = {'!', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+'};
    private static final Character[] LOWER_ALPHA = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
    private static final Character[] UPPER_ALPHA = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    private static final Character[] VALID_NUMS = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
    private static final String[] KEYBOARD_COMBOS = {"qwe", "wer", "ert", "rty", "tyu", "yui", "uio", "iop", "asd", "sdf", "dfg", "fgh", "gjh", "hjk", "jkl", "zxc", "xcv", "cvb", "vbn", "bnm"};
    
    private Scanner scanner;
    private String password;
    private Integer score;
    private List<Character> pass;
    private JFrame parent;
    private JLabel frameScore;

    private boolean num = false;
    private boolean upper = false;
    private boolean lower = false;
    private boolean character = false;
    
    public App() { }
    
    private void checkPassword() {
        System.out.println("Checking password...");
    }

    private void generatePassword() {
        System.out.println("Generating password...");
    }
    
    private void why() {
        System.out.println("Why...");
    }
    
    protected JPanel createContent() {
        JPanel mainPanel = new JPanel();
        JButton check = new JButton("Check Password");
        JButton generate = new JButton("Generate Password");
        
        check.addActionListener(e -> this.checkPassword());
        generate.addActionListener(e -> this.generatePassword());
        
        check.setBounds(500,500, 170, 50);
        generate.setBounds(500, 200, 170, 50);
        
        mainPanel.add(check);
        mainPanel.add(generate);
        
        return mainPanel;
    }
    
    protected JMenuBar createMenu() {
        JMenuBar menuBar = new JMenuBar();
        JMenu checkPass = new JMenu("Check Password");
        JMenu resetPass = new JMenu("Generate Password");
        JMenu extraCodes = new JMenu("Extra Codes");
        
        JMenuItem enterPass = new JMenuItem("Enter password >>>");
        JMenuItem generatePass = new JMenuItem("Generate >>>");
        JMenuItem verify = new JMenuItem("Valid >>>");
        JMenuItem about = new JMenuItem("Why >>>");
        
        enterPass.addActionListener(e -> this.checkPassword());
        generatePass.addActionListener(e -> this.generatePassword());
        verify.addActionListener(e -> JOptionPane.showMessageDialog(this.parent, Arrays.asList(VALID_CHARS).toString(), "Valid Characters", JOptionPane.PLAIN_MESSAGE));
        about.addActionListener(e -> this.why());
        
        menuBar.add(checkPass);
        menuBar.add(resetPass);
        menuBar.add(extraCodes);
        
        checkPass.add(enterPass);
        resetPass.add(generatePass);
        extraCodes.add(verify);
        extraCodes.add(about);
        
        return menuBar;
    }
    
    @Override
    public void run() {
        this.parent = new JFrame();
        
        this.parent.setJMenuBar(createMenu());
        this.parent.setContentPane(createContent());
        this.parent.pack();
        this.parent.setLocationRelativeTo(null);
        this.parent.setVisible(true);
    }
    
    public static void main(String[] args) {
        try {
            SwingUtilities.invokeAndWait(new App());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}