如何在 Java Swing 中同步两个视图

2024-01-30

我正在尝试这样做:在我的 GUI 中,我有一个带有自定义模型的 JTable,在 GUI 的其他部分,我有一个面板,可以在其中绘制一些箭头。我想“同步这两个视图。假设我的 JTable 中有 5 行,我将在箭头面板中绘制 5 个箭头。如果我修改行数,则必须具有相同的行数排。 所以我尝试使用设计模式观察者。

为了简单起见,我尝试在一个文件中提供一个可计算的示例: 我在第一个面板 (ButtonPanel) 中创建 n 个按钮,并在第二个面板 (LabelButton) 中创建 n 个标签。

问题是:如何将标签数量与DP Observer的标签数量同步

import java.awt.Color;
import java.awt.GridLayout;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

interface Observer {
    public void update(Subject subject, int number);
}

interface Subject {
    public void addObserver(Observer observer);

    public void delObserver(Observer observer);

    public void notifyObservers();
}

class SynchronizeNumber implements Subject {
    private ArrayList<Observer> observers;

    private int numberSync;

    public SynchronizeNumber() {
        super();
        observers = new ArrayList<Observer>();

    }

    public SynchronizeNumber(int numberSync) {
        super();
        this.numberSync = numberSync;
        observers = new ArrayList<Observer>();

    }

    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);

    }

    @Override
    public void delObserver(Observer observer) {
        observers.remove(observer);

    }

    @Override
    public void notifyObservers() {
        for (Observer o : observers) {
            o.update(this, this.numberSync);
        }
    }

    /**
     * @return the number
     */
    public int getNumberSync() {
        return numberSync;
    }

    /**
     * @param number
     *            the number to set
     */
    public void setNumberSync(int numberSync) {
        this.numberSync = numberSync;
        notifyObservers();
    }
}

class ButtonPanel extends JPanel implements Observer {

    private int numberButton;

    public ButtonPanel() {
        super();
    }

    public ButtonPanel(int numberButton) {
        this.numberButton = numberButton;
        for (int i = 1; i <= numberButton; i++)
            this.add(new JButton("" + i));
    }

    /**
     * @return the numberLabel
     */
    public int getNumberButton() {
        return numberButton;
    }

    /**
     * @param numberLabel
     *            the numberLabel to set
     */
    public void setNumberButton(int numberButton) {
        this.numberButton = numberButton;
    }

    @Override
    public void update(Subject subject, int number) {
        if (subject instanceof SynchronizeNumber) {
            SynchronizeNumber synchronizeNumber = (SynchronizeNumber) subject;
            numberButton = synchronizeNumber.getNumberSync();
            System.out.println("ButtonPanel, numberButton: " + numberButton);
        }
    }
}

class LabelPanel extends JPanel implements Observer {

    private int numberLabel;

    public LabelPanel() {
        super();
    }

    public LabelPanel(int numberLabel) {
        super();
        this.numberLabel = numberLabel;
        for (int i = 1; i <= numberLabel; i++)
            this.add(new JLabel("label numbe: " + i));
        this.setBorder(new LineBorder(Color.blue));
    }

    @Override
    public void update(Subject subject, int number) {
        if (subject instanceof SynchronizeNumber) {
            SynchronizeNumber synchronizeNumber = (SynchronizeNumber) subject;
            numberLabel = synchronizeNumber.getNumberSync();
            System.out.println("LabelPanel, numberLabel: " + numberLabel);
        }
    }

    /**
     * @return the numberLabel
     */
    public int getNumberLabel() {
        return numberLabel;
    }

    /**
     * @param numberLabel
     *            the numberLabel to set
     */
    public void setNumberLabel(int numberLabel) {
        this.numberLabel = numberLabel;
    }
}

public class Test {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setLayout(new GridLayout(2, 1));

        // create an subject synchronizeNumber
        SynchronizeNumber synchronizeNumber = new SynchronizeNumber();

        // set number to 1
        synchronizeNumber.setNumberSync(1);

        //create observers buttonPanel and labelPanel 
        ButtonPanel buttonPanel = new ButtonPanel(synchronizeNumber.getNumberSync());
        LabelPanel labelPanel = new LabelPanel(synchronizeNumber.getNumberSync());

