当前位置: 首页 > 知识库问答 >
问题:

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

宗政天逸
2023-03-14

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

我一直在使用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);
    }
}

共有1个答案

吕霖
2023-03-14

一种可能的方法(我不是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);
    }

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

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);
        }
    }
}

请注意,我使用了一个布尔字段activated来激活行为更改,这样它就不会在创建GUI时激发。在显示GUI之后,我在模型上调用setactivated(true)

关于您的编辑:

其目的是在选项卡更改时将几个JTextFields的文本保存到外部文件中,因此每次用户单击不同的选项卡时,当前选项卡的值都会写入外部文件

我应该知道,这毕竟是一个XY问题,在这里你问如何解决一个特定的代码问题,而最好的解决方案是使用一种完全不同的方法。在将来,请给我们所有与原问题相关的信息,这样我们就可以避免不必要的解决方法浪费时间。

 类似资料:
  • 使用JavaFX2.2,我有一个窗口,它主要由一个有4个选项卡的TabPane组成。用户可以更改任何选项卡中显示的数据,如果他们这样做了,我希望确保他们在保存/取消/更新数据之前不会更改该选项卡。特别是,我想确保他们不会选择不同的标签。如果他们试图退出或执行某个菜单项,我可以捕捉到,但我似乎找不到中断选项卡更改的方法。我可以捕捉到他们点击了一个新的选项卡(onSelectionChanged),并

  • 在选择我的treeview时遇到问题。其思想是,用户单击该项,然后将数据添加到他们选择的节点下 似乎所选项目是一个文本块,我似乎找不到一种方法将其作为treeview项目来添加节点。 是的,我对这种编程很陌生。 感谢您提供的任何帮助。

  • 我正在一个名为Dashboard的类中创建一个标签疼痛,它在标签中包含“填充”面板。我想知道是否有办法创建一个新的仪表板并更改我存储在选项卡中的面板。我不确定这是否是正确的解释方法,但这里有一些代码。 我现在想创建一个新类来创建和实例仪表板,但更改选项卡中显示的面板。我尝试了这样的操作: 我不确定这是否可能,或者是否有另一种方法可以做到这一点。

  • 主要内容:ion-tabs,实例,ion-tab,$ionicTabsDelegateion-tabs ion-tabs 是有一组页面选项卡组成的选项卡栏。可以通过点击选项来切换页面。 对于 iOS,它会出现在屏幕的底部,Android会出现在屏幕的顶部(导航栏下面)。 用法 实例 <ion-tabs class="tabs-positive tabs-icon-only"> <ion-tab title="首页" icon-on="ion-ios-filing" icon-off

  • ion-tabs ion-tabs 是有一组页面选项卡组成的选项卡栏。可以通过点击选项来切换页面。 对于 iOS,它会出现在屏幕的底部,Android会出现在屏幕的顶部(导航栏下面)。 用法<ion-tabs class="tabs-positive tabs-icon-only"> <ion-tab title="首页" icon-on="ion-ios-filing" icon-off="io

  • 问题内容: 这类似于问题如何在Java Swing中构建Google- chrome标签和菜单栏界面?(我想实现相同的目的),但更重要的是:如何在JTabbedPane中的选项卡的前面和后面放置组件? 我已经自己想到了按钮的想法,但是我宁愿有一个JTabbedPane,因为它确实是它的意思,但是在侧面装饰有按钮或图标。 我已经看到,基里尔(Kirill)的laf-widget项目对多个LaF都执行