对其及其父组件使用“setVisible(true)”后组件不可见

问题描述 投票:0回答:2

我有一个 Java 8 应用程序,其中有几个

JTextField
和一个用于登录数据库的
JButton
,以及
JTextArea
内的
JScrollPane
用于显示错误。如果没有要显示的错误消息,则文本区域和滚动窗格都必须隐藏 (
setVisible(false)
)。

public static ResourceBundle resourceBundle;
private static JTextArea textarea_error;
private JScrollPane scrollPane_error;
private JButton button_login;
private Connection connection = null;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                resourceBundle = ResourceBundle.getBundle("Bundle", Locale.English);
                Main frame = new Main(); 
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            } catch (Exception e) {
                //Error handling with the TextArea
            }
        }
    });
}

public Main() {
    textarea_error = new JTextArea();
    textarea_error.setEditable(false);
    textarea_error.setText("Error");
    scrollPane_error = new JScrollPane(textarea_error);
    scrollPane_error.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
    button_login = new JButton(resourceBundle.getString("main.button.login"));
    button_login.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            startLogin();
        }
    });
    //Aligning components,... here

    textarea_error.setVisible(false);
    scrollPane_error.setVisible(false); //this
}

private void startLogin() {
    //Read TextField input content here (user, pw, server-url)
    SwingWorker<String, String> sw = new SwingWorker<String, String>() {
        @Override
        protected String doInBackground() throws Exception {
            login(user,pw,server);
            return null;
        }
                
    };
    sw.execute();
}

private void login(String user, String pw, String server) {
    try {
        DriverManager.registerDriver(new SQLServerDriver());
        connection = DriverManager.getConnection(server, user, pw);
        Statement s = connection.createStatement();
    } catch (SQLException e) {
        scrollPane_error.setVisible(true); //this
        textarea_error.setText(resourceBundle.getString("main.error.userpw"));
        textarea_error.setCaretPosition(0);
        textarea_error.setVisible(true);
    }
}

问题:当出现错误(例如错误的用户名或密码)但文本区域和滚动窗格仍然不可见时,会调用

catch
。如果我只更改文本区域的可见性并始终使滚动窗格保持可见(=删除两个“此”行 - 这也始终显示滚动窗格的边框),那么这工作正常,但一旦我也设置了滚动窗格的可见性,它也不会或者它的孩子回来了。

我不想使用

setEnable
,因为我希望它们仍然占用空间,即使不需要它们。

我已经尝试使用

invalidate
revalidate
repaint
(甚至在滚动窗格上)但这没有帮助。我
setVisible(true)
这两个组件的顺序似乎也并不重要。

为什么会发生这种情况以及如何解决?

java swing visibility jscrollpane jtextarea
2个回答
0
投票

这是我创建的一个简单示例。

Wxample

当 GUI 出现时,

JTextArea
JScrollPane
设置为不可见。当您单击“登录”
JButton
时,
JTextArea
JScrollPane
将变得可见并显示错误消息。

Message

这是完整的可运行代码。全部 102 行。

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class LoginExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new LoginExample());
    }

    private JFrame frame;

    private JScrollPane scrollPane;

    private JTextArea errorArea;

    @Override
    public void run() {
        frame = new JFrame("Login Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createLoginPanel(), BorderLayout.CENTER);
        frame.add(createMessagePanel(), BorderLayout.SOUTH);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public JPanel createLoginPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5);

        gbc.gridx = 0;
        gbc.gridy = 0;
        JLabel label = new JLabel("UserID:");
        panel.add(label, gbc);

        gbc.gridx++;
        JTextField useridField = new JTextField(20);
        panel.add(useridField, gbc);

        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Password:");
        panel.add(label, gbc);

        gbc.gridx++;
        JPasswordField passwordField = new JPasswordField(20);
        panel.add(passwordField, gbc);

        gbc.gridwidth = 2;
        gbc.gridx = 0;
        gbc.gridy++;
        JButton button = new JButton("Login");
        panel.add(button, gbc);

        button.addActionListener(e -> {
            errorArea.setText("Error message");
            errorArea.setVisible(true);
            scrollPane.setVisible(true);
            frame.pack();
        });

        return panel;
    }

    private JPanel createMessagePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        errorArea = new JTextArea(5, 30);
        errorArea.setWrapStyleWord(true);
        errorArea.setLineWrap(true);
        errorArea.setEditable(false);
        errorArea.setVisible(false);
        scrollPane = new JScrollPane(errorArea);
        scrollPane.setVisible(false);

        panel.add(scrollPane);

        return panel;
    }

}

0
投票

根据您问题中的代码,您正在从

SwingWorker
调用方法 login,这意味着方法
login
确实 notEvent Dispatch Thread (EDT)中运行,并且您正在设置
ScrollPane 
在该方法中可见。

直接从方法

login
调用方法
startLogin
,即完全取消
SwingWorker
,或者向 SwingWorker 添加
done
方法,或者使用 SwingWorker 注册一个
PropertyChangeListener
(通过方法添加PropertyChangeListener)。

© www.soinside.com 2019 - 2024. All rights reserved.