在JavaSwing中处理来自复合组件的事件

col17t5w  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(380)

我制作了一个桌面应用程序来处理一些web服务的配置,它可以工作,但是代码很难维护,因为所有de-logic视图都在同一个类(主类)中,所以我决定重做它,并应用mvc架构和react哲学将复杂的应用程序拆分为简单的、可重用的组件。我最终得到的结果是:

我的应用程序有 JFrame 有一个主要的 JPanel ,此主 JPanel 有很多其他的 JPanel 但是主电源是 centerJPanel 以及 SaveJPanel 用于演示目的。centerjpanel有我的复合组件(蓝色矩形)contenedorswtbtn。
我的对手包括 JPanel , JLabel 对于标题和switchtogglebtn组件,我可以有任意多个switchtogglebtn,因为我的想法是动态添加它们。

我的switchtogglebtn由一个 JPanel , JLabel 名字,还有 JToggleButton .

mycomponent:switchtogglebtn的代码(很抱歉是西班牙语):

public class SwitchToggleBtn extends JPanel 
    {

    private  JToggleButton SwtBtn;
    private JLabel nombLogs; 
    private String Name;
    public SwitchToggleBtn(String Nombre, boolean bandera) 
    {
        super(new BorderLayout(10,10));
        this.Name = Nombre;
        this.setBackground(new java.awt.Color(255, 255, 255));
        this.setBorder( new EmptyBorder( 5, 5, 5, 12));
        this.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(153, 153, 153)));

        this.nombLogs = new JLabel(Nombre);
        this.nombLogs.setFont(new java.awt.Font("Segoe UI Symbol", 0, 14));
        this.add(nombLogs, BorderLayout.WEST);
        this.SwtBtn = new JToggleButton();        
        this.SwtBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/principal/icon/btnToggleOff.png"))); // NOI18N
        this.SwtBtn.setBorder(null);
        this.SwtBtn.setBorderPainted(false);
        this.SwtBtn.setContentAreaFilled(false);
        this.SwtBtn.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        this.SwtBtn.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/principal/icon/btnToggleOffDisabled.png"))); // NOI18N
        this.SwtBtn.setDisabledSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/principal/icon/btnToggleOnDisable.png"))); // NOI18N
        this.SwtBtn.setFocusPainted(false);
        this.SwtBtn.setMaximumSize(new java.awt.Dimension(70, 34));
        this.SwtBtn.setMinimumSize(new java.awt.Dimension(70, 34));
        this.SwtBtn.setPreferredSize(new java.awt.Dimension(70, 34));
        this.SwtBtn.setSelected(bandera);
        this.SwtBtn.setName(Nombre);
        IsSelected();

        this.SwtBtn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                IsSelected();
            }
        });
        this.add(SwtBtn, BorderLayout.EAST);

       this.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mouseclicked(evt);
            }
       });          
    }    

    private void IsSelected()
    {
        if (this.SwtBtn.isSelected())
              this.SwtBtn.setIcon(new ImageIcon(getClass().getResource("/principal/icon/btnToggleOn.png")));
        else
           this.SwtBtn.setIcon(new ImageIcon(getClass().getResource("/principal/icon/btnToggleOff.png")));
    }
}

上下文WTBTN的代码(很抱歉是西班牙语):

public class ContenedorSwtBtn extends JPanel
{

    public ContenedorSwtBtn(String Nombre) 
    {
        super();  
        this.setBackground(new java.awt.Color(255, 255, 255));
        this.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(153, 153, 153)));
        this.setToolTipText("");
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        JLabel titulo = new JLabel();
        titulo.setBackground(new java.awt.Color(0, 0, 0));
        titulo.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
        titulo.setForeground(new java.awt.Color(0, 51, 51));
        titulo.setText(Nombre); 
        titulo.setAlignmentX(Component.CENTER_ALIGNMENT);    
        this.add(titulo);            
    }

    public void AddComponent(String nombreLog, boolean bandera)
    {
          SwitchToggleBtn log = new SwitchToggleBtn(nombreLog, bandera);          
          this.add(log);             
    }   
}

这是最终结果:

当我单击swichtogglebtn组件中的jtogglebutton时,它会改变他的状态,并将图标从off更改为on,反之亦然。
最后是创建新组件并将其添加到主jpanel中,如下所示:

