Java JTabbedPane - 更改所选选项卡之前的操作

daa*_*lgi 0 java swing jtabbedpane changelistener

使用 JTabbedPane,我想捕捉新选项卡选择更改生效之前的瞬间并执行操作。它类似于摆动组件的焦点丢失事件。目的是在tab改变的时候将几个JTextField的文本保存到一个外部文件中,这样每次用户点击不同的tab时,当前tab的值都会写入到外部文件中。

我一直在使用 ChangeListener 来跟踪选项卡的更改,但还没有找到满足我需要的方法。在下一个简单示例中如何实现它的任何想法?

import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TabSample {
    static void add(JTabbedPane tabbedPane, String label) {
        JButton button = new JButton(label);
        tabbedPane.addTab(label, button);
    }

    public static void main(String args[]) {
        JFrame frame = new JFrame("TabSample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTabbedPane tabbedPane = new JTabbedPane();

        String titles[] = { "Geometry", "Materials", "Analysis"};
        for (int i = 0, n = titles.length; i < n; i++) {
            add(tabbedPane, titles[i]);
        }

        ChangeListener changeListener = new ChangeListener() {
            public void stateChanged(ChangeEvent changeEvent) {
                JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource();
                int index = sourceTabbedPane.getSelectedIndex();
                System.out.println("Tab changed to: " + sourceTabbedPane.getTitleAt(index));
        }
        };
        tabbedPane.addChangeListener(changeListener);
        frame.add(tabbedPane, BorderLayout.CENTER);
        frame.setSize(400, 150);
        frame.setVisible(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

Hov*_*els 5

一种可能的方法,我不能 100% 确定这样做是否可以接受,而是为 JTabbedPane 创建您自己的模型,这是一个实现 SingleSelectionModel 的模型(检查SingleSelectionModel API),它覆盖了setSelectedIndex(int index)方法,我很确定 Swing 在想要告诉 JTabbedPane 更改选项卡时使用的方法。如果您创建一个从DefaultSingleSelectionModel扩展的类,一个实现上述接口并覆盖此方法的具体类,您可以在调用 super 的方法之前进行方法调用,从而在选项卡更改之前进行 GUI 调用。例如,您的setSelectedIndex方法可能如下所示:

    @Override
    public void setSelectedIndex(int index) {
        if (activated) {
            String text = String.format("Before change, old index: %d; new index: %d", super.getSelectedIndex(), index);
            JOptionPane.showMessageDialog(gui, text);
        }
        super.setSelectedIndex(index);
    }
Run Code Online (Sandbox Code Playgroud)

使用上面的代码可以实现如下:

import java.awt.BorderLayout;
import java.awt.Component;

import javax.swing.DefaultSingleSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TabSample {
    static void add(JTabbedPane tabbedPane, String label) {
        JButton button = new JButton(label);
        tabbedPane.addTab(label, button);
    }

    public static void main(String args[]) {
        JFrame frame = new JFrame("TabSample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MySingleSelectionModel selectionModel = new MySingleSelectionModel(frame);

        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.setModel(selectionModel);

        String titles[] = { "Geometry", "Materials", "Analysis"};
        for (int i = 0, n = titles.length; i < n; i++) {
            add(tabbedPane, titles[i]);
        }

        ChangeListener changeListener = new ChangeListener() {
            public void stateChanged(ChangeEvent changeEvent) {
                JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource();
                int index = sourceTabbedPane.getSelectedIndex();
                System.out.println("Tab changed to: " + sourceTabbedPane.getTitleAt(index));
        }
        };
        tabbedPane.addChangeListener(changeListener);
        frame.add(tabbedPane, BorderLayout.CENTER);
        frame.setSize(400, 150);
        frame.setVisible(true);
        selectionModel.setActivated(true);
    }

    private static class MySingleSelectionModel extends DefaultSingleSelectionModel {
        private Component gui;
        private boolean activated = false;

        public MySingleSelectionModel(Component gui) {
            this.gui = gui;
        }

        public void setActivated(boolean activated) {
            this.activated = activated;
        }

        @Override
        public void setSelectedIndex(int index) {
            if (activated) {
                String text = String.format("Before change, old index: %d; new index: %d", 
                        super.getSelectedIndex(), index);
                JOptionPane.showMessageDialog(gui, text);
            }
            super.setSelectedIndex(index);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我使用布尔字段activated来激活行为更改,以便它不会在创建 GUI 时触发。我显示 GUI调用setActivated(true)模型。


关于您的编辑:

目的是在tab改变的时候将几个JTextField的文本保存到一个外部文件中,这样每次用户点击不同的tab时,当前tab的值都会写入到外部文件中。

我应该知道,毕竟这是一个XY 问题,当最好的解决方案是使用完全不同的方法时,您会问如何解决特定的代码问题。以后,请向我们提供原始问题的所有相关信息,以便我们避免在不必要的解决方案上浪费时间。

实际上在选项卡更改之前无需执行任何操作因为在选项卡更改获取数据完全没问题。您的解决方案是使用 ChangeListener,并且无需经过我上面发布的内容的体操。