【问题标题】:Using JTabbedPane with JPanels that need to share data将 JTabbedPane 与需要共享数据的 JPanel 一起使用
【发布时间】:2016-09-27 13:39:03
【问题描述】:

在我的应用程序中,我将几个自定义 JPanel 添加到 JTabbedPane。单个 JPanel 提供了一个功能,我已将它们添加到 JTabbedPane 中,以便用户可以轻松地在模块之间切换。

所有这些自定义 JPanel 都对同一组数据进行操作,这意味着如果其中一个模块必须更改数据中的某些内容(例如,列表),则所有其他面板都应该知道该更改并做出相应的反应。

但是,使用 JTabbedPane,您首先需要实例化这些 JPanel 以将它们添加到 JTabbedPane - 您只需执行一次。

我有一个问题 - 假设用户向面板 A 中的集合添加了一些内容(由所有面板共享)并切换到面板 B。在这种情况下会发生什么? B 应该如何知道该集合中已添加了某些内容?

我的想法是简单地检测一个选项卡切换事件,并调用 B 的方法来考虑新数据。但我觉得这不是应该的。

你有什么建议?

【问题讨论】:

  • “在我的应用程序中,我有几个自定义的 JPanel..” 为什么它们是“自定义”的?你的意思是 extends JPanel
  • “同一组数据” 这表明为(假定相关的)数据保留一个模型,该模型在各个面板中表示。
  • @AndrewThompson 是的,我的意思是他们扩展了 JPanel。有模型是一回事,在这种情况下如何正确使用它是个问题。例如,我的 JPanel 可能看起来完全不同(不同的按钮等),具体取决于当前数据。
  • @AndrewThompson 我们来谈谈一个简单的 JComboBox。我通过将 DefaultComboBoxModel 传递给它 + 自定义渲染器来初始化它。 DefaultComboBoxModel 包含来自我的“模型”的集合。如果集合被修改了怎么办?我需要手动更新组合框模型,对吗?
  • “我的意思是他们扩展了 JPanel。” 为什么?

标签: java swing jtabbedpane


【解决方案1】:

在下面的示例中,选项卡式窗格中的每个面板都有其自己的JComboBox,用于侦听常见的ComboBoxModel。当通用模型更新时,通过点击Update,每一个监听JComboBox都会看到变化。

我从不需要任何两个组合框来共享一个模型。我的面板包含完全不同的 JComponent 实例,但这些组件显示的外观和数据取决于所有这些面板共有的几个集合。

您可以利用observer pattern,检查here。具体细节取决于您的用例,但 PropertyChangeListener 示例值得研究。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.Date;
import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

/**
 * @see https://stackoverflow.com/a/37514928/230513
 * @see https://stackoverflow.com/questions/8752037
 * @see https://stackoverflow.com/a/37222598/230513
 */
public class TabTest {

    private static final int N = 5;
    private final JTabbedPane pane = new JTabbedPane();
    private final DefaultComboBoxModel model = new DefaultComboBoxModel(
        new String[]{"Alpher", "Bethe", "Gamow", "Dirac", "Einstein"});

    public TabTest() {
        for (int i = 0; i < N; i++) {
            Color color = Color.getHSBColor((float) i / N, 1, 1);
            pane.add("Tab " + String.valueOf(i), new TabContent(i, color));
        }
    }

    private class TabContent extends JPanel {

        private TabContent(int i, Color color) {
            setOpaque(true);
            setBackground(color);
            add(new JComboBox(model));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(320, 240);
        }
    }

    private void display() {
        JFrame f = new JFrame("TabColors");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(pane);
        JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        p.add(new JButton(new AbstractAction("Update") {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.addElement(new Date());
            }
        }));
        f.add(p, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TabTest().display();
            }
        });
    }
}

【讨论】:

  • 问题是我永远不需要任何两个组合框来共享模型。我的面板包含完全不同的 JComponent,但这些组件显示的外观和数据取决于所有这些面板共有的几个集合。一旦一个面板修改了任何这些集合中的某些内容,其他面板应该意识到这种变化并应该修改它们的外观或它们显示的数据。
  • @user4205580:您可能不需要与此处找到的完全相同的设置,但您确实需要相同的概念——两个视图可以并且应该共享相同的模型。使用此概念并将其应用于您的设置和代码,您将解决您的问题。也请对此答案投赞成票。
  • 我已经在上面详细说明了;尤其是@Hovercraft Full Of Eels' example;如需更多指导,请编辑您的问题以包含minimal reproducible example,可能是基于上述示例的,显示您当前的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 2017-04-25
  • 2023-03-21
相关资源
最近更新 更多