Java Swing:获取对GUI组件的引用

问题描述

我已经开始学习Java,因此也开始学习Swing。我一直在研究构建GUI并想知道,在创建GUI组件后,如何获取GUI组件的引用以对其进行修改/读取/删除。创建组件时是否必须保留引用?还是Javascript中有类似的内容document.querySelector(),.querySelectorAll(),.getElementBy...()

作为示例,我们可以使用按钮和标签。单击按钮时,我想更改标签。在此示例中,每个人似乎都坚持使用他们在创建组件时获得的引用。

我已经阅读了有关MVC的信息,但是在我看来,它甚至更高级,更适合大型应用程序。

能否请您指出正确的学习Swing的方向-可靠的信息源-(有大量的教程,但并不是所有的教程都具有足够的质量)。

另外,我知道我必须在某个时候学习MVC才能创建更复杂的GUI。因此,如果您可以分享有关该主题的可靠链接,我也将不胜感激。

谢谢。

解决方法

JButton button = new JButton();
    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            //runs when button is pressed

            button pressed = (JButton)e.getSourse();
        }
        
    });

您可以将actionListener添加到按钮,然后从Event e获取按钮实例

JFrame f = new JFrame();
    f.setSize(500,500);
    f.setVisible(true);
    
    JButton button = new JButton();
    button.setBounds(0,100,100);
    f.add(button);
    
    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            System.out.println("pressed");
            JButton b = (JButton)e.getSource();
            b.setSize(200,200);
        }
        
    });

这就是我测试的方式,而且效果很好

,

如评论中所述,获取对所需组件的引用的一种简单方法就是自己存储引用。对于按钮更新标签的示例,您可以在代码中的某个地方维护对标签的引用。例如:

import java.awt.Font;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Main {
    
    //Utility method to create a String with random contents:
    private static String randomString(final int length) {
        
        //Create the alphabet:
        String alphabet = "abcdefghijklmnopqrstuvwxyz";
        alphabet += alphabet.toUpperCase();
        alphabet += "0123456789";
        
        final int alphabetLength = alphabet.length();
        final Random rand = new Random();
        final char[] chars = new char[length];
        
        //Fill the random String:
        for (int i = 0; i < chars.length; ++i)
            chars[i] = alphabet.charAt(rand.nextInt(alphabetLength));
        
        return new String(chars);
    }
    
    private static void createAndShowGUI() {
        //Initialize a JLabel with a random text:
        final JLabel label = new JLabel(randomString(10));
        
        //Change font to MONOSPACED BOLD (of the current size):
        label.setFont(new Font(Font.MONOSPACED,Font.BOLD,label.getFont().getSize()));
        
        //Create the JButton:
        final JButton button = new JButton("Click to change label text");
        
        //See here we maintain a reference to the label in the lambda expression:
        button.addActionListener(event -> label.setText(randomString(10)));
        
        //Create a Container (JPanel is-a Container) for the button and the label:
        final JPanel contents = new JPanel(); //FlowLayout by default.
        contents.add(button);
        contents.add(label);
        
        final JFrame frame = new JFrame("Main");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Declares that the application will exit when we click the close icon of the frame.
        frame.getContentPane().add(contents);
        frame.pack(); //Adjust the size of the frame according to its contents.
        frame.setLocationRelativeTo(null); //Make the frame centered in screen.
        frame.setVisible(true); //Show the frame.
    }
    
    public static void main(final String[] args) {
        //Always call Swing related code on the EDT. On way to achieve this is by calling invokeLater like so:
        SwingUtilities.invokeLater(Main::createAndShowGUI); //Main::createAndShowGUI is just another lambda expression.
    }
}

据我所知,Swing最可靠的信息来源是Oracle在以下链接中的官方说法:https://docs.oracle.com/javase/tutorial/uiswing/index.html,该链接指向有关Swing的许多主题的教程的更多链接。

对于要获得除当前引用之外的ComponentWindow等的引用的辅助方法,可以使用SwingUtilities类中的方法,例如:

  • getAncestorNamed:每个Component都有一个名称,以及相应的accessormutator方法。这样,您就可以按名称引用Component
  • getRoot:创建Component并将它们添加到Container和本质上Window s时,您将创建一个Component树层次结构。通过调用此方法,您可以为任何给定的Component访问该层次结构的根Component
  • getUnwrappedParent:属于Component的树层次结构的每个Component都有祖先(除非它是根ComponentComponent不属于到任何层次结构)。您可以使用此方法获得其祖先。
  • getWindowAncestorwindowForComponent:使用这两种等效方法,您可以获取Window的第一个 Component 祖先(后者依次已经属于Component s的树层次结构。

但是最常见的情况是,您很少使用这些方法(取决于您的编程风格),并且通常在类中维护对所需的所有Component的引用。

最后,还有一些访问Component的所有Container的通用方法,例如getComponents,它返回Component内的所有Container (请注意,JFrame是-a Window,它是-a Container)。

Container上使用getParent执行相反的操作(即获取Component所属的父Component)。

在将Component添加到树层次结构之后,将使用大多数这些方法。例如,获取没有添加到任何Component中的Window的窗口祖先是没有意义的。