JPanel MainPanel= new JPanel();
    MainPanel.setBackground(new java.awt.Color(255, 255, 255));
    MainPanel.setEnabled(true);
    MainPanel.setMaximumSize(new java.awt.Dimension(300, 280));
    MainPanel.setMinimumSize(new java.awt.Dimension(300, 280));
    MainPanel.setPreferredSize(new java.awt.Dimension(300, 280));     
    MainPanel.setVisible(true);

    ContenedorSwtBtn myComponent= new ContenedorSwtBtn("SETTINGS");
    myComponent.AddComponent("ONE", true);
    myComponent.AddComponent("TWO", false);
    myComponent.AddComponent("THREE",true);

    MainPanel.add(myComponent);

当我点击jtogglebutton并改变它的状态时,我想要确切的组件和它的当前状态,但是从主jpanel或中心面板,这样我就可以“保存更改”(savejpanel中的红色按钮)并实现一些逻辑来保存配置。如何将事件从子组件传递到父组件,或者如何从父组件知道子组件何时更改其状态。我读过关于创建一个实现actionlistener接口或实现propertychangeslistener接口的类,但我不明白。非常感谢你的帮助。

x7rlezfr

x7rlezfr1#

我不确定你想做什么,因为你的问题与mvc有任何关系(例如mvc swing应用程序的一个例子,请看这里),因为我可以告诉你,你真正需要的是从自定义控件中弹出事件,这样你就可以注册以在主面板中接收这些事件。
这很容易做到。检查我下面的例子。
基本上: ButtonPanel 是它自己的“组件”(它不扩展 JPanel 因为我不认为这是必要的,相反,有一个getter getPanel() 对于它创建的组件)。 ButtonPanel 还实现了 ActionListener 为按钮创建事件 ButtonPanel 有能力添加 ActionListener 通过 addActionListener 所以其他人可以注册 ActionEvent 他是从 ButtonPanel .

testapp.java文件:

import java.awt.event.ActionEvent;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class TestApp {

    public TestApp() {
        createAndShowGUI();

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TestApp::new);
    }

    private void createAndShowGUI() {
        JFrame frame = new JFrame("TestApp");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setBorder(new EmptyBorder(20, 20, 20, 20));
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        ButtonPanel buttonPanel = new ButtonPanel();
       // here we register for events created from the button panel as buttons are pressed
        buttonPanel.addActionListener((ActionEvent e) -> {
            JToggleButton button = (JToggleButton) e.getSource();
            switch (e.getActionCommand()) { // which button was pressed?
                case "button1":
                    JOptionPane.showMessageDialog(panel, "Button 1 pressed and isSelected is: " + button.isSelected());
                    break;
                case "button2":
                    JOptionPane.showMessageDialog(panel, "Button 2 pressed and isSelected is:" + button.isSelected());
                    break;
            }
        });
        panel.add(buttonPanel.getPanel());

        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
}

buttonpanel.java:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JToggleButton;

public class ButtonPanel implements ActionListener {

    private JPanel panel;
    private JToggleButton button1;
    private JToggleButton button2;
    private ActionListener actionListener;

    public ButtonPanel() {
        initView();
    }

    private void initView() {
        panel = new JPanel();
        button1 = new JToggleButton("Button 1 (OFF)");
        button2 = new JToggleButton("Button 2 (OFF)");
        button1.addActionListener(this);
        button2.addActionListener(this);
        panel.add(button1);
        panel.add(button2);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JToggleButton button = ((JToggleButton) e.getSource());
        button.setText(button.getText().substring(0, button.getText().indexOf("(")) + "(" + (button.isSelected() ? "ON" : "OFF") + ")");

        if (e.getSource() == button1) {
            if (actionListener != null) {
                actionListener.actionPerformed(new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, "button1"));// we send button1 as a command so we know what button was pressed
            }
        } else if (e.getSource() == button2) {
            if (actionListener != null) {
                actionListener.actionPerformed(new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, "button2"));// we send button2 as a command so we know what button was pressed
            }
        }
    }

    public JPanel getPanel() {
        return panel;
    }

    void addActionListener(ActionListener actionListener) {
        this.actionListener = actionListener;
    }
}

相关问题