I'm looking for a place to hook some code to programmatically create, size and position a JPanel after the application has finished loading.
我正在寻找一个地方来挂钩一些代码,以便在应用程序加载完成后以编程方式创建,调整大小和定位JPanel。
I'm just starting with Java. I'm using NetBeans 6.5.1 with jdk1.6.0_13. I've used the new project wizard to create a basic Java/Swing desktop application. This is a SingleFrameApplication that uses a FrameView with a central main JPanel where all the UI elements are placed.
我刚开始使用Java。我正在使用带有jdk1.6.0_13的NetBeans 6.5.1。我已经使用新项目向导来创建基本的Java / Swing桌面应用程序。这是一个SingleFrameApplication,它使用带有*主要JPanel的FrameView,其中放置了所有UI元素。
I first tried my code in the FrameView constructor but when I try to arrange my JPanel based on the bounding rectangle of one of the design time controls I added to the UI, that control has not yet finished being positioned and sized so I'm getting all zeros for the coordinates.
我首先在FrameView构造函数中尝试了我的代码但是当我尝试根据我添加到UI中的一个设计时控件的边界矩形来安排我的JPanel时,该控件还没有完成定位和调整大小所以我得到了全部为坐标的零。
I've verified my code works as expected by calling it from a click event after the application has loaded so my problem is finding a way to know when everything is finished being sized and arranged.
我已经验证了我的代码按照预期通过在应用程序加载后从单击事件中调用它来工作,所以我的问题是找到一种方法来了解何时完成所有内容的大小和排列。
I also tried the componentShown event from the main JPanel but I later read that is only fired if setVisible is explicitly called which apparently doesn't happen during normal application startup.
我还尝试了来自主JPanel的componentShown事件,但我后来读到只有在显式调用setVisible时才会触发,这在正常的应用程序启动过程中显然不会发生。
Can anyone provide some pointers? Thanks.
任何人都可以提供一些指示吗?谢谢。
Update:
In addition to what I mention in my answer below, I also read about the Application.ready() method. This would also be a point in time of interest for knowing when the UI part of an application is finished doing everything it needs to do. Communicating to my view from the application seemed a bit messy though.
除了我在下面的回答中提到的内容之外,我还阅读了Application.ready()方法。这也是知道应用程序的UI部分何时完成它需要做的所有事情的兴趣点。从应用程序传达我的观点似乎有点混乱。
4 个解决方案
#1
The solution I went with was actually a combination of the answers from Charles Marin and JRL (I upvoted both of your answers for credit, thanks).
我采用的解决方案实际上是查尔斯马林和JRL的答案的组合(我赞同你的两个信用答案,谢谢)。
I had my FrameView class implement WindowListener.
我有我的FrameView类实现WindowListener。
...
public class MyView extends FrameView implements WindowListener
...
and in my FrameView constructor I added a listener to the application's main frame.
在我的FrameView构造函数中,我向应用程序的主框架添加了一个监听器。
...
getFrame().addWindowListener((WindowListener) this);
...
Then in my implementation of windowActivated I could call the code I had to arrange and size a control on the main JPanel based on the location and size of other controls.
然后在我的windowActivated实现中,我可以根据其他控件的位置和大小调用我必须安排的代码并在主JPanel上调整控件的大小。
public void windowActivated(WindowEvent e)
{
// The application should now be finished doing its startup stuff.
// Position and size a control based on other UI controls here
}
#2
I think you want WindowActivated. Have a look at this part of the tutorial.
我想你想要WindowActivated。看看本教程的这一部分。
#3
I'd try using getFrame().isValid()
我尝试使用getFrame()。isValid()
#4
I assume this is the WYSIWYG editor thing. I'm looking at NetBeans 6.1, so your experiences may vary.
我认为这是WYSIWYG编辑器的事情。我正在研究NetBeans 6.1,因此您的体验可能会有所不同。
The traditional way to layout Swing components is by using a LayoutManager (or LayoutManager2). According to the NetBeans help, the visual editor supports these so long as they don't require support for constraints.
布局Swing组件的传统方法是使用LayoutManager(或LayoutManager2)。根据NetBeans的帮助,可视化编辑器支持这些,只要它们不需要支持约束。
The procedure goes something like this:
程序如下:
- Create a new JavaBean and have it implement LayoutManager (a BeanInfo is required too for palette support - you can create one by right-clicking the bean class)
- Build the project
- Right-click the bean and choose Tools > Add to Palette... and add it
- Right-click the panel for which you want to set the layout and select Set Layout > Your Bean Name
创建一个新的JavaBean并让它实现LayoutManager(对于调色板支持也需要BeanInfo - 您可以通过右键单击bean类来创建一个)
建立项目
右键单击该bean,然后选择“工具”>“添加到调色板...”并添加它
右键单击要为其设置布局的面板,然后选择“设置布局”>“您的Bean名称”
You may find the design-time experience somewhat lacking.
您可能会发现设计时体验有点缺乏。
A sample layout implementation:
示例布局实现:
public class StepLayoutBean extends Object implements Serializable, LayoutManager {
public void addLayoutComponent(String name, Component component) {
}
public void layoutContainer(Container container) {
Dimension space = container.getSize();
int xoffset = 0;
int yoffset = 0;
for (Component kid : container.getComponents()) {
Dimension prefSize = kid.getPreferredSize();
if (prefSize.width + xoffset > space.width) {
xoffset = 0;
}
Rectangle bounds = new Rectangle(xoffset, yoffset, prefSize.width, prefSize.height);
kid.setBounds(bounds);
xoffset += prefSize.width;
yoffset += prefSize.height;
}
}
public Dimension minimumLayoutSize(Container container) {
Dimension size = new Dimension();
for (Component kid : container.getComponents()) {
Dimension minSize = kid.getMinimumSize();
size.width = minSize.width > size.width ? minSize.width : size.width;
size.height += minSize.height;
}
return size;
}
public Dimension preferredLayoutSize(Container container) {
Dimension size = new Dimension();
for (Component kid : container.getComponents()) {
Dimension prefSize = kid.getPreferredSize();
size.width += prefSize.width;
size.height += prefSize.height;
}
return size;
}
public void removeLayoutComponent(Component component) {
}
}
If a custom layout doesn't fit the bill, have a look at the event bindings under the component's properties panel - though resizing that way might be a recipe for some kind of recursive event storm.
如果自定义布局不符合条件,请查看组件属性面板下的事件绑定 - 尽管调整大小可能会导致某种递归事件风暴。
#1
The solution I went with was actually a combination of the answers from Charles Marin and JRL (I upvoted both of your answers for credit, thanks).
我采用的解决方案实际上是查尔斯马林和JRL的答案的组合(我赞同你的两个信用答案,谢谢)。
I had my FrameView class implement WindowListener.
我有我的FrameView类实现WindowListener。
...
public class MyView extends FrameView implements WindowListener
...
and in my FrameView constructor I added a listener to the application's main frame.
在我的FrameView构造函数中,我向应用程序的主框架添加了一个监听器。
...
getFrame().addWindowListener((WindowListener) this);
...
Then in my implementation of windowActivated I could call the code I had to arrange and size a control on the main JPanel based on the location and size of other controls.
然后在我的windowActivated实现中,我可以根据其他控件的位置和大小调用我必须安排的代码并在主JPanel上调整控件的大小。
public void windowActivated(WindowEvent e)
{
// The application should now be finished doing its startup stuff.
// Position and size a control based on other UI controls here
}
#2
I think you want WindowActivated. Have a look at this part of the tutorial.
我想你想要WindowActivated。看看本教程的这一部分。
#3
I'd try using getFrame().isValid()
我尝试使用getFrame()。isValid()
#4
I assume this is the WYSIWYG editor thing. I'm looking at NetBeans 6.1, so your experiences may vary.
我认为这是WYSIWYG编辑器的事情。我正在研究NetBeans 6.1,因此您的体验可能会有所不同。
The traditional way to layout Swing components is by using a LayoutManager (or LayoutManager2). According to the NetBeans help, the visual editor supports these so long as they don't require support for constraints.
布局Swing组件的传统方法是使用LayoutManager(或LayoutManager2)。根据NetBeans的帮助,可视化编辑器支持这些,只要它们不需要支持约束。
The procedure goes something like this:
程序如下:
- Create a new JavaBean and have it implement LayoutManager (a BeanInfo is required too for palette support - you can create one by right-clicking the bean class)
- Build the project
- Right-click the bean and choose Tools > Add to Palette... and add it
- Right-click the panel for which you want to set the layout and select Set Layout > Your Bean Name
创建一个新的JavaBean并让它实现LayoutManager(对于调色板支持也需要BeanInfo - 您可以通过右键单击bean类来创建一个)
建立项目
右键单击该bean,然后选择“工具”>“添加到调色板...”并添加它
右键单击要为其设置布局的面板,然后选择“设置布局”>“您的Bean名称”
You may find the design-time experience somewhat lacking.
您可能会发现设计时体验有点缺乏。
A sample layout implementation:
示例布局实现:
public class StepLayoutBean extends Object implements Serializable, LayoutManager {
public void addLayoutComponent(String name, Component component) {
}
public void layoutContainer(Container container) {
Dimension space = container.getSize();
int xoffset = 0;
int yoffset = 0;
for (Component kid : container.getComponents()) {
Dimension prefSize = kid.getPreferredSize();
if (prefSize.width + xoffset > space.width) {
xoffset = 0;
}
Rectangle bounds = new Rectangle(xoffset, yoffset, prefSize.width, prefSize.height);
kid.setBounds(bounds);
xoffset += prefSize.width;
yoffset += prefSize.height;
}
}
public Dimension minimumLayoutSize(Container container) {
Dimension size = new Dimension();
for (Component kid : container.getComponents()) {
Dimension minSize = kid.getMinimumSize();
size.width = minSize.width > size.width ? minSize.width : size.width;
size.height += minSize.height;
}
return size;
}
public Dimension preferredLayoutSize(Container container) {
Dimension size = new Dimension();
for (Component kid : container.getComponents()) {
Dimension prefSize = kid.getPreferredSize();
size.width += prefSize.width;
size.height += prefSize.height;
}
return size;
}
public void removeLayoutComponent(Component component) {
}
}
If a custom layout doesn't fit the bill, have a look at the event bindings under the component's properties panel - though resizing that way might be a recipe for some kind of recursive event storm.
如果自定义布局不符合条件,请查看组件属性面板下的事件绑定 - 尽管调整大小可能会导致某种递归事件风暴。