问题描述
我已经开始学习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的许多主题的教程的更多链接。
对于要获得除当前引用之外的Component
,Window
等的引用的辅助方法,可以使用SwingUtilities
类中的方法,例如:
-
getAncestorNamed
:每个Component
都有一个名称,以及相应的accessor和mutator方法。这样,您就可以按名称引用Component
。 -
getRoot
:创建Component
并将它们添加到Container
和本质上Window
s时,您将创建一个Component
树层次结构。通过调用此方法,您可以为任何给定的Component
访问该层次结构的根Component
。 -
getUnwrappedParent
:属于Component
的树层次结构的每个Component
都有祖先(除非它是根Component
或Component
不属于到任何层次结构)。您可以使用此方法获得其祖先。 -
getWindowAncestor
和windowForComponent
:使用这两种等效方法,您可以获取Window
的第一个Component
祖先(后者依次已经属于Component
s的树层次结构。
但是最常见的情况是,您很少使用这些方法(取决于您的编程风格),并且通常在类中维护对所需的所有Component
的引用。
最后,还有一些访问Component
的所有Container
的通用方法,例如getComponents
,它返回Component
内的所有Container
(请注意,JFrame
是-a Window
,它是-a Container
)。
在Container
上使用getParent
执行相反的操作(即获取Component
所属的父Component
)。
在将Component
添加到树层次结构之后,将使用大多数这些方法。例如,获取没有添加到任何Component
中的Window
的窗口祖先是没有意义的。