2016-04-17 3 views
4

左の列:デフォルトで選択されている行を選択または選択解除するためのチェックボックス。右列:行までの選択行の量を表す文字列。行内のチェックボックスの選択を解除すると、下の行の値が変更されます。JavaFX TableViewでこのビジュアルグリッチを解決するにはどうすればよいですか?

バグ:表の一番下までスクロールします。招待コード74の行のチェックボックスの選択を解除します。もう一度選択します。最後の3つの招待コードは、73,74、および75を再度読み取る必要があります。しかし、かなり頻繁に73,73,74、または73,74,74を表示します。

バグは必ずしも発生しません!それが発生しない場合は、テーブルのスクロールバーで上下にスクロールして上の手順を繰り返すと、それが発生する可能性があります。

これは視覚的にしか見えないようです - ObservableListの内容をコンソールにダンプして、正しい値を表示するようにしました。この視覚的な不具合以外、私のアプリは正しく動作します。ウィンドウ内の他のコントロール(たとえば、表のスクロールバー)をクリックすると、表内の招待コードが正しい値にフリップされます。私のデスクトップ上の別のワークスペースに切り替えて戻ってくると、正しい値も表示されます。

Small imageは、左側にObservableListのコンソールダンプ、右側にはバグのあるテーブルを示しています。

質問:非常に論理的に: どうすればこのバグをスクワッシュできますか?

EDIT:Kleopatraが勧告したように、より多くのコードを投げ捨てました。ありがとう!

MCV:

FXMLDocumentController.java

package invcodebug; 

import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.CheckBoxTableCell; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.util.Callback; 

public class FXMLDocumentController implements Initializable { 
    @FXML private TableView<Person> personTable; 
    @FXML private TableColumn<Person, Boolean> invitedCol; 
    @FXML private TableColumn<Person, String> inviteCodeCol; 
    private final ObservableList<Person> persons 
      = FXCollections.observableArrayList(); 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     initPersonTable(); 
     populatePersons(); 
    } 

    private void initPersonTable() { 
     invitedCol.setCellValueFactory(new PropertyValueFactory<>("invited")); 
     inviteCodeCol.setCellValueFactory(new PropertyValueFactory<>("inviteCode")); 

     invitedCol.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() { 
      @Override 
      public ObservableValue<Boolean> call(Integer param) { 
       doInvCode(); 

// SHOWS: underlying ObservableList has correct values 
System.out.println("--------------------------"); 
for (Person p : persons) { 
    System.out.println(p.isInvited() + " " + p.getInviteCode() 
    ); 
} 
       return persons.get(param).invitedProperty(); 
      } 
     })); 

     personTable.setItems(persons); 
    } 

    private void doInvCode() { 
     int invCounter = 1; 
     for (Person p : persons) { 
      if (p.isInvited()) { 
       p.setInviteCode(((Integer) invCounter).toString()); 
       invCounter++; 
      } else p.setInviteCode(""); 
     } 
    } 

    private void populatePersons() { 
     for (int i = 0; i < 75; i++) { 
      persons.add(new Person(true, "")); 
     } 
    } 
} 

Person.java

package invcodebug; 

import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleStringProperty; 

public class Person { 
    private final SimpleBooleanProperty invited; 
    private final SimpleStringProperty inviteCode; 

    public Person(boolean invited, String inviteCode) { 
     this.invited = new SimpleBooleanProperty(invited); 
     this.inviteCode = new SimpleStringProperty(inviteCode); 
    } 

    public boolean isInvited() { 
     return invited.get(); 
    } 
    public SimpleBooleanProperty invitedProperty() { 
     return invited; 
    } 

    public String getInviteCode(){ 
     return inviteCode.get(); 
    } 
    public void setInviteCode(String invCode) { 
     this.inviteCode.set(invCode); 
    } 
    public SimpleStringProperty inviteCodeProperty() { 
     return inviteCode; 
    } 
} 

FXMLDocument.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.layout.AnchorPane?> 

<AnchorPane id="AnchorPane" prefHeight="464.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="invcodebug.FXMLDocumentController"> 
    <children> 
     <TableView fx:id="personTable" editable="true" layoutX="26.0" layoutY="28.0" prefHeight="347.0" prefWidth="572.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="20.0"> 
      <columns> 
       <TableColumn fx:id="invitedCol" prefWidth="27.0" sortable="false" /> 
       <TableColumn fx:id="inviteCodeCol" editable="false" prefWidth="110.0" resizable="false" sortable="false" text="Invite Code" /> 
      </columns> 
     </TableView> 
    </children> 
</AnchorPane> 

InvCodeBug.java

package invcodebug; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class InvCodeBug extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); 
     Scene scene = new Scene(root); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

は私のバグのように見えます(セルが再利用されると、それは何らかのスクロールの後に起こります)。無関係:次回は、問題を示す最短の例を提供してください(スピナー、テキストフィールド、または名前列の編集がすべてスローされる可能性があります) – kleopatra

+0

@kleopatraバグはオラクルに報告され、質問は編集されました。あなたのアドバイスをありがとう! – Arjan

答えて

1

は、おそらく最も技術的な答えが、doInvCode()メソッドの最後にpersonTable.requestFocus();を使用して、テーブルを視覚的に更新して問題を解決するようされていません。

+0

良い回避策、ありがとう!その影響を最小限に抑えるため、コールバックで使用しました。 – Arjan

関連する問題