CardLayout 在 windows 上无法正确呈现

CardLayout not rendering properly on windows

我一直在处理新项目的登录屏幕,在 windows 上使用 CardLayout 时遇到了奇怪的渲染 "error"。

Mac 上的注册屏幕:SignUp Screen Mac

屏幕在我的 Mac 计算机上正确加载,但在 windows 上单击 "Register" 或单击 "Back" 后它们看起来像这样。

windows 上的相同屏幕:SignUp Screen Windows

如您所见,在 windows 上,来自 CardLayout 的 SignUp "card" 呈现在 Login "card" 上,没有隐藏另一个,反之亦然,不像 mac。

现在我的问题是,这是否是由于透明背景造成的,因此 windows 认为后面的那个应该仍然可见,或者它是否会创建一个全新的 "card" 每个是时候我换个地方了,还是忘了把后面的那个一起藏起来?

为什么这适用于 Mac 但不适用于 Windows?

另外,我该如何解决这个问题?

我会把整个Class放上来,大家可以自己测试一下。

(旁注:您可能还会注意到按钮 "Register" 在 windows 上显示白色按钮形状,即使它具有 btnRegister.setBorder(null);设置(适用于 Mac))

完整的Class代码:

package testing;

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.JTextField;

import utilities.ComponentMover;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;

import javax.swing.JSeparator;
import javax.swing.JPasswordField;

@SuppressWarnings("serial")
public class ClientStarter extends JFrame implements ActionListener {

JPanel cards;

private int height = 450;
private int width = 700;
private int trasparancy = 90;
private int labelWidth = 400;

final static String BACK = "Back";
final static String REGISTER = "Register";

private Color textLine = Color.GRAY;
private Color textColor = Color.WHITE;
private Color tipColor = Color.GRAY;
private Color disabledTipColor = new Color(90, 90, 90);



//   LOGIN //

JPanel loginCard;

public static JTextField usernameIn = new JTextField();
private JLabel userLabel = new JLabel("Username :");

public static JPasswordField passwordIn = new JPasswordField();
private JLabel passLabel = new JLabel("Password :");

private JButton btnLogin = new JButton("Login");
private JButton btnRegister = new JButton(REGISTER);
private JLabel registerLabel = new JLabel("Don't own an Account? ");

private JSeparator separatorUser = new JSeparator();
private JSeparator separatorPass = new JSeparator();

//    SIGNUP   //

JPanel joinCard;

public static JTextField emailNew = new JTextField();
public static JLabel newEmailLabel = new JLabel("Email : (Not Available)");

public static JTextField usernameNew = new JTextField();
public static JLabel newUserLabel = new JLabel("Username :");

public static JTextField passwordNew = new JTextField();
public static JLabel newPassLabel = new JLabel("Password :");

public static JTextField passwordNew2 = new JTextField();
public static JLabel newPassLabel2 = new JLabel("Re-enter password :");


private JButton btnSignUp = new JButton("Signup");
private JButton btnBack = new JButton(BACK);

private JSeparator separatorMailNew = new JSeparator();
private JSeparator separatorUserNew = new JSeparator();
private JSeparator separatorPassNew = new JSeparator();
private JSeparator separatorPassNew2 = new JSeparator();

public ClientStarter() {
    getContentPane().setBackground(Color.GRAY);
    setUndecorated(true);
    setBackground(new Color(0, 0, 0, trasparancy));
    setTitle("EnChant");
    setSize(width, height);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);
    setResizable(false);

    //Create the cards
    //     LOGIN     //
    Font avenir = new Font("Avenir", Font.PLAIN, 18);

    loginCard = new JPanel();
    loginCard.setLayout(null);

    usernameIn.setBounds(348, 150, 327, 35);
    usernameIn.setColumns(10);
    usernameIn.setFont(avenir);
    usernameIn.setBorder(null);

    passwordIn.setBounds(348, usernameIn.getY() + 74, 327, 35);
    passwordIn.setColumns(10);
    passwordIn.setFont(avenir);
    passwordIn.setBorder(null);

    userLabel.setBounds(usernameIn.getX(), usernameIn.getY() - 20, labelWidth, 16);
    userLabel.setFont(avenir);

    passLabel.setBounds(passwordIn.getX(), passwordIn.getY() - 20, labelWidth, 16);
    passLabel.setFont(avenir);

