我正在使用一个自制的工具栏来浏览我的应用程序,该工具栏出现在所有页面上。每次显示新页面时,我都会使用以下代码关闭当前帧并打开新帧:
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
我这样做是因为ActionListeners是在工具栏类中声明的,而每个页面的框架是在运行时声明的,并且不是静态的。
这一切都很好,除了一个特殊的情况——"取消"按钮,第一次访问帧时它会关闭一次。第二次它将关闭并重新打开2次,第三次3次,依此类推。我已经使用代码中的"计数器"跟踪了这一点。
我已经最小化了代码以重新创建相同的行为,如下所示:
工具栏类
public class Toolbar {
static JButton buttonCancel = new JButton("Cancel");
static int counter;
public static JPanel Toolbar(String panelname){
FlowLayout layout = new FlowLayout();
JPanel Toolbar = new JPanel(new BorderLayout());
Toolbar.setLayout(layout);
GridLayout GLayout = new GridLayout(2,1);
GLayout.setVgap(0);
JPanel container2 = new JPanel();
if(panelname.matches("Customers")){
container2.setLayout(GLayout);
JButton buttonAddCust = new JButton("Add Cust");
container2.add(buttonAddCust, BorderLayout.PAGE_START);
buttonAddCust.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
Customers.AddCustomersGui();
}
});
}
JPanel container21 = new JPanel();
if(panelname.matches("Add Customers")){
container21.setLayout(GLayout);
container21.add(buttonCancel, BorderLayout.PAGE_START);
buttonCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter ++;
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
System.out.println("Coutner " + counter);
Customers.CustomersGui();
}
});
}
Toolbar.add(container2);
Toolbar.add(container21);
return Toolbar;
}
}
GUI类
public class Customers extends Toolbar{
public static void CustomersGui(){
final JFrame frame = new JFrame("Customers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel customers = new JPanel();
customers.add(Toolbar.Toolbar(frame.getTitle()));
frame.setContentPane(customers);
frame.setSize(1200,500);
frame.setVisible(true);
}
public static void AddCustomersGui(){
final JFrame frame1 = new JFrame("Add Customers");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel Addcustomers = new JPanel();
Addcustomers.add(Toolbar.Toolbar(frame1.getTitle()));
frame1.setContentPane(Addcustomers);
frame1.setSize(1200,500);
frame1.setVisible(true);
}
}
主类
public static void main(String[] args) {
Customers.CustomersGui();
}
您将在代码的每次迭代中向按钮Cancel添加一个新的ActionListener,这就是程序行为的原因。
此外,根据我的评论,你说,
每次显示新页面时,我都会关闭当前框架并打开一个新框架。
更好的设计可能不是交换可能令人讨厌的窗口,而是使用CardLayout交换JPanel视图。请阅读《多个JFrame的使用,良好/不良实践?》?。
例如,将这行代码添加到您的程序中:
if (panelname.matches("Add Customers")) {
container21.setLayout(GLayout);
container21.add(buttonCancel, BorderLayout.PAGE_START);
buttonCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter++;
java.awt.Window win[] = java.awt.Window.getWindows();
for (int i = 0; i < win.length; i++) {
win[i].dispose();
}
System.out.println("Coutner " + counter);
Customers.CustomersGui();
}
});
// ***** add this here **********
System.out.println("buttonCancel ActionListener count: "
+ buttonCancel.getListeners(ActionListener.class).length);
}
您将看到ActionListeners被多次添加到此按钮。
交换视图的示例:
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class SwapPanels extends JPanel {
public static final String CUSTOMER = "customer";
public static final String ADD_CUSTOMER = "Add Customer";
protected static final int PREF_W = 800;
protected static final int PREF_H = 600;
public static final String CANCEL = "Cancel";
private CardLayout cardLayout = new CardLayout();
public SwapPanels() {
setLayout(cardLayout);
add(createCustomerPanel(CUSTOMER), CUSTOMER);
add(createAddCustomerPanel(ADD_CUSTOMER), ADD_CUSTOMER);
}
public void showCard(String key) {
cardLayout.show(this, key);
}
public JPanel createAddCustomerPanel(String name) {
JPanel addCustPanel = new JPanel() {
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
};
addCustPanel.setName(name);
addCustPanel.setBorder(BorderFactory.createTitledBorder(name));
addCustPanel.add(new JButton(new AbstractAction(CANCEL) {
{
int mnemonic = (int)getValue(NAME).toString().charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
if (CANCEL.equals(e.getActionCommand())) {
SwapPanels.this.showCard(CUSTOMER);
}
}
}));
return addCustPanel;
}
private JPanel createCustomerPanel(String name) {
JPanel custPanel = new JPanel() {
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
};
custPanel.setName(name);
custPanel.setBorder(BorderFactory.createTitledBorder(name));
custPanel.add(new JButton(new AbstractAction(ADD_CUSTOMER) {
{
int mnemonic = (int)getValue(NAME).toString().charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
if (ADD_CUSTOMER.equals(e.getActionCommand())) {
SwapPanels.this.showCard(ADD_CUSTOMER);
}
}
}));
return custPanel;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SwapPanels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SwapPanels());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}