【问题标题】:How to wire one pane to another如何将一个窗格连接到另一个窗格
【发布时间】:2012-05-09 20:07:43
【问题描述】:

如何将输出连接到paneWithList

PaneWithList 在其JList 上有一个侦听器,以便将所选行输出到控制台。如何将该输出定向到输出时的JTextPane

PaneWithList 可以触发Main 接收的事件吗? PropertyChangeSupport 就够了吗?

Main.java:

package dur.bounceme.net;

import javax.swing.JTabbedPane;

public class Main {

    private static JTabbedPane tabs;
    private static PaneWithList paneWithList;
    private static PaneWithTable paneWithTable;
    private static Output output;

    public static void main(String[] args) {
        tabs = new javax.swing.JTabbedPane();
        paneWithList = new PaneWithList();
        paneWithTable = new PaneWithTable();
        tabs.addTab("list", paneWithList);
        tabs.addTab("table", paneWithTable);
        tabs.addTab("output", output);
    }
}

【问题讨论】:

  • 只需让JTextPane 将自己注册为同一个JList 的侦听器。
  • 添加监听器(这个)?你能扩大一点吗?

标签: java swing oop user-interface netbeans


【解决方案1】:

这是一个使用observer pattern 的示例,也可以看到hereherehere。请注意,也可以收听组合的模型。

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;

/**
* @see http://en.wikipedia.org/wiki/Observer_pattern
* @see https://stackoverflow.com/a/10523401/230513
*/
public class PropertyChangeDemo {

    public PropertyChangeDemo() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(false);
        f.add(new ObserverPanel());
        f.pack();
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                PropertyChangeDemo example = new PropertyChangeDemo();
            }
        });
    }
}

class ObserverPanel extends JPanel {

    private JLabel title = new JLabel("Value received: ");
    private JLabel label = new JLabel("null", JLabel.CENTER);

    public ObserverPanel() {
        this.setBorder(BorderFactory.createTitledBorder("ObserverPanel"));
        JPanel panel = new JPanel(new GridLayout(0, 1));
        panel.add(title);
        panel.add(label);
        this.add(panel);
        ObservedPanel observed = new ObservedPanel();
        observed.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent e) {
                if (e.getPropertyName().equals(ObservedPanel.PHYSICIST)) {
                    String value = e.getNewValue().toString();
                    label.setText(value);
                }
            }
        });
        this.add(observed);
    }
}

class ObservedPanel extends JPanel {

    public static final String PHYSICIST = "Physicist";
    private static final String[] items = new String[]{
        "Alpher", "Bethe", "Gamow", "Dirac", "Einstein"
    };
    private JComboBox combo = new JComboBox(items);
    private String oldValue;

    public ObservedPanel() {
        this.setBorder(BorderFactory.createTitledBorder("ObservedPanel"));
        combo.addActionListener(new ComboBoxListener());
        this.add(combo);
    }

    private class ComboBoxListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent ae) {
            String newValue = (String) combo.getSelectedItem();
            firePropertyChange(PHYSICIST, oldValue, newValue);
            oldValue = newValue;
        }
    }
}

【讨论】:

  • 我更好地理解了 firePropertyChange 的传播方式,谢谢。不太清楚你是如何传递实际值的,需要再次阅读,但这对我来说是缺失的部分。
  • 这是一个相关的example,它使用了无模式对话框。
  • 哇!华丽的!我想知道观察者模式是否需要在 观察者面板 中创建一个 观察者面板 的实例
  • @JG.:我会说不; PropertyChangeEvent 只是在 Swing 中影响 observer pattern 的一种方式;更多here.
【解决方案2】:

我会使用JMenu with JMenuItems,内容使用CardLayout而不是非常复杂的JTabbedPane(s)

【讨论】:

  • +1 不错的选择,通常使用Action 连接。
  • Action 似乎不适用于所有 Swing 控件...?
【解决方案3】:

作为我自己的参考,对于任何使用 Netbeans GUI 构建器的人来说,它的工作原理如下:

PanelWithList 类:

package dur.bounceme.net;

public class PanelWithList extends javax.swing.JPanel {

    public PanelWithList() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();

        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jList1MouseClicked(evt);
            }
        });
        jList1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jList1KeyReleased(evt);
            }
        });
        jScrollPane1.setViewportView(jList1);

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane2.setViewportView(jTextArea1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(54, 54, 54)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 247, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 308, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(167, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(35, 35, 35)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane2)
                    .addComponent(jScrollPane1))
                .addContainerGap(166, Short.MAX_VALUE))
        );
    }// </editor-fold>                        

    private void jList1MouseClicked(java.awt.event.MouseEvent evt) {                                    
        row();
    }                                   

    private void jList1KeyReleased(java.awt.event.KeyEvent evt) {                                   
        row();
    }                                  
    // Variables declaration - do not modify                     
    private javax.swing.JList jList1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextArea jTextArea1;
    // End of variables declaration                   

    private void row() {
        Object o = jList1.getSelectedValue();
        String s = (String)o;
        jTextArea1.setText(s);
        this.firePropertyChange("list", -1, 1);
    }
}

和 Frame.java 作为驱动程序:

package dur.bounceme.net;

public class Frame extends javax.swing.JFrame {

    public Frame() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        panelWithList1 = new dur.bounceme.net.PanelWithList();
        panelWithTable1 = new dur.bounceme.net.PanelWithTable();
        newJPanel1 = new dur.bounceme.net.PanelWithCombo();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        panelWithList1.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                panelWithList1PropertyChange(evt);
            }
        });
        jTabbedPane1.addTab("tab1", panelWithList1);
        jTabbedPane1.addTab("tab2", panelWithTable1);
        jTabbedPane1.addTab("tab3", newJPanel1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 937, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 913, Short.MAX_VALUE)
                    .addContainerGap()))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 555, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 521, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(22, Short.MAX_VALUE)))
        );

        pack();
    }// </editor-fold>

    private void panelWithList1PropertyChange(java.beans.PropertyChangeEvent evt) {
        System.out.println("panelWithList1PropertyChange ");

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Frame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JTabbedPane jTabbedPane1;
    private dur.bounceme.net.PanelWithCombo newJPanel1;
    private dur.bounceme.net.PanelWithList panelWithList1;
    private dur.bounceme.net.PanelWithTable panelWithTable1;
    // End of variables declaration
}

关键是panelWithList1PropertyChange 是“panelWithList”本身的监听器。

因为PanelWithList.firePropertyChange("list", -1, 1); 无法发送我看到的 Object 或 String,我不确定如何获取从 JList 一直到 JFrame 的 value

嗯,API 说是的,它可以发送对象。必须检查一下。

我认为有必要获取一些关于 JList 使用的模型的信息,直到 JFrame。但是,这不会破坏 MVC 吗?或者这可能是错误的方法。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多