我正在使用观察者模式来显示谁在玩。我从Observable获得了正确的数据,这就是为什么我不发布它。如您所见,正在设置文本,因为我可以调用label.getText()。
标签为什么不会更新?

香港专业教育学院试图重新粉刷,重新验证,SwingUtilities.invokeLater,updateUI和各种各样的东西。我不知道我在做什么错。

在此先感谢您。

public class PlayersTurnPane extends JPanel implements Observer {

    private JLabel label = new JLabel();

    public PlayersTurnPane() {
        setLayout(new BorderLayout());
        setBackground(Color.gray);
        label.setText("White");
        label.setHorizontalAlignment(getWidth() / 2);
        label.setFont(new Font("Serif", Font.PLAIN, 25));
        add(label);

    }

    @Override
    public void update(Observable arg0, Object arg1) {
        label.setText((String)arg1); //But it will not update label
        System.out.println(label.getText()); //The text is being set
    }

}


我的观察

 public class TurnObserver extends Observable {

    public TurnObserver(PlayersTurnPane playersTurnPane) {
        addObserver(playersTurnPane);
    }

    public void setTurn(String turn){
        setChanged();
        notifyObservers(turn);
        clearChanged();
    }

}


我在哪里发送数据

private TurnObserver turnObserver = new TurnObserver(new PlayersTurnPane());

public void grabPiece(BoardTile boardTile) {
        if(focusedPiece != null && playerTurn.getCurrentTurn() == focusedPiece.getPieceColor()) {
            boardTile.add(focusedPiece);
            updateUI();
            playerTurn.changeTurn();
            turnObserver.setTurn(playerTurn.getCurrentTurn());
        }
    }


该面板已添加到此处

public class EastPanel extends JPanel {

    public EastPanel() {
        setLayout(new GridLayout(3,0));
        add(new TimePane());
        add(new MoveHistoryPane());
        add(new PlayersTurnPane());
    }

}

最佳答案

如果正在打印System.out.println(label.getText());,则代码中未显示Swing线程问题,这可能是由于在Swing事件线程上运行了长时间运行的代码,从而阻止了该线程的工作-就像绘制更新的JLabel上的文本。确保所有长时间运行的代码都在后台线程上完成,并且Swing状态更改和查询在Swing事件线程上进行。有关详细信息,请阅读Concurrency in Swing

回覆,


  我从Observable获得了正确的数据,这就是为什么我不发布它。


但是,正是这些未发布的代码才是解决问题的关键。



堂,疯了是对的:你在阴影:

public TurnObserver() {
    addObserver(new PlayersTurnPane());
}


您要添加一个新的PlayersTurnPane作为观察者,但可能不是显示的PlayersTurnPane!关键:每次在构造函数上调用new时,都会创建一个新对象,这里是PlayersTurnPane。您应该传入显示的PlayersTurnPane,而不是新的。

您在使用以下代码时遇到问题:

public class EastPanel extends JPanel {

    public EastPanel() {
        setLayout(new GridLayout(3,0));
        add(new TimePane());
        add(new MoveHistoryPane());
        add(new PlayersTurnPane());
    }
}


dsiplayed PlayersTurnPane被匿名创建-该对象正在添加到显示中,但是该对象未被任何变量引用,如果要将完全相同的PlayersTurnPane对象传递给该方法,则需要这样做这使其可观察。

我建议您在需要引用对象的地方使用类字段而不是匿名对象。所以在这里,也许会更好:

public class EastPanel extends JPanel {

    public EastPanel(PlayersTurnPane playersTurnPane) {
        setLayout(new GridLayout(3,0));
        add(new TimePane()); // you likely need parameters for
        add(new MoveHistoryPane());  // these two objects as well
        add(playersTurnPane);
    }
}


您似乎缺少的关键概念是引用的重要性之一,引用是指向感兴趣对象的指针。继续阅读。

10-05 23:37