        // add buttonPanel and labelPanel as observers
        synchronizeNumber.addObserver(buttonPanel);
        synchronizeNumber.addObserver(labelPanel);

        // make a change manually
        synchronizeNumber.setNumberSync(4);
        f.add(buttonPanel);
        f.add(labelPanel);
        f.setSize(400, 400);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

}

编辑:我使用我自己的 DP Observer,而不是来自 API,因为多重扩展是不可能的


我使用观察者模式,因为我认为这是最好的解决方案。

Swing 是一个事件驱动的 API,其行为非常类似于观察者模式,因为有事件和订阅侦听这些事件的侦听器。例如JButton http://docs.oracle.com/javase/7/docs/api/javax/swing/JButton.html组件调度一个动作事件 http://docs.oracle.com/javase/7/docs/api/java/awt/event/ActionEvent.html每次按下并通知订阅动作监听器 http://docs.oracle.com/javase/7/docs/api/java/awt/event/ActionListener.html是发生了什么事。

同样的原则,责任是表模型 http://docs.oracle.com/javase/7/docs/api/javax/swing/table/TableModel.html派遣一个表模型事件 http://docs.oracle.com/javase/7/docs/api/javax/swing/event/TableModelEvent.html每次数据更改(添加/删除行、更新单元格等)并通知订阅者表模型监听器 http://docs.oracle.com/javase/7/docs/api/javax/swing/event/TableModelListener.html发生此类事件。

您可以利用这一事实来实现您的主要目标:

假设我的 JTable 有 5 行,我将在其中绘制 5 个箭头 箭头面板。

  1. 创建一个JPanel能够根据需要绘制许多箭头。看进行定制绘画 http://docs.oracle.com/javase/tutorial/uiswing/painting/ lesson.
  2. 附上一个TableModelListener给你的TableModel为了重新粉刷你的JPanel当插入/删除行时。

我有两个类,我希望两个类之间有最小的依赖关系 类。

如果您遵循我的建议,您应该能够创建一个独立且可重用的JPanel像这样:

class MyCustomPanel extends JPanel {

    private int numberOfArrows = 0;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // never forget to call super.paintComponent(g)
        Graphics graphics = g.create();
        int y = 10;
        for(int i = 0; i < numberOfArrows; i++) {                
            graphics.drawLine(10, y, getWidth() - 10, y); // instead of lines just draw your arrows
            y += 10;
        }
        graphics.dispose();
    }

    /**
     * Public method to set the number of arrows that has to be drawn.
     * @param arrows 
     */
    public void setNumberOfArrows(int arrows) {
        numberOfArrows = arrows;
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return isPreferredSizeSet() 
             ? super.getPreferredSize() : new Dimension(200,200);
    }
}

这样,您的面板可以独立地从外部获取箭头数量,而不管它是如何确定的(可以是表模型中的行数、列表中的元素数、固定值,无论您想要什么)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Java Swing 中同步两个视图 的相关文章

