gpt4 book ai didi

java - 如何在 Java Swing 中同步两个 View

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:03:45 25 4
gpt4 key购买 nike

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

为简单起见,我尝试提供一个可在一个文件中计算的示例:我在第一个面板 (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,因为不可能进行多次扩展

最佳答案

I use Observer pattern because I think it is the best solution.

Swing 是一种事件驱动的 API,在存在事件和订阅监听这些事件的监听器的意义上,它的行为非常像观察者模式。例如JButton组件发送 ActionEvent每次按下并通知订阅ActionListener是不是出事了。

同理,责任TableModel dispatch TableModelEvent每次更改数据(添加/删除行、更新单元格等)并通知订阅者TableModelListener在这样的事件中。

您可以使用这个事实来实现您的主要目标:

So let's say if we have 5 rows in my JTable, I will draw 5 arrows in the panel of arrows.

  1. 创建一个JPanel,可以根据需要绘制许多箭头。参见 Performing Custom Painting教训。
  2. TableModelListener 附加到您的 TableModel,以便在插入/删除行时重新绘制您的 JPanel

I have two classes and I want a minimun dependency between the two classes.

如果您遵循我的建议,您应该能够像这样创建一个独立且可重用的 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);
}
}

通过这种方式,您的面板可以根据确定的方式独立地从外部获取箭头数量(它可以是表模型中的行数、列表中的元素数、固定值,任何你想要的)。

关于java - 如何在 Java Swing 中同步两个 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24886172/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com