WindowBuilder for Swing制作了成员数据,似乎没有必要
WindowBuilder for Swing 将复选框创建为局部变量,将文本框创建为成员数据。这种不一致让我很烦恼。由于无论如何它们都会链接到顶层 JFrame 中,因此只要 JFrame 具有对它们的引用,这些小部件就肯定会存在,因此文本框似乎不需要成为成员数据。在我看来,文本框应该像复选框一样是本地的。本地人封装得更好。本地引用可能会在 WindowBuilder 生成的 GUI 对象(扩展 JFrame 的类)构造函数的末尾处消失,并且 JFrame 仍将引用所有小部件。
使它们成为本地的并将“final”放在这些小部件声明的前面,以便它们可以在事件处理程序的匿名内部类中使用,这就是使它们工作的方法。我还必须稍微重新排列顺序,因为如果文本框都被声明为成员,则文本框的实例化顺序并不重要。顺序对于当地人来说确实很重要,所以我不得不将“新”运算符(实例化)的使用“向上”移动到本地范围的顶部。它们只需位于使用它们的事件处理程序的北部即可。
到目前为止,我还没有发现任何错误,所以我想问为什么 WindowBuilder 一开始不这样做。我对 Swing 和 WindowBuilder 很陌生,因此 WindowBuilder 很可能有充分的理由不这样做,尽管这似乎是适合我的情况的正确方法。
以下是经过一些简单的命名修改之后但在上述修改之前的 WindowBuilder 输出。这是输出,有 2 个文本框、2 个复选框、2 个位于北部的按钮和 1 个位于中心的标签。将此内容粘贴到此处,以防有人可以在这里看到一些内容,这些内容可以解释 WindowBuilder 使用成员数据背后的选择。
public class TestWB extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextField textBox1;
private JTextField textBox2;
public TestWB() // the constructor
{
... // see the constructor below
}
}
上述类的构造函数:
public TestWB()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 646, 451);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel northPanel = new JPanel();
contentPane.add(northPanel, BorderLayout.NORTH);
JButton button1 = new JButton("button1");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
northPanel.add(button1);
JButton button2 = new JButton("button2");
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
northPanel.add(button2);
final JCheckBox checkBox1 = new JCheckBox("cb1");
checkBox1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CbProcessor cbp = new CbProcessor();
cbp.dealWithCb(checkBox1.isSelected(), textBox1);
}
});
northPanel.add(checkBox1);
final JCheckBox checkBox2 = new JCheckBox("cb2");
checkBox2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CbProcessor cbp = new CbProcessor();
cbp.dealWithCb(checkBox2.isSelected(), textBox2);
}
});
northPanel.add(checkBox2);
textBox1 = new JTextField();
textBox1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
textBox1.setText("tb1");
northPanel.add(textBox1);
textBox1.setColumns(5);
textBox2 = new JTextField();
textBox2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
textBox2.setText("tb2");
northPanel.add(textBox2);
textBox2.setColumns(5);
JPanel centerPanel = new JPanel();
contentPane.add(centerPanel, BorderLayout.CENTER);
JLabel label1 = new JLabel("label1");
centerPanel.add(label1);
}
WindowBuilder for Swing creates checkboxes as local variables and textboxes as member data. This inconsistency bothered me. Since it all gets linked up into the toplevel JFrame anyway, these widgets are sure to live as long as the JFrame has references down to them so there doesn't seem to be a need for the textboxes to be member data. It seems to me that the textboxes should be locals just like the checkboxes. Locals are better encapsulation. The local references can die at the end of the GUI object (a class that extends JFrame) constructor generated by WindowBuilder and the JFrame will still have references to all the widgets.
Making them local and putting "final" in front of these widget declarations so that they can be used inside the event handler's anonymous inner classes was what it took to make them work. I also had to rearrange the order a bit since the order of instantiation of textboxes doesn't matter if they are all declared as members. Order does matter for locals so I had to move the uses of the "new" operator (instantiation) "up" a bit towards the top of the local scope. They just had to be north of the event handlers that use them.
So far I've found no bugs as a consequence so I am asking why WindowBuilder did not do it this way to begin with. I am new to Swing and WindowBuilder so there is a high probability that there are excellent reasons for WindowBuilder to not do this even though it seems to be the right approach for my case.
The following is the WindowBuilder output after some trivial naming modifications but before the modifications described above. This is the output as it is with 2 textboxes, 2 checkboxes, 2 buttons in the north and 1 label in the center. This is being pasted here in case somebody can see something here that may explain the choice behind WindowBuilder's use of member data.
public class TestWB extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextField textBox1;
private JTextField textBox2;
public TestWB() // the constructor
{
... // see the constructor below
}
}
The constructor for the above class:
public TestWB()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 646, 451);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel northPanel = new JPanel();
contentPane.add(northPanel, BorderLayout.NORTH);
JButton button1 = new JButton("button1");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
northPanel.add(button1);
JButton button2 = new JButton("button2");
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
northPanel.add(button2);
final JCheckBox checkBox1 = new JCheckBox("cb1");
checkBox1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CbProcessor cbp = new CbProcessor();
cbp.dealWithCb(checkBox1.isSelected(), textBox1);
}
});
northPanel.add(checkBox1);
final JCheckBox checkBox2 = new JCheckBox("cb2");
checkBox2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CbProcessor cbp = new CbProcessor();
cbp.dealWithCb(checkBox2.isSelected(), textBox2);
}
});
northPanel.add(checkBox2);
textBox1 = new JTextField();
textBox1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
textBox1.setText("tb1");
northPanel.add(textBox1);
textBox1.setColumns(5);
textBox2 = new JTextField();
textBox2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
textBox2.setText("tb2");
northPanel.add(textBox2);
textBox2.setColumns(5);
JPanel centerPanel = new JPanel();
contentPane.add(centerPanel, BorderLayout.CENTER);
JLabel label1 = new JLabel("label1");
centerPanel.add(label1);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这种情况下,阅读 WindowBuilder 文档可以轻松回答您的问题。 WindowBuilder 将以您喜欢的任何方式生成代码。小部件可以全部是局部变量、全部是字段或两者之间的任意组合。您可以单独或逐个类型(通过设置默认值)控制不同小部件的范围。事实上,WindowBuilder 具有非常丰富的代码生成首选项,并且可以复制您想要的几乎任何代码生成样式。它还会愉快地对您扔给它的任何代码进行逆向工程,因此您可以对生成的代码进行任何您想要的更改(手动或通过工具),并且它会保持完美的状态。
This is a case where reading the WindowBuilder docs would have easily answered your question(s). WindowBuilder will generate code any way that you like. Widgets can all be local variables, all be fields, or any combination in between. You can control the scope of different widgets individually or on a type-by-type basis (by setting defaults). In fact, WindowBuilder has an incredibly rich set of code generation preferences and can replicate just about any code generation style you could desire. It will also happily reverse engineer just about any code you throw at it, so you can make just about any changes you want to the generated code (by hand or via the tool) and it will remain perfectly happy.
我对 WindowBuilder 不太了解,但我确实对 SWT 和 SimpleDesktopAplication FrameWorks 了解一些,但是
1)两者都基于 AWT(部分来自 SWT)和 Swing
2)两者都覆盖了标准 AWT 和 Swing。 Swing 的方法
3) 在某些情况下很难返回到标准 AWT &来自框架方法的 Swing 方法
我建议在开始时学习基本的 Swing ,
I don't know something about WindowBuilder, but I do know something about SWT and SimpleDesktopAplication FrameWorks but
1) both are based on AWT(part from SWT) and Swing
2) both are overrode standard AWT & Swing's methods
3) in some cases is too hard to returns back to standard AWT & Swing's methods from Framework's methods
I'd suggest to learn basic Swing at begining,