在重绘方法中添加GUI组件

4
我对Java GUI的理解不如我想象中的好。在我的窗体的paint方法中,我想清除所有当前的按钮,并添加新的按钮。(总体目标是提供一个界面,用户可以看到字符并单击按钮以下载与该字符相关的文档。由于每个字符都不同,当用户从我的列表中选择一个新用户时,将为他们提供一组新的文档和按钮。)
这是我刚刚编写的一个测试窗体,展示了事情会偏离轨道的地方。它具有我在实际程序中使用的类似范例,没有太多的杂乱无章。
public class GUITest extends JFrame
{

/**
 * @param args
 */
public static void main(String[] args)
{
    Container gui_test = new GUITest();

}

private JComponent content = null;

public GUITest()
{
    super();

    setVisible(true);
}

public void paint(Graphics g)
{
    this.removeAll();

    content = new JPanel();

    JComponent test_button = new JButton("New Button 1");
    JComponent button = new JButton("New Button 2");

    content.add(button);
    content.add(test_button);

    this.add(content);

    super.paint(g);
}

}

没有调用removeAll(),按钮会继续被放在JPanel上面,但是有了这个调用,就什么也不显示了。我不知道为什么会这样,因为我已经适当地添加了组件,对吗?
编辑 明白了,让我给你更详细的解释。客户通过查看西侧面板上游戏中角色列表来浏览我的程序。他们可以从列表中选择一行,然后在东侧面板上显示char详情。详情包括图像和描述。最近,我添加了相关文档,这些文档将显示在东侧面板的底部。我创建了键盘监听器,以便客户可以通过按数字键快速查看文档,但我还希望给他们能够单击按钮启动pdf视图并查看文档内容的能力。
由于每个char都有不同的相关文档和不同数量的文档,我每次都会重新绘制按钮,以反映相关文档的数量和文档的适当标题。这就是重绘出现问题的地方。你给了我一个很好的解释,但我不知道如何让客户访问文档,除了在热键启动文档时绘制文档的描述。这有意义吗?

2
我可以建议阅读http://docs.oracle.com/javase/tutorial/uiswing/和http://docs.oracle.com/javase/tutorial/2d/index.html(更深入地了解内部情况)。 - MadProgrammer
2个回答

7
永远不要在paint或paintComponent方法中添加或删除GUI组件。永远不要这样做。这些方法仅用于绘制,并且需要尽可能快,否则您的程序将显得无响应。此外,您无法完全控制何时甚至是否将调用这些方法,因此程序逻辑和结构不应进入这些方法。相反,使用事件侦听器(例如ActionListeners、ListSelectionListeners或键绑定)来响应用户事件。
关于:
客户通过在西面板上查看游戏中的角色列表来导航我的程序。他们可以从列表中选择一行,这将在东面板上显示char详细信息。详细信息是一个图像和说明。最近,我为该特定字符添加了相关文档,这些文档将显示在东面板底部。我创建了键盘监听器,以便客户可以通过按数字键快速查看文档,但我还想让他们能够单击按钮启动pdf视图并查看文档内容。
我将使用JList来保存左侧可选信息的列表,并使用ListSelectionListener对其进行反应。在侦听器中,我将更改相关的显示信息。我还避免在Swing中使用KeyListeners,而是倾向于使用Key Bindings,因为它们更灵活,对焦点不那么严格。
关于:
由于每个角色都有不同的相关文档和不同数量的文档,所以我每次都重新绘制按钮,以反映相关文档的数量和适当的文档标题。这就是repaint表现奇怪的地方。您给了我一个好的解释,但我不知道如何让客户访问文档,除了绘制文档说明以及启动它所需的热键。这有意义吗?
我不确定您在做什么或者您想要做什么。

谢谢!这很有道理,因为一些疯狂的事情发生了,比如有时候按钮会出现,但有时候不会。在这种情况下,有什么替代方案吗? - Sal
我有键盘监听器,可以在不点击按钮的情况下打开文档,但是我应该如何让客户端也能够单击某个按钮或类似对象?我选择了一个糟糕的设计吗?还是有一些“轻量级”组件适用于这种情况? - Sal
1
@Sal:请提供更多详细信息。我不完全理解你的问题,只知道你的程序有什么困难。 - Hovercraft Full Of Eels
明白了,让我给您更详细的说明。一个客户通过查看游戏中西侧面板上的字符列表来导航我的程序。他们可以从列表中选择一行,这将在东侧面板上显示字符详细信息。详细信息包括图像和描述。最近,我为该特定字符添加了相关文档,这些文档将显示在东侧面板的底部。我创建了键盘监听器,以便客户可以通过按数字键快速查看文档,但我也想让他们有能力点击按钮启动PDF视图并查看文档内容。 - Sal
由于每个字符都有不同的相关文档和不同数量的文档,我每次都重新绘制按钮,以反映相关文档的数量和文档的适当标题。这就是重新绘制出现问题的地方。您给了我一个很好的解释,但我不知道如何让客户访问文档,除了在启动它所需的热键旁边绘制文档描述。这有意义吗? - Sal
显示剩余3条评论

3
由于每个字符都有不同数量和相关文档,我每次都会重新绘制按钮,以反映相关文档的数量和适当的文档标题。这就是重新绘制时出现问题的地方。你给了我一个很好的解释,但我不知道如何让客户端访问文档,除了在热键启动时绘制文档的描述。这样说通吗?
因此,不要“绘制”按钮,而是改变它们的文本(setText(...))。
当用户选择一个“char”时,您需要重新构建屏幕的某些部分。更改列表模型(如上所建议),并在文档容器中添加/删除任何必要的按钮。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接