本文介绍了Swing JPanel 不会重绘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个扩展 JPanel 的简单对象,当在这个对象上调用 update() 方法时,它意味着向面板添加一些标签,然后重新绘制.但是调用 update 方法后标签不显示,下面是更新代码:

I have a simple object which extends JPanel, when the update() method is called on this object it it meant to add some labels to the panel and then repaint. However the labels do not show up after the update method is called, below is the code for update:

public void update(){
        GridBagConstraints constraints = new GridBagConstraints();

        if(cardsHidden){
            for(int i = 0; i < 2; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(PlayingCards.cardImages[PlayingCards.CARD_BACK_INDEX]);
                add(card, constraints);
            }
        }
        else{
            Card[] holeCards = player.getHoleCards();
            for(int i = 0; i < holeCards.length; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(holeCards[i].getImageIcon());
                add(card, constraints);
            }
        }

        validate();
        repaint();
    }

有什么想法吗?

谢谢

编辑

已解决:

事实证明 HoleCardsPanel 没有正确添加到其父框架.一旦解决了这个问题,添加新的 JLabel 就可以正常工作了.我也:

It turns out that the HoleCardsPanel wasn't adding to its parent frame properly. Once that was fixed the adding of new JLabels works fine. I also:

  • 使用 SwingUtillities.invokeLater
  • 将对 update() 方法的调用添加到事件调度线程
  • 必须从最上面的组件(在本例中为 JFrame)调用 validate() 作为 Devon_C_Miller 在他的回答中提出建议.
  • added the call to the update() method to the event dispatch thread using SwingUtillities.invokeLater
  • had to call validate() from the uppermost component (in this case the JFrame) as Devon_C_Miller suggests in his answer.

推荐答案

这取决于您想要发生的事情以及使用的布局管理器,但基本规则是:

It depends on what you want to happen and what layout managers are in use, but the basic rules are:

  1. 确保在 EDT 上调用了 update.如果不是(SwingUtilities.isEventDispatchThread() 返回 false),您将需要使用 SwingUtilities.invokeLater 在 EDT 上安排更新.例如:

  1. Make sure update is called on the EDT. If it's not (SwingUtilities.isEventDispatchThread()returns false) you will need to use SwingUtilities.invokeLater to schedule the update on the EDT. For example:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        update();
    }});

  • 调用invalidate().大多数更改组件的事情都会为您做到这一点.因此,只有在以下内容本身不起作用时才需要调用它.

  • Call invalidate(). Most things that change a component will do this for you. So you only need to call this if the following does not work on its own.

    最高受影响的组件上调用validate().这可能是 Java 渲染周期中最混乱的部分.对 invalidate 的调用将组件及其所有祖先标记为需要布局.对validate 的调用执行组件及其所有后代的布局.一个向上"工作,另一个向下"工作.您需要在树中将受您更改影响的最高组件上调用 validate.

    Call validate() on the highest affected component. This is probably the muddiest bit of Java's rendering cycle. The call to invalidate marks the component and all of its ancestors as needing layout. The call to validate performs the layout of the component and all of its descendants. One works "up" and the other works "down". You need to call validate on the highest component in the tree that will be affected by your change.

    此外,在顶级组件(JWindow、JDialog、JFrame)上调用 validate 不一定会调整该组件的大小.要实现这一点,您需要调用 pack()setSize().

    Also, calling validate on a top-level component (JWindow, JDialog, JFrame) will not necessarily resize that component. To make that happen, you'll need to call pack() or setSize().

    如果您的更改改变了容器的大小或位置,调整大小的容器将重新绘制,但不会擦除过去占用的空间.在容器的父容器上调用 repaint() 将导致它重新绘制背景,纠正损坏.

    If your changes alter the size or position of containers, The resized containers will repaint, but they will not erase the space the used to occupy. Calling repaint() on the parent of the container will cause it to repaint the background, correcting the damage.

    这篇关于Swing JPanel 不会重绘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 07-29 22:22