奇怪的JavaFX应用程序线程异常

时间:2017-12-21 21:45:53

标签: javafx

我们正在使用Java Serialization制作一个名为Dominion的纸牌游戏,其中包含客户端服务器。我们还使用observer / observable和threads(用于在服务器和客户端读取消息的线程)。

如果玩家能够玩牌或购买牌,我们会用CSS突出显示牌。突出显示由接口Observer的更新方法添加,其中正在观察游戏卡。如果特定条件为真,我们将向游戏卡添加突出显示(类GameCard是实现Observer)。

一般来说它运作正常,但有一张牌(名为民兵)迫使对手从他们手中弃牌,直到他们只剩下3张牌。我们可以多次玩这个没有例外,但突然有几个例外(大约7-10次打了民兵卡)。我们不知道为什么。

这种例外的原因是什么?我认为如果我发布代码没有帮助,我会发布例外:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.text.PrismTextLayout.addTextRun(PrismTextLayout.java:755)
    at com.sun.javafx.text.GlyphLayout.addTextRun(GlyphLayout.java:140)
    at com.sun.javafx.text.GlyphLayout.breakRuns(GlyphLayout.java:210)
    at com.sun.javafx.text.PrismTextLayout.buildRuns(PrismTextLayout.java:770)
    at com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1021)
    at com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:223)
    at com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:246)
    at javafx.scene.text.Text.getLogicalBounds(Text.java:358)
    at javafx.scene.text.Text.impl_computeGeomBounds(Text.java:1168)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.computeLocalBounds(Node.java:3595)
    at javafx.scene.Node.updateLocalBounds(Node.java:3625)
    at javafx.scene.Node.getLocalBounds(Node.java:3486)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1524)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.impl_intersectsBounds(Node.java:5015)
    at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2931)
    at javafx.scene.Node.impl_pickNode(Node.java:4914)
    at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899)
    at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485)
    at javafx.scene.Scene.pick(Scene.java:1942)
    at javafx.scene.Scene.access$6700(Scene.java:159)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3711)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    at java.lang.Thread.run(Unknown Source)
Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.elementData(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
    at com.sun.javafx.collections.VetoableListDecorator.get(VetoableListDecorator.java:306)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1591)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.impl_intersectsBounds(Node.java:5015)
    at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2931)
    at javafx.scene.Node.impl_pickNode(Node.java:4914)
    at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899)
    at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485)
    at javafx.scene.Scene.pick(Scene.java:1942)
    at javafx.scene.Scene.access$6700(Scene.java:159)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3711)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    at java.lang.Thread.run(Unknown Source)
Exception in thread "JavaFX Application Thread" 

...如果我们只是将鼠标悬停在舞台上,则会抛出数百次此异常:

Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException

可能导致例外的代码: 1.在本课程中,我们将突出显示对手必须丢弃的牌(直到他留下3张牌;见croupier.isDiscardModeMilitia ......行。)

public class GameCard extends Button implements Observer  {
    protected static final boolean MoneyCard = false;
    ServiceLocatorClient sl = ServiceLocatorClient.getServiceLocator();
    Croupier croupier = Croupier.getCroupier();

    Label   lbl_cardName;
    String text_DE;
    boolean holeCard  = false;

    int costs;

    StackSizeInfo stackSizeInfo;


    public GameCard(Label cardName, String text_DE) {
        super();
        this.lbl_cardName = cardName;
        this.text_DE=text_DE;
        this.assignPicture();
    }

    public GameCard(){
    }

    GameCard gc = this;