    btnLogin.setBounds(348, passwordIn.getY() + 81, 327, 45);
    btnLogin.addActionListener(this);

    registerLabel.setBounds(btnLogin.getX(), btnLogin.getY() + btnLogin.getHeight() + 5, labelWidth, 16);
    registerLabel.setFont(new Font("Avenir", Font.PLAIN, 13));  
    btnRegister.setBounds(btnLogin.getX() + 130, registerLabel.getY() - 1, 70, 16);
    btnRegister.addActionListener(this);
    btnRegister.setBorder(null);


    loginCard.setBackground(new Color(0, 0, 0, trasparancy));

    usernameIn.setBackground(new Color(0, 0, 0, 0));
    usernameIn.setForeground(textColor);

    passwordIn.setBackground(new Color(0, 0, 0, 0));
    passwordIn.setForeground(textColor);


    userLabel.setForeground(tipColor);
    passLabel.setForeground(tipColor);


    btnLogin.setForeground(new Color(70, 130, 180));
    btnLogin.setBackground(Color.WHITE);

    btnRegister.setForeground(new Color(70, 130, 180));
    registerLabel.setForeground(tipColor);


    separatorUser.setForeground(textLine);
    separatorUser.setBounds(usernameIn.getX(), usernameIn.getY()+usernameIn.getHeight()-8, usernameIn.getWidth(), 6);

    separatorPass.setForeground(textLine);
    separatorPass.setBounds(passwordIn.getX(), passwordIn.getY()+passwordIn.getHeight()-8, passwordIn.getWidth(), 6);

    loginCard.add(usernameIn);
    loginCard.add(separatorUser);
    loginCard.add(userLabel);
    loginCard.add(passwordIn);
    loginCard.add(separatorPass);
    loginCard.add(passLabel);
    loginCard.add(btnLogin);
    loginCard.add(btnRegister);
    loginCard.add(registerLabel);



    //    SIGNUP   //
    joinCard = new JPanel();
    joinCard.setLayout(null);

    emailNew.setBounds(348, 62, 327, 35);
    emailNew.setColumns(10);
    emailNew.setFont(avenir);
    emailNew.setBorder(null);
    emailNew.setEditable(false);

    usernameNew.setBounds(348, emailNew.getY() + 74, 327, 35);
    usernameNew.setColumns(10);
    usernameNew.setFont(avenir);
    usernameNew.setBorder(null);

    passwordNew.setBounds(348, usernameNew.getY() + 74, 327, 35);
    passwordNew.setColumns(10);
    passwordNew.setFont(avenir);
    passwordNew.setBorder(null);

    passwordNew2.setBounds(348, passwordNew.getY() + 74, 327, 35);
    passwordNew2.setColumns(10);
    passwordNew2.setFont(avenir);
    passwordNew2.setBorder(null);

    //32, 106, 180, 254  : 2, 76, 150, 224

    newEmailLabel.setBounds(emailNew.getX(), emailNew.getY() - 20, labelWidth, 16);
    newEmailLabel.setFont(avenir);

    newUserLabel.setBounds(usernameNew.getX(), usernameNew.getY() - 20, labelWidth, 16);
    newUserLabel.setFont(avenir);

    newPassLabel.setBounds(passwordNew.getX(), passwordNew.getY() - 20, labelWidth, 16);
    newPassLabel.setFont(avenir);

    newPassLabel2.setBounds(passwordNew2.getX(), passwordNew2.getY() - 20, labelWidth, 16);
    newPassLabel2.setFont(avenir);


    btnSignUp.setBounds(348, passwordNew2.getY() + 71, 327, 45); //335  // +81
    btnSignUp.addActionListener(this);

    btnBack.setBounds(btnSignUp.getX()-70, btnSignUp.getY(), 70, 45); //380 
    btnBack.addActionListener(this);


    joinCard.setBackground(new Color(0, 0, 0, trasparancy));

    emailNew.setBackground(new Color(0, 0, 0, 0));
    emailNew.setForeground(textColor);

    usernameNew.setBackground(new Color(0, 0, 0, 0));
    usernameNew.setForeground(textColor);

    passwordNew.setBackground(new Color(0, 0, 0, 0));
    passwordNew.setForeground(textColor);

    passwordNew2.setBackground(new Color(0, 0, 0, 0));
    passwordNew2.setForeground(textColor);

    newEmailLabel.setForeground(disabledTipColor);
    newUserLabel.setForeground(tipColor);
    newPassLabel.setForeground(tipColor);
    newPassLabel2.setForeground(tipColor);

    btnSignUp.setForeground(new Color(70, 130, 180));
    btnBack.setBackground(Color.WHITE);


    separatorMailNew.setBounds(emailNew.getX(), emailNew.getY()+emailNew.getHeight()-8, emailNew.getWidth(), 6);
    separatorMailNew.setForeground(textLine);

    separatorUserNew.setBounds(usernameNew.getX(), usernameNew.getY()+usernameNew.getHeight()-8, usernameNew.getWidth(), 6);
    separatorUserNew.setForeground(textLine);

    separatorPassNew.setBounds(passwordNew.getX(), passwordNew.getY()+passwordNew.getHeight()-8, passwordNew.getWidth(), 6);
    separatorPassNew.setForeground(textLine);

    separatorPassNew2.setBounds(passwordNew2.getX(), passwordNew2.getY()+passwordNew2.getHeight()-8, passwordNew2.getWidth(), 6);
    separatorPassNew2.setForeground(textLine);

    joinCard.add(emailNew);
    joinCard.add(newEmailLabel);
    joinCard.add(usernameNew);
    joinCard.add(newUserLabel);
    joinCard.add(passwordNew);
    joinCard.add(newPassLabel);
    joinCard.add(passwordNew2);
    joinCard.add(newPassLabel2);
    joinCard.add(btnSignUp);
    joinCard.add(btnBack);
    joinCard.add(separatorMailNew);
    joinCard.add(separatorUserNew);
    joinCard.add(separatorPassNew);
    joinCard.add(separatorPassNew2);



    //    End    //

    JPanel whiteRectLogin = new JPanel();
    whiteRectLogin.setBackground( Color.WHITE );
    whiteRectLogin.setBounds(0, 0, 250, height);
    loginCard.add(whiteRectLogin);

    JPanel whiteRectJoin = new JPanel();
    whiteRectJoin.setBackground( Color.WHITE );
    whiteRectJoin.setBounds(0, 0, 250, height);
    joinCard.add(whiteRectJoin);



    cards = new JPanel(new CardLayout());
    cards.setBackground(new Color(0, 0, 0, trasparancy));

    cards.add(loginCard, BACK);
    cards.add(joinCard, REGISTER);

    getContentPane().add(cards); 

    //Top, Left, bottom, right
    ComponentMover cm = new ComponentMover(this, this);
    cm.setEdgeInsets(new Insets(-50, 1, 0, -50));

    validate();

    repaint();
    getContentPane().setLayout(null);


}


public void actionPerformed(ActionEvent e) {
    if(e.getSource() == btnRegister) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, REGISTER);
        loginCard.setVisible(false);

    }
    if(e.getSource() == btnBack) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, BACK);
        loginCard.setVisible(false);
    }
    if(e.getSource() == btnSignUp) {
        //new SignUpCheck();
    }
}

public static void main(String[] args) {
    new ClientStarter();
}
}

could this be caused because of the transparent background

可能吧。 Swing 无法正确渲染透明背景。 Swing 期望组件完全不透明或完全透明。

查看 Backgrounds With Transparency 以获得问题的完整描述和一些解决方案。

您可以使用如下代码对每个组件进行自定义绘制:

JPanel panel = new JPanel()
{
    protected void paintComponent(Graphics g)
    {
        g.setColor( getBackground() );
        g.fillRect(0, 0, getWidth(), getHeight());
        super.paintComponent(g);
    }
};
panel.setOpaque(false); // background of parent will be painted first
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);

或者你可以用AlphaContainerclass给你画

此外,您还有其他几个问题:

  1. 不要为您的 Swing 组件使用静态变量。那不是 static 关键字的正确用法。

  2. 不要使用空布局和 setBounds()。 Swing 旨在与布局管理器一起使用。布局管理器在多个平台上运行良好。

  3. 不要使用 alpha 值 0。0 表示完全透明,因此只需在组件上使用 setOpaque(false) 方法即可。

  4. 不要继续创建新的 Color 对象。每个组件都可以使用相同的 Color 对象。它可以节省资源,并且可以更轻松地一次更改所有组件的所有颜色。

  5. 不要在 class 的构造函数中使用 validate() 和 repaint()。在调用 setVisible(true) 之前,应将所有组件添加到框架中,因此不需要这些方法。