问题描述
我试图这样做:在我的GUI中,我有一个JTable与一个自定义模型,在GUI的其他部分,我有一个面板,我画一些箭头。我想同步这两个视图,所以让我们说如果我的JTable中有5行,我将在箭头面板中画出5个箭头,如果我对行数进行修改,我必须有相同数量的行所以我试图使用Design Pattern Observer。
为了简单起见,我尝试提供一个可在一个文件中计算的示例:
我在第一个Panel(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>观察员;
private int numberSync;
public SynchronizeNumber(){
super();
观察者= new ArrayList< Observer>();
}
public SynchronizeNumber(int numberSync){
super();
this.numberSync = numberSync;
观察者= 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.numberSync);
}
}
/ **
* @返回数字
* /
public int getNumberSync(){
返回numberSync;
}
/ **
* @param number
*要设置的数字
* /
public void setNumberSync(int numberSync) {
this.numberSync = numberSync;
notifyObservers();
}
}
class ButtonPanel扩展JPanel实现Observer {
private int numberButton;
public ButtonPanel(){
super();
}
public ButtonPanel(int numberButton){
this.numberButton = numberButton; (int i = 1; i< = numberButton; i ++)
this.add(new JButton(+ i));
}
/ **
* @返回numberLabel
* /
public int getNumberButton(){
return numberButton;
}
/ **
* @param numberLabel
* numberLabel设置
* /
public void setNumberButton(int numberButton) {
this.numberButton = numberButton;
}
@Override
public void update(Subject subject,int number){
if(subject instanceof SynchronizeNumber){
SynchronizeNumber synchronizeNumber =(SynchronizeNumber ) 学科;
numberButton = synchronizeNumber.getNumberSync();
System.out.println(ButtonPanel,numberButton:+ numberButton);
}
}
}
class LabelPanel扩展JPanel实现Observer {
private int numberLabel;
public LabelPanel(){
super();
}
public LabelPanel(int numberLabel){
super();
this.numberLabel = numberLabel; (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 ) 学科;
numberLabel = synchronizeNumber.getNumberSync();
System.out.println(LabelPanel,numberLabel:+ numberLabel);
}
}
/ **
* @返回numberLabel
* /
public int getNumberLabel(){
return numberLabel;
}
/ **
* @param numberLabel
* numberLabel设置
* /
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));
//创建主题synchronizeNumber
SynchronizeNumber synchronizeNumber = new SynchronizeNumber();
//将数字设置为1
synchronizeNumber.setNumberSync(1);
//创建观察器buttonPanel和labelPanel
ButtonPanel buttonPanel = new ButtonPanel(synchronizeNumber.getNumberSync());
LabelPanel labelPanel = new LabelPanel(synchronizeNumber.getNumberSync());
//添加buttonPanel和labelPanel作为观察者
synchronizeNumber.addObserver(buttonPanel);
synchronizeNumber.addObserver(labelPanel);
//手动修改
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观察者而不是API,因为多个扩展是不可能的
Swing是一个事件驱动的API,几乎像Observer在有事件和听众订阅的意义上,模式听这些事件。例如组件调度,每次按下并通知订阅发生了什么事。 / p>
同样的原则,是来分派每次数据被更改(行添加/删除,单元格更新等)并通知订阅在
您可以使用此事实来实现您的主要目标:
- 创建一个
JPanel
,可以根据需要绘制许多箭头。请参阅课程。 - 将
TableModelListener
附加到您的TableModel
中,以便重新绘制您的JPanel
当行被插入/删除时。
如果您应该遵循我的建议,您应该可以创建一个独立且可重复使用的 JPanel
,如下所示:
class MyCustomPanel extends JPanel {
private int numberOfArrows = 0;
@Override
public void paintComponent(Graphics g){
super.paintComponent(g); //永远不会忘记调用super.paintComponent(g)
图形图形= g.create();
int y = 10; (int i = 0; i< numberOfArrows; i ++){
graphics.drawLine(10,y,getWidth() - 10,y);
//而不是线绘制你的箭头
y + = 10;
}
graphics.dispose();
}
/ **
*设置必须绘制的箭头数量的公共方法。
* @param箭头
* /
public void setNumberOfArrows(int arrow){
numberOfArrows =箭头;
repaint();
}
@Override
public Dimension getPreferredSize(){
return isPreferredSizeSet()
? super.getPreferredSize():new Dimension(200,200);
}
}
这样你的面板可以从箭头的数量外部独立于如何确定(它可以是表模型中的行数,列表中的元素数量,固定值,无论您想要什么)。
I'm trying to do this: In my GUI, I have one JTable with a custom model, and in other part of the GUI, I have one panel where i draw some arrows. I want to "synchronize this two view. So let's say if we have 5 rows in my JTable, I will draw 5 arrows in the panel of arrows. If I make a modification in the number of row, I must have the same number of row.So I'm trying to use Design Pattern Observer.
To make simple, I try to provide an example computable in one file:I create n buttons in my first Panel (ButtonPanel) and I create n label in the second panel (LabelButton).
The problem is : How to synchronize the number of label withthe number of label with 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);
}
}
edit: I use my own DP Observer and not from the API because multiple extending is not possible
Swing is an Event Driven API and acts pretty much like an Observer Pattern in the sense that there are events and listeners subscribed to listen those events. For instance JButton component dispatches an ActionEvent every time it is pressed and notifies to subscribed ActionListeners that something happened.
With the same principle, is responsibility of TableModel to dispatch a TableModelEvent every time data has been changed (rows added/deleted, cells updated, etc) and notify subscribed TableModelListeners in such events.
You can use this fact to accomplish your main goal:
- Create a
JPanel
with the ability to draw many arrows as you wish. See Performing Custom Painting lesson. - Attach a
TableModelListener
to yourTableModel
in order to repaint yourJPanel
when rows are inserted/deleted.
If you follow my suggestions, you should be able to create an independent and reusable JPanel
like this:
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);
}
}
This way your panel can take the number of arrows from the outside independently on how it is determined (it could be number of rows in a table model, number of elements in a list, a fixed value, whatever you want).
这篇关于如何在Java Swing中同步两个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!