    @Override
    public void update(Observable arg0, Object arg1) {

        getStyleClass().remove("highlight");
        getStyleClass().remove("highlight2");
        getStyleClass().remove("highlight3");

        //Highlighte alle Karten im Kaufmodus, welche ich mit der aktuelln Buypower und buys kaufen kann
        if (croupier.isBuyMode() == true && croupier.getBuyPower() >= this.costs && !this.isHoleCard() && croupier.getBuys() > 0){
            this.getStyleClass().add("highlight");
        }

        //Highlighte alle Geldkarten im Kaufmodus
        if (croupier.isBuyMode() == true && this.isHoleCard() && this instanceof MoneyCard){
            this.getStyleClass().add("highlight");
        }

        //Highlighte alle Aktionskarten im Aktionsmodus
        if (croupier.isActionMode() == true && this.isHoleCard() && this instanceof ActionCard){
            this.getStyleClass().add("highlight");
        }

        //Highlighte alle HoleCards im Discardmodus (basement)
        if (croupier.isDiscardMode() == true && this.isHoleCard()){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle HoleCards im TrashModus Kapelle
        if (croupier.isTrashModeChapel() == true && this.isHoleCard()){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle MoneyCards im TrashModus Mine
        if (croupier.isTrashModeMine() == true && this instanceof MoneyCard && this.isHoleCard()){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle Karten auf der Hand, welche im Umbaumodus weggeworfen werden können
        if (croupier.isTrashModeRebuilding() == true && this.isHoleCard()){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle Kupferkarten auf der Hand, die gegen +3Geld weggeworfen werden können (ActionCard Geldverleiher)
        if (croupier.isTrashModeMoneylender() == true && this.isHoleCard() && this.getLbl_cardName().getText().equals("copper")){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle MoneyCards, welche erworben werden können im Minen-Modus
        if (croupier.isModeForMine() == true && this instanceof MoneyCard && !this.isHoleCard() && this.costs <= croupier.getSavedMCValueForMineMode()){
            this.getStyleClass().add("highlight");
        }

        //Highlighte alle Karten zum Kauf, welche erworben werden können im Rebuilding-Modus
        if (croupier.isModeForRebuilding() == true && !this.isHoleCard() && this.costs <= croupier.getCardValueForRebuildingMode()){
            this.getStyleClass().add("highlight");
        }

        //Highlighte alle Karten zum Kauf, welche erworben werden können im Rebuilding-Modus
        if (croupier.isModeForWorkshop() == true && !this.isHoleCard() && this.costs <= 4){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle Moat-Karten wenn ein Angriff gemacht worden ist
        if (croupier.isReactionMode() == true && this.isHoleCard() && this.getLbl_cardName().getText().equals("moat")){
            this.getStyleClass().add("highlight3");
        }

        //Highlighte alle Moat-Karten wenn ein Angriff gemacht worden ist
        if (croupier.isDiscardModeMilitia() == true && this.isHoleCard()){
            this.getStyleClass().add("highlight2");
        }

        //Highlighte alle Moat-Karten wenn ein Angriff gemacht worden ist
        if (croupier.isModeForCurseCard() == true && !this.isHoleCard() && this.getLbl_cardName().getText().equals("curse")){
            this.getStyleClass().add("highlight2");
        }

        //wenn stacksize auf 0, wird highlighting ebenfalls deaktiviert
        if (croupier.getStackSize(gc) == 0) {
            this.getStyleClass().remove("highlight");
        }

        //update das STackSize infoLabel auf der Karte      
        if (this.stackSizeInfo != null){

            stackSizeInfo.updateStackSizeInfo();

        }


    }




    public void assignStackSizeInfo(){
        stackSizeInfo = new StackSizeInfo(gc,croupier.getStackSize(gc));
    }




    public void assignPicture(){
        if (this.holeCard == false)
            this.getStyleClass().addAll("card_mini",lbl_cardName.getText());
        else 
            this.getStyleClass().addAll("card",lbl_cardName.getText()+"_big");
    }




    public boolean isHoleCard() {
        return holeCard;
    }

    public void setHoleCard(boolean holeCard) {
        this.holeCard = holeCard;
    }

    public Label getLbl_cardName() {
        return lbl_cardName;
    }

    public String getText_DE(){
        return this.text_DE;
    }

    public void setLbl_cardName(Label lbl_cardName) {
        this.lbl_cardName = lbl_cardName;
    }   
}
  1. 可能的代码片段:这里我们正在更新GUI。每当我们从手牌上打牌时就会发生这种情况。我们将在另一个方法中首先从LinkedList(HoleCards)中删除它,然后我们调用updateGUI

    public void updateGUI(){

            // Zeichne holeCards Neu
            hb_wrapper_holeCards.getChildren().clear();
            for (int i = 0; i < croupier.getHoleCards().size(); i++) {
                GameCard gc1 = croupier.getHoleCards().get(i);
    
                try{
                    hb_wrapper_holeCards.getChildren().add(gc1);
                    gc1.setPrefSize(160, 260);
                    gc1.setMaxWidth(160);
                }catch (NullPointerException e){
                    //
                }
    
    
            // Zeichne Ablagekarte neu
            hb_wrapper_stapel.getChildren().clear();
            dummyCardAblagestapel.getStyleClass().clear();
            try {
                String cssSelector = new String(croupier.getAblagestapel().peekLast().getLbl_cardName().getText()+"_big");
    
                dummyCardAblagestapel.getStyleClass().addAll("card",cssSelector);
                hb_wrapper_stapel.getChildren().addAll(dummyCardAblagestapel,nachziehstapel);   
            } catch(Exception e){
                hb_wrapper_stapel.getChildren().addAll(this.dummyCardAblagestapel,nachziehstapel);  
                }           
            }
    
        }
    
  2. note1:我猜它发生在我们突出显示卡片的第一个片段中。在玩家丢弃牌之后,他只剩下3张牌,我们将删除高亮显示。正好当他丢弃他的最后一张牌时,抛出异常(但正如我所说,我们可以在没有例外的情况下玩这种情况大约7-10次,但突然出现例外情况)

    note2:我已经在这两个代码片段上尝试使用Platform.runLater但它没有帮助

0 个答案:

没有答案