gpt4 book ai didi

Java Swing API - 两个 JPanel 如何相互通信?

转载 作者:行者123 更新时间:2023-12-02 23:29:50 25 4
gpt4 key购买 nike

这是我与 Java Swing 相关的第二篇文章,如果我的问题太简单了,请原谅我。我正在尝试让多个 JPanel 相互通信。我正在构建一个简单的 2D 网格,可以向其中添加墙壁/阻挡单元,然后运行简单的 Floodfill/A* 搜索算法(给定起始位置和目标位置)。

为了隔离我的问题,我决定使用示例会更容易。因此,我创建了一个简单的应用程序,允许用户写入文本框,假设他/她单击了“开始”按钮。一旦写入文本框完成,用户可以单击“开始”按钮将其翻转到“停止”状态。在“停止”状态下,用户无法向文本框添加任何文本(即应用程序根本不应该注册任何击键)。这是一个简单的问题,却真正提出了我的问题。现在的 UI 如下所示:

enter image description here

enter image description here

我的问题:当按钮显示“停止”(因为处于编辑模式)时,我应该能够书写,并且我当按钮显示“开始”时,不应该能够在文本区域中书写(因为它不是编辑模式)。但是,从上面的图像中,您可以看到我无论如何都可以在文本区域中书写。那么如何使文本区域的编辑依赖按钮状态?

这是我的代码,尝试在按钮面板和文本面板之间建立连接,但不知何故它没有按预期工作。

我查看了 StackOverflow 帖子 herehere ,但坦率地说,我似乎并不清楚答案。

简单文本面板:

public class SimpleTextPanel extends JPanel implements PropertyChangeListener, ChangeListener {


private boolean canWrite;
public SimpleTextPanel() {

// set the border properties
canWrite = true;
TitledBorder title = BorderFactory.createTitledBorder("Simple Text Panel");
title.setTitleColor(Color.BLACK);
title.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,
Color.DARK_GRAY, Color.GRAY));
this.setBorder(title);

JTextArea editSpace = new JTextArea(10, 20);
editSpace.setEditable(true);
editSpace.addPropertyChangeListener(this);
this.add(editSpace);
}

@Override
public void stateChanged(ChangeEvent changeEvent) {
JButton button = (JButton)changeEvent.getSource();
canWrite = button.getText().equals("Start");
}

@Override
public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
JTextArea area = (JTextArea)propertyChangeEvent.getSource();
if(!canWrite) area.setText((String)propertyChangeEvent.getOldValue());
}
}

简单按钮面板:

public class SimpleButtonPanel extends JPanel implements ActionListener {

JButton switchButton;
private boolean canWrite = true;

public SimpleButtonPanel(SimpleTextPanel txt) {

// set the border properties
TitledBorder title = BorderFactory.createTitledBorder("Simple Button Panel");
title.setTitleColor(Color.BLACK);
title.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,
Color.DARK_GRAY, Color.GRAY));
this.setBorder(title);

switchButton = new JButton("Start");
switchButton.addActionListener(this);
switchButton.addChangeListener(txt);
this.add(switchButton);
}

@Override
public void actionPerformed(ActionEvent actionEvent) {
if(switchButton.getText().equals("Start")) {
switchButton.setText("Stop");
canWrite = false;
} else if(switchButton.getText().equals("Stop")) {
switchButton.setText("Start");
canWrite = true;
}
}
}

简单示例测试:

public class SimpleExampleTest extends JFrame {

public SimpleExampleTest() {

setLayout(new BorderLayout());
setTitle("Simple Example");
setSize(300, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);

SimpleTextPanel text = new SimpleTextPanel();
SimpleButtonPanel button = new SimpleButtonPanel(text);

add(text, BorderLayout.NORTH);
add(button, BorderLayout.SOUTH);
//button.addPropertyChangeListener(text); // so that text editor knows whether to allow writing or not
}


public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
SimpleExampleTest ex = new SimpleExampleTest();
ex.setVisible(true);
}
});
}
}

感谢任何/所有帮助。谢谢你!

最佳答案

一种方法是设计一个可以由小组共享的模型。

文本面板只想知道当前状态是什么以及该状态何时发生变化。按钮面板想要知道状态何时发生变化,并且也希望能够改变状态。

这将两个面板彼此解耦,因为它们并不真正关心状态如何更改或由谁更改,只关心它们可以相应地响应更改...

此外,模型并不关心它们中的任何一个,它只是携带状态并在状态更改时提供通知。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;

public class TalkToEachOther {

public static void main(String[] args) {
new TalkToEachOther();
}

public TalkToEachOther() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Simple Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

MutableSimpleModel model = new DefaultSimpleModel();

SimpleTextPanel text = new SimpleTextPanel(model);
SimpleButtonPanel button = new SimpleButtonPanel(model);

frame.add(text, BorderLayout.NORTH);
frame.add(button, BorderLayout.SOUTH);
//button.addPropertyChangeListener(text); // so that text editor knows whether to allow writing or not
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public interface SimpleModel {

public boolean isEditable();

public void addPropertyChangeListener(PropertyChangeListener listener);
public void removePropertyChangeListener(PropertyChangeListener listener);

}

public interface MutableSimpleModel extends SimpleModel {

public void setEditable(boolean editable);

}

public class DefaultSimpleModel implements MutableSimpleModel {

private Set<PropertyChangeListener> listeners;
private boolean editable;

public DefaultSimpleModel() {
listeners = new HashSet<>(25);
}

@Override
public void setEditable(boolean value) {
if (value != editable) {
editable = value;
firePropertyChange("editable", !editable, editable);
}
}

@Override
public boolean isEditable() {
return editable;
}

@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
}

@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.remove(listener);
}

protected void firePropertyChange(String editable, boolean oldValue, boolean newValue) {
PropertyChangeEvent evt = new PropertyChangeEvent(this, editable, oldValue, newValue);
for (PropertyChangeListener listener : listeners) {
listener.propertyChange(evt);
}
}

}

public class SimpleTextPanel extends JPanel {

private SimpleModel model;
private JTextArea editSpace = new JTextArea(10, 20);

public SimpleTextPanel(SimpleModel model) {

this.model = model;
model.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
updateEditableState();
}
});
setLayout(new BorderLayout());

// set the border properties
TitledBorder title = BorderFactory.createTitledBorder("Simple Text Panel");
title.setTitleColor(Color.BLACK);
title.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,
Color.DARK_GRAY, Color.GRAY));
this.setBorder(title);

editSpace = new JTextArea(10, 20);
this.add(new JScrollPane(editSpace));

updateEditableState();
}

protected void updateEditableState() {
editSpace.setEditable(model.isEditable());
}
}

public class SimpleButtonPanel extends JPanel implements ActionListener {

private MutableSimpleModel model;
private boolean canWrite = true;

private JButton switchButton;

public SimpleButtonPanel(MutableSimpleModel model) {

this.model = model;
model.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
updateEditableState();
}
});

// set the border properties
TitledBorder title = BorderFactory.createTitledBorder("Simple Button Panel");
title.setTitleColor(Color.BLACK);
title.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED,
Color.DARK_GRAY, Color.GRAY));
this.setBorder(title);

switchButton = new JButton("Start");
switchButton.addActionListener(this);
this.add(switchButton);

updateEditableState();
}


@Override
public void actionPerformed(ActionEvent actionEvent) {
model.setEditable(!model.isEditable());
}

protected void updateEditableState() {
if (model.isEditable()) {
switchButton.setText("Stop");
} else {
switchButton.setText("Start");
}
}
}
}

关于Java Swing API - 两个 JPanel 如何相互通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25600122/

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