代码之家  ›  专栏  ›  技术社区  ›  Reiion

JButton不是选定的组件,而是对最近添加的按钮值的更改

  •  0
  • Reiion  · 技术社区  · 8 年前

    我正在为一个学校项目开发一个小的用户界面生成器,我能够将按钮的文本值从 textField 使用 DocumentListener .

    然而,在尝试添加另一个按钮时,我发现当我在新按钮上选择时,它会变回最近选择的组件的值。

    //DragListener: for isolating changes on a particular component
    DragListener drag = new DragListener(UIBuilder.this);
    
    //Add new button on mouseclick
    addButton.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent arg0) {
            JButton button = new JButton("JButton");
            button.setBounds(50,20, 90,20);
            internalFrame.getContentPane().add(button);
            button.addMouseListener(drag);
            button.addMouseMotionListener(drag);
            repaint();
            System.out.println("Button added.");
        }
    });
    

    然后将组件传递给 DragListener

    public class DragListener extends MouseInputAdapter
    {
        Point location;
        MouseEvent pressed;
        private UIBuilder uiBuilder;
    
       public DragListener(UIBuilder ui){
        this.uiBuilder = ui;
       }
    
       public void mousePressed(MouseEvent me)
       {
           pressed = me;
           Component component = me.getComponent();
    
           if (component instanceof JButton){
               JButton button = (JButton) component;
               uiBuilder.getTxtFieldsetText().setText(button.getText());
               uiBuilder.getTextFieldName().setText(button.getName());
    
            uiBuilder.getTxtFieldsetText().getDocument().addDocumentListener(new DocumentListener() {
    
            @Override
            public void removeUpdate(DocumentEvent e) {
                ((JButton) component).setText(uiBuilder.getTxtFieldsetText().getText());
            }
    
            @Override
            public void insertUpdate(DocumentEvent e) {
                ((JButton) component).setText(uiBuilder.getTxtFieldsetText().getText());
            }
    
            @Override
            public void changedUpdate(DocumentEvent e) {
                ((JButton) component).setText(uiBuilder.getTxtFieldsetText().getText());
            }
        });
           }
       }
    
       public void mouseDragged(MouseEvent me)
       {
           Component component = me.getComponent();
           location = component.getLocation(location);
           int x = location.x - pressed.getX() + me.getX();
           int y = location.y - pressed.getY() + me.getY();
           component.setLocation(x, y);
    
        }
    

    因为我很难命名和描述这个问题。。。我不太确定如何进一步解释我的问题,所以我想我会把这个贴出来 gif 对于任何阅读的人来说,都是为了更好地理解。

    1 回复  |  直到 8 年前
        1
  •  0
  •   Community Mohan Dere    6 年前

    嗯,你似乎没有移除 DocumentListener 什么时候 mousePressed 再次调用。

    看看你的代码。。。

    public void mousePressed(MouseEvent me)
    {
       pressed = me;
       Component component = me.getComponent();
    
       if (component instanceof JButton){
           JButton button = (JButton) component;
           uiBuilder.getTxtFieldsetText().setText(button.getText());
           uiBuilder.getTextFieldName().setText(button.getName());
    
           uiBuilder.getTxtFieldsetText().getDocument().addDocumentListener(new DocumentListener() {
               //...
    

    鼠标按下 调用时,您设置 UIBuilder DocumentListener 尚未从最后一个按钮中删除,它会自动更新之前选择的按钮的文本。

    你需要稍微改变一下这个概念。这个 DragListener UIBuilder 然后将生成事件 DragListener公司 可以响应。通过这种方式,您可以对代码进行解耦,但也可以减少像这样可能出现的错误。

    然后,您将维护对所选组件的引用,并在收到 UIBuilder ,相应地更新其状态。

    这可能意味着您需要生成自己的侦听器接口和事件模型,但由于您习惯于处理 MouseListener 和 DocumentListener ,您已经基本了解了它们的工作原理

    实例

    从描述生成器可以生成的事件的基本界面开始

    public interface UIBuilderListener extends EventListener {
        public void componentTextDidChange(ComponentTextEvent evt);
        public void componentNameDidChange(ComponentTextEvent evt);
    }
    

    可以有不止一个听众,每个人都专注于一系列特定的事件,但我只是保持简单。

    对象事件处理程序被传递有关事件的信息,例如。。。

    public class ComponentTextEvent extends EventObject {
    
        private String text;
    
        public ComponentTextEvent(UIBuilder source, String text) {
            super(source);
            this.text = text;
        }
    
        public UIBuilder getBuilder() {
            return (UIBuilder) getSource();
        }
    
        public String getText() {
            return text;
        }
    
    }
    

    然后你的 DragListener公司

    public class DragListener extends MouseInputAdapter implements UIBuilderListener {
    
        Point location;
        private UIBuilder uiBuilder;
        private Component selectedComponent;
    
        public DragListener(UIBuilder ui) {
            this.uiBuilder = ui;
            ui.addBuilderListener(this);
        }
    
        public void mousePressed(MouseEvent me) {
            selectedComponent = me.getComponent();
        }
    
        @Override
        public void componentTextDidChange(ComponentTextEvent evt) {
            if (selectedComponent instanceof JButton) {
                JButton btn = (JButton) selectedComponent;
                btn.setText(evt.getText());
            }
        }
    
        @Override
        public void componentNameDidChange(ComponentTextEvent evt) {
            if (selectedComponent instanceof JButton) {
                JButton btn = (JButton) selectedComponent;
                btn.setName(evt.getText());
            }
        }
    
    }
    

    这是很好的香草(很好),我们想要 DragListener公司 UIBuilder 这将尽可能地解耦代码,并允许您更改生成器(或 DragListener公司 )在不影响彼此的情况下工作,因为它们依赖于API描述的内容,而不是它们的实现方式(我个人认为 UIBuilder 还有一个界面,但那就是我)

    然后,在 UIBuilder DocumentListener 反对 JTextField 他们自己

    JTextField componentTextField;
    componentTextField.getDocument().addDocumentListener(new DocumentListener() {
    
        protected void generateTextEvent(DocumentEvent e) {
            try {
                Document doc = e.getDocument();
                generateTextEvent(doc.getText(0, doc.getLength()));
            } catch (BadLocationException ex) {
                // Handle possible exception
            }
        }
    
        @Override
        public void removeUpdate(DocumentEvent e) {
            generateTextEvent(e);
        }
    
        @Override
        public void insertUpdate(DocumentEvent e) {
            generateTextEvent(e);
        }
    
        @Override
        public void changedUpdate(DocumentEvent e) {
            generateTextEvent(e);
        }
    });
    

    最终会打电话给。。。

    protected void generateTextEvent(String text) {
        ComponentTextEvent evt = new ComponentTextEvent(this, text);
        // Loop through listener register and call componentTextDidChange
    }
    

    它将执行事件的实际调度