JTextField 插入符号未正确显示

JTextField caret not showing properly

我在 JFrame 中有一个 JTextField。插入符号在看起来正常的插入符号和半画的插入符号之间闪烁。

插入符号仅显示在顶部和底部。我试过使用自定义插入符号,但它们都只显示部分图形。密码字段的错误也相同。我不知道它是否相关,但我在 mac 上并且我没有 windows machine 来测试错误是否发生在 windows 上出色地。 这是我的 window 的 MCVE(尽可能短):

public class Login1 extends JFrame implements Serializable {
private static final long serialVersionUID = 1L;

private JPanel pnl_mainPanel;
private JButton btn_login_main, btn_newAccount, btn_seeAccounts, btn_login_login, btn_cancel_login, btn_next, btn_cancel_new;
private JTextField tf_username_login, tf_username_new;
private JPasswordField pf_password, pf_password_new, pf_password_confirm;
private JLabel lbl_username_login, lbl_password_login, lbl_username_new, lbl_password_new, lbl_password_confirm;

private static final String TITLE = "Login";
private final int WINDOW_WIDTH = 400;
private final int WINDOW_HEIGHT = 300;
private final Dimension WINDOW_DIM = new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT);

public Login1() {
    super(TITLE);
    setSize(WINDOW_DIM);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new BorderLayout());
    buildPanel();
    add(pnl_mainPanel);
    setVisible(true);
    setResizable(false);
}

private void buildPanel() {
    pnl_mainPanel = new JPanel();
    btn_login_main = new JButton("Login");
    btn_newAccount = new JButton("New Account");
    btn_seeAccounts = new JButton("ℹ");

    // login page
    btn_login_login = new JButton("Login");
    btn_cancel_login = new JButton("Cancel");
    tf_username_login = new JTextField();
    pf_password = new JPasswordField();
    lbl_username_login = new JLabel("Username:");
    lbl_password_login = new JLabel("Password:");

    // new account page
    btn_next = new JButton("Next");
    btn_cancel_new = new JButton("Cancel");
    tf_username_new = new JTextField();
    pf_password_new = new JPasswordField();
    pf_password_confirm = new JPasswordField();
    lbl_username_new = new JLabel("Username:");
    lbl_password_new = new JLabel("Password:");
    lbl_password_confirm = new JLabel("<html>Confirm<br>Password:</html>");

    pnl_mainPanel.setLayout(null);
    pnl_mainPanel.add(btn_login_main);
    pnl_mainPanel.add(btn_newAccount);
    pnl_mainPanel.add(btn_seeAccounts);

    btn_login_login.setSize(75, 30);
    btn_login_login.setLocation(new Point(310, 175));
    btn_cancel_login.setSize(75, 30);
    btn_cancel_login.setLocation(new Point(310, 215));
    tf_username_login.setSize(200, 25);
    tf_username_login.setLocation(new Point(100, 178));
    pf_password.setSize(200, 25);
    pf_password.setLocation(new Point(100, 218));
    lbl_username_login.setSize(100, 25);
    lbl_username_login.setLocation(new Point(15, 178));
    lbl_password_login.setSize(100, 25);
    lbl_password_login.setLocation(new Point(15, 218));

    btn_next.setSize(75, 30);
    btn_next.setLocation(new Point(310, 160));
    btn_cancel_new.setSize(75, 30);
    btn_cancel_new.setLocation(new Point(310, 200));
    tf_username_new.setSize(200, 25);
    tf_username_new.setLocation(new Point(100, 163));
    pf_password_new.setSize(200, 25);
    pf_password_new.setLocation(new Point(100, 203));
    pf_password_confirm.setSize(200, 25);
    pf_password_confirm.setLocation(new Point(100, 243));
    lbl_username_new.setSize(100, 25);
    lbl_username_new.setLocation(new Point(15, 163));
    lbl_password_new.setSize(100, 25);
    lbl_password_new.setLocation(new Point(15, 203));
    lbl_password_confirm.setSize(100, 30);
    lbl_password_confirm.setLocation(new Point(15, 238));

    btn_login_main.setSize(163, 100);
    btn_login_main.setLocation(new Point(25, 150));
    btn_newAccount.setSize(162, 100);
    btn_newAccount.setLocation(new Point(213, 150));
    btn_seeAccounts.setSize(20, 20);
    btn_seeAccounts.setLocation(new Point(375, 255));

    btn_login_main.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            pnl_mainPanel.remove(btn_login_main);
            pnl_mainPanel.remove(btn_newAccount);

            pnl_mainPanel.remove(btn_next);
            pnl_mainPanel.remove(btn_cancel_new);
            pnl_mainPanel.remove(tf_username_new);
            pnl_mainPanel.remove(pf_password_new);
            pnl_mainPanel.remove(pf_password_confirm);
            pnl_mainPanel.remove(lbl_username_new);
            pnl_mainPanel.remove(lbl_password_new);
            pnl_mainPanel.remove(lbl_password_confirm);

            pnl_mainPanel.add(btn_login_login);
            pnl_mainPanel.add(btn_cancel_login);
            pnl_mainPanel.add(tf_username_login);
            pnl_mainPanel.add(pf_password);
            pnl_mainPanel.add(lbl_username_login);
            pnl_mainPanel.add(lbl_password_login);
            repaint();
            tf_username_login.requestFocus();
        }
    });
    btn_cancel_login.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            pnl_mainPanel.remove(btn_login_login);
            pnl_mainPanel.remove(tf_username_login);
            pnl_mainPanel.remove(pf_password);
            pnl_mainPanel.remove(btn_cancel_login);
            pnl_mainPanel.remove(lbl_username_login);
            pnl_mainPanel.remove(lbl_password_login);
            pnl_mainPanel.add(btn_login_main);
            pnl_mainPanel.add(btn_newAccount);
            repaint();
        }
    });
    btn_newAccount.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            pnl_mainPanel.remove(btn_login_main);
            pnl_mainPanel.remove(btn_newAccount);
            pnl_mainPanel.add(btn_next);
            pnl_mainPanel.add(btn_cancel_new);
            pnl_mainPanel.add(tf_username_new);
            pnl_mainPanel.add(pf_password_new);
            pnl_mainPanel.add(pf_password_confirm);
            pnl_mainPanel.add(lbl_username_new);
            pnl_mainPanel.add(lbl_password_new);
            pnl_mainPanel.add(lbl_password_confirm);
            repaint();
            tf_username_new.requestFocus();
        }
    });
    btn_cancel_new.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            pnl_mainPanel.remove(btn_next);
            pnl_mainPanel.remove(btn_cancel_new);
            pnl_mainPanel.remove(tf_username_new);
            pnl_mainPanel.remove(pf_password_new);
            pnl_mainPanel.remove(pf_password_confirm);
            pnl_mainPanel.remove(lbl_username_new);
            pnl_mainPanel.remove(lbl_password_new);
            pnl_mainPanel.remove(lbl_password_confirm);
            pnl_mainPanel.add(btn_login_main);
            pnl_mainPanel.add(btn_newAccount);
            repaint();
        }
    });

}

public static void main(String[] args){
    Login1 l = new Login1();
}
}

提前致谢!

我可以确认这发生在我的 Mac 上,而不会发生在我的 Linux 上。

将字段的高度至少改成28即可轻松解决

tf_username_login.setSize(200, 28);

我的猜测是Mac OS X无法创建高度小于28像素的字段(虽然这可能是字体选择等问题,我没有测试过那么远)。出于某种原因,它会在全高(28 像素)处绘制完整的插入符号,但会以用户指定的大小 (25) 将其擦除,这会导致您注意到的现象。