随机推荐

  • JBoss 4.2.2 Web服务soap:地址

    我在 JBoss 4 2 2 中部署了一个 EJB3 bean 作为 Web 服务 在生产中 服务器位于 Apache 服务器后面 该服务器将请求重定向到 Jboss 服务器 这使得 WSDL 具有错误的soap address 位置 我能
  • 将按钮添加到 PreferenceScreen

    我不知道如何在PreferenceScreen 向上按钮会在应用程序图标旁边的操作栏中显示插入符号 使您可以导航应用程序的层次结构 更多信息here http developer android com training implement
  • 查找 CSV 文件中的重复项总数

    我正在解析 CSV 文件 需要您的帮助 我的 CSV 文件中有重复项 我想告诉Python向我提供重复地址的总数和唯一地址的总数 然后列出它们 我已经成功到达地址显示它是唯一还是重复的部分 但现在我想告诉 Python 也为我提供受尊重的数
  • 查看和设置 Safari/Chrome 的 HTTP 标头

    我正在测试一个 API 我想用 safari 来访问它并查看返回的原始 json API 要求每个请求都发送特定的 HTTP 标头 Safari 或 Chrome 中有没有办法在访问 URL 时设置我的 http 标头 有几个 Google
  • 如何在 Pytorch 中可视化网络?

    import torch import torch nn as nn import torch optim as optim import torch utils data as data import torchvision models
  • 历史推送后,反应路由器不会重新渲染

    我希望在用户登录后重新渲染 刷新 所以我使用history push要做到这一点 import history from layout Navbar export const loginUser userData gt dispatch g
  • 如何在 JavaScript 中有效地将预定义大小的大块分割成较小的块,这些块是其大小的因素?

    假设我们有这样的结构 16 bins let BIN OF BINS 128 bits each chunk 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 52428
  • MATLAB 将多个图形保存到 PDF

    有什么办法可以做到这一点吗 我知道如何使用 saveas saveas 1 filename pdf 将一个图形保存到 PDF 文件中 但是否可以添加多个图形 所以像 saveas 1 2 3 filename pdf Thanks 我不这
  • 每 3 条记录后新建包含 div

    我想创建一个新的包含 div 3 个结果后 使用 PDO 结果循环 对于我的自学项目 我必须使用引导程序制作一个产品页面 并且在每第三条记录之后 我必须制作一个新行并再次显示 3 col md 4 等等 现在我将其作为我的代码 div cl
  • 如何获取 char 的 unicode 值?

    我想获得汉字的 Unicode 值 它可能看起来像let values u16 f 当我使用 as bytes I got 227 129 174 当我使用 escape unicode I got u306e the 0x306e这正是我
  • PHP 的 unlink 函数可以与路径一起使用吗?

    我想从 PHP 中的文件夹中删除文件 但我只有该文件的路径 是否可以提供取消链接的路径 例如 unlink path to file txt 如果这不起作用 删除这些文件的唯一方法是在 path to 目录中创建一个 php 文件 并将其以
  • 改变架构生成器中的列长度?

    我有两个字段需要增加字符限制 我通读了文档 令我惊讶的是我没有找到它的选项 可以做吗 如果不是 我应该如何解决这个问题 我可以删除该列并使用正确的属性重新创建它 但我不想丢失数据库中的任何数据 对于 Laravel 4 DB update
  • mysql、准备好的语句和自动类型转换

    我使用常规语句和准备好的语句执行完全相同的查询时得到不同的结果 我认为这是一个类型转换错误 mysql gt show columns from server where field vlan Field Type Null Key Def
  • 在 Android 中缓存文件的最佳实践

    我目前的应用程序将图像文件缓存在cache应用程序的子目录 这些图像用于ListView并存储在HashMap of SoftReferences to Bitmaps 所以我的问题是 缓存这些图像文件的最佳方法是什么 而不增加我的应用程序
  • 协助刷新 athena 表中的数据

    我编写了从 S3 上的多个外部表读取数据的查询 应用必要的过滤器 连接 然后将结果加载到目标表中以在 Athena 中进行分析 但是 随着源表中的数据刷新 我想刷新目标表 所以我打算删除并重新创建该表 但它似乎不起作用 我能够删除目标表 但
  • 为什么 ondrop 不起作用?

    我试图让拖放工作 但我将一个函数连接到 ondrop 事件 但该函数从未被调用 这是一个笨蛋 http plnkr co edit qGEdYO8okRZAR3bnZrNk p preview http plnkr co edit qGEd
  • MPMediaItems 原始歌曲数据

    我想知道如何访问 MPMediaItem 的原始数据 有任何想法吗 您可以通过以下方式获取媒体项的数据 void mediaItemToData Implement in your project the media item picker
  • 其他语言中的 Cobol 88 类型等效项是什么?

    我现在正在学习 COBOL 非常喜欢 88 类型的变量 我想知道其他语言中是否有类似的东西 也是最知名的语言 例如 C Objective C 甚至使用库 我唯一能想到的相似之处就是使用 define booleanResult varia
  • 颠倒方向在 iOS 6 中不适用于导航视图和选项卡栏视图?

    我在 ios 6 中创建了一个带有导航视图的应用程序 此外 我还在应用程序摘要中设置了所有方向选项 甚至使用了 BOOL shouldAutoRotate and NSUInteger supportedInterfaceOrientaio
  • 如何在 Java Swing 中同步两个视图

    我正在尝试这样做 在我的 GUI 中 我有一个带有自定义模型的 JTable 在 GUI 的其他部分 我有一个面板 可以在其中绘制一些箭头 我想 同步这两个视图 假设我的 JTable 中有 5 行 我将在箭头面板中绘制 5 个箭头 如果我