java - 如何在Java中更新LookAndFeel?

标签 java swing repaint look-and-feel

我编写了一个程序,首先更新测试 GUI 上的 LookAndFeel。一旦用户单击“选择”按钮,LookAndFeel 就会传递到主 GUI 方法,该方法使用该选择创建一个新窗口。

效果很好。虽然,当用户循环浏览各种 LookAndFeels 时,测试 GUI 并没有真正更新并显示更改。每次单击更改按钮时,我都会更新并显示当前的 LookAndFeel(和 repain();),所以我知道它正在更改。此外,当您点击选择时,将使用您当时使用的任何选项创建新的 GUI(即使测试 GUI 窗口没有显示更改)。

我做错了什么?

    import javax.swing.*;           //UI.Manager <-- available
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.UIManager.*;
    import javax.imageio.ImageIO;
    import java.io.IOException;
    import java.net.URL;

    public class gui1 {
    static JFrame frame1, testFrame;
    static Container pane, testPane;
    static JButton btnConnect, btnDisconnect, changeButton, selectButton;
    static JLabel lblServer, lblUsername, lblPassword, lblPort, testLabel;
    static JTextField txtServer, txtUsername, txtPassword, txtPort;
    static Insets insets;
    static JTextArea area, testArea;
    public JScrollPane scroller, testScroller;
    static int  currentIndex;


URL frameImage;
Image img;

static boolean LookAndFeelSelected;

public static void main(String[] args){
    gui1 begin = new gui1();
}

public gui1() {

    //build our test gui & components
    testFrame = new JFrame("Select which LookAndFeel you prefer..");
    testFrame.setSize(375, 250);
    testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    testLabel = new JLabel("Text Example", JLabel.CENTER);
    testArea = new JTextArea(300,200);
    testPane = testFrame.getContentPane();
    changeButton = new JButton("Change");
    selectButton = new JButton("Select");
    testScroller = new JScrollPane(testArea);
    testScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    testScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

    testPane.add(changeButton);
    testPane.add(selectButton);
    testFrame.getContentPane().add(BorderLayout.WEST, changeButton);
    testFrame.getContentPane().add(BorderLayout.EAST, selectButton);
    testFrame.getContentPane().add(BorderLayout.CENTER, testScroller);
    testFrame.getContentPane().add(BorderLayout.NORTH, testLabel);

    changeButton.addActionListener(new changeListener());
    selectButton.addActionListener(new selectListener());

    testFrame.setVisible(true);

    while(!LookAndFeelSelected) {
        try{
            Thread.sleep(500);
        }catch(InterruptedException ex) {ex.printStackTrace();}
    }

    System.out.println("Selected!");
    //start the real GUI with selected LookAndFeel
    testFrame.dispose();
    buildGui(UIManager.getLookAndFeel());
}
public void buildGui(LookAndFeel chosen){
    //The frame and panel
    frame1 = new JFrame("Sample GUI Application");
    frame1.setSize(800, 230);
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pane = frame1.getContentPane();
    pane.setLayout(null);
    insets = pane.getInsets();

    //Set the image
    try{
        frameImage = new URL("http://i.imgur.com/jMaYO1f.jpg");
        img = ImageIO.read(frameImage);
    }catch(IOException ex){ex.printStackTrace();}
    frame1.setIconImage(img);

    //Construct our objects for gui
    btnConnect = new JButton("Connect");
    btnDisconnect = new JButton("Disconnect");
    lblServer = new JLabel("Remote Host: ");
    lblUsername = new JLabel("Username: ");
    lblPassword = new JLabel("Password: ");
    lblPort = new JLabel("Port #");
    txtServer = new JTextField(10);
    txtPassword = new JTextField(10);
    txtUsername = new JTextField(10);
    txtPort = new JTextField(5);
    area = new JTextArea(700, 125);
    area.setLineWrap(true);
    area.setEditable(false);
    scroller = new JScrollPane(area);
    scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

    //Add components to the pane
    pane.add(lblServer);
    pane.add(lblServer);
    pane.add(lblPassword);
    pane.add(lblUsername);
    pane.add(lblPort);
    pane.add(txtServer);
    pane.add(txtPort);
    pane.add(txtPassword);
    pane.add(txtUsername);
    pane.add(btnConnect);
    pane.add(btnDisconnect);
    pane.add(scroller);  //includes area and scroller!


    //Arrange our components in the pane
    lblServer.setBounds(insets.left + 5, insets.top + 5, lblServer.getPreferredSize().width, lblServer.getPreferredSize().height);
    txtServer.setBounds(lblServer.getX() + lblServer.getWidth() + 5, insets.top + 5, txtServer.getPreferredSize().width, txtServer.getPreferredSize().height);
    lblUsername.setBounds(txtServer.getX() + txtServer.getWidth() + 5, insets.top + 5, lblUsername.getPreferredSize().width, lblUsername.getPreferredSize().height);
    txtUsername.setBounds(lblUsername.getX() + lblUsername.getWidth() + 5, insets.top + 5, txtUsername.getPreferredSize().width, txtUsername.getPreferredSize().height);
    lblPassword.setBounds(txtUsername.getX() + txtUsername.getWidth() + 5, insets.top + 5, lblPassword.getPreferredSize().width, lblPassword.getPreferredSize().height);
    txtPassword.setBounds(lblPassword.getX() + lblPassword.getWidth() + 5, insets.top + 5, txtPassword.getPreferredSize().width, txtPassword.getPreferredSize().height);
    lblPort.setBounds(txtPassword.getX() + txtPassword.getWidth() + 5, insets.top + 5, lblPort.getPreferredSize().width, lblPort.getPreferredSize().height);
    txtPort.setBounds(lblPort.getX() + lblPort.getWidth() + 5, insets.top + 5, txtPort.getPreferredSize().width, txtPort.getPreferredSize().height);
    btnConnect.setBounds(txtPort.getX() + txtPort.getWidth() + 5, insets.top + 5, btnConnect.getPreferredSize().width, btnConnect.getPreferredSize().height);
    btnDisconnect.setBounds(insets.left + 5, lblServer.getY() + lblServer.getHeight() + 15, btnDisconnect.getPreferredSize().width, btnDisconnect.getPreferredSize().height);
    scroller.setBounds(insets.left + 5, btnDisconnect.getX() + btnDisconnect.getHeight() + 33, 760, 125);

    //Add button listeners
    btnConnect.addActionListener(new connectListener());
    btnDisconnect.addActionListener(new disconnectListener());

    //Change the Look & Feel
    try {
        UIManager.setLookAndFeel(chosen);
    } catch (Exception ex) {ex.printStackTrace();}

    frame1.setVisible(true);
    frame1.setResizable(false);
}


public static class connectListener implements ActionListener {
    public void actionPerformed(ActionEvent event){
        String toField = String.format("ServerIP: %s \t Username: %s \t Password: %s \t Port: %s\n", txtServer.getText(), txtUsername.getText(),
                txtPassword.getText(), txtPort.getText());
        area.append(toField);
    }
}

public static class disconnectListener implements ActionListener {
    public void actionPerformed(ActionEvent event){
        area.append("Disconnected ..\n");
    }
}
// Here only for initial LookAndFeel selection!
public static class changeListener implements ActionListener {
    public void actionPerformed(ActionEvent event){
        LookAndFeelInfo[] lafArray = UIManager.getInstalledLookAndFeels();  //not actual LookAndFeel(just name), thus use LookAndFeelInfo

        try {
            if (currentIndex == lafArray.length - 1) {
                currentIndex = 0;
                System.out.println("You have seen all Look and Feels, starting over .. \n\n");
            }
            UIManager.setLookAndFeel(lafArray[currentIndex++].getClassName());
            testFrame.getContentPane().validate();
            testFrame.getContentPane().repaint();    //repaint the frame to update changes

        }catch(Exception ex) {ex.printStackTrace();}
        String LookAndFeelName = String.format("Changed to: %s",UIManager.getLookAndFeel().getClass());     //gets current and displays name
        System.out.println(LookAndFeelName);
    }
}

public static class selectListener implements ActionListener {
    public void actionPerformed(ActionEvent event){
        LookAndFeelSelected = true;
    }
}

}

最佳答案

这不是重新绘制的问题,外观和感觉比仅仅绘制颜色更深入。看这个教程http://www.roseindia.net/java/example/java/swing/GettingAndSettingLAF.shtml

在下面,您可以在按钮单击更改时更改外观和感觉:

testFrame.getContentPane().validate();
testFrame.getContentPane().repaint();

SwingUtilities.updateComponentTreeUI(testFrame);

关于java - 如何在Java中更新LookAndFeel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17032696/

相关文章:

java - 如何通过java中的mouselisteners获取2D数组(jlabel)的索引?

java - 是否可以将 JComponent 及其所有子组件绘制到另一个组件?

java - 如何在java中按下按钮时绘制一个正方形

java - 从 xml 文件检索值的 JAXB 程序

java - 在eclipse中如何获取开发插件的open workspace的文件路径

java.lang.SecurityException : sealing violation: 错误

java - JComponent 显示完整尺寸或根本不显示

java - JFrame 不重绘

java - .setVisible(true) 立即重绘

java - 如何使用 NDK 将 Lame 3.99.5 添加到 Android Studio?