编辑直通Button时,JavaFX TableView的行为很奇怪

时间:2018-06-08 18:30:46

标签: java javafx tableview

我有一个可以通过按钮编辑的TableView。按钮按下阶段确认和其他数据弹出。问题通常是在收集和/或确认所有数据(例如删除行或创建新行)之后,TableView会显示双倍甚至三倍的数据条目。附在下面。这些行无法单击。不要得到一个焦点。我的操作系统是Ubuntu 16.04,我的IDE是Netbeans 8.2。

   package basicShit;

import allg.ObjectFilePersistence;
import allg.StringFilePersistence;
import allg.TTADAOException;
import allg.ThinxToAdminDAO;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.Pair;

import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;
import java.util.function.Consumer;

public class Director extends Application
{

    private static ThinxToAdminDAO<Project> projectMGMT;

    private static String log = "";

    private static File logFilesDir = new File("/home/storm/Projekte/LogFiles");

    private static final String CONTEXTFILENAME = "Contexte";
    private static File contextListDir = new File("/home/storm/Projekte/Contexte");
    private static String contexteFileEnd = "cntxt";

    private static final String NOTETYPEFILENAME = "NoteTyps";
    private static File noteListDir = new File("/home/storm/Projekte/NoteTyps");
    private static String noteTypsFileEnd = "typs";

    private static ButtonsTableAndTxtArea<ProjectTableViewModel> bTATA;

    private final static List<String> COLUMNNAMES = Arrays.asList
            ("Name", "Status", "Goal");
    private final static List<String> COLUMNACCESS = Arrays.asList
            ("name", "status", "goal");

    private static Set<String> contextChoice;
    private static Set<String> noteListTyps;

    private final Button btnCreate = new Button("Create");
    private final Button btnSave = new Button("Save");
    private final Button btnReadAndUpdate = new Button("Read/Update");
    private final Button btnDelete = new Button("Delete");
    private final Button btnSetDataDir = new Button("Set Data Dir");
    private final Button btnStats = new Button("Statistics");
    private final Button btnVSG = new Button("View Step Group");


    public static <S> void logIt(Pair<S, String> p)
    {
        String l = p.getValue() + " " + getNowTimeString();
        log= log + "\n" + l;
        System.out.println(l);
    }

    public static String getTimeString(LocalDateTime ldt)
    {

        ZonedDateTime nowWithTimeZone = ZonedDateTime.of
                (ldt, ZoneId.of("Europe/Berlin"));
        DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime
                (FormatStyle.FULL);
        return dtf.format(nowWithTimeZone);
    }

    public static String getNowTimeString()
    {
        return getTimeString(LocalDateTime.now());
    }

    public static Consumer<String> alertWindow = (s)->
    {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setHeaderText("Error");
        alert.setContentText(s);
        alert.setResizable(true);
        alert.getDialogPane().setPrefWidth(s.length()*7+10);
        alert.showAndWait();
    };

    public static boolean confirm(String question)
    {

        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setHeaderText("Confirmation");
        alert.setContentText(question);
        Optional<ButtonType> result = alert.showAndWait();

        return (result.get().equals(ButtonType.OK));
    }

    private List<Button> getBtns()
    {

        List<Button> btnList = new ArrayList<>();

        final EventHandler<ActionEvent> eHCreate = (event)->
        {
            Pair<Project, String> p = create();
            if (p.getKey() != null)
            {
                try
                {
                    projectMGMT.add(p.getKey());
                    writeToTable(p.getKey());
                    logIt(p);
                }
                catch(TTADAOException e)
                {
                    System.out.println("Couldnt register Project!");
                }
            }
        };
        btnCreate.setOnAction(eHCreate);
        btnList.add(btnCreate);

        final EventHandler<ActionEvent> eHSave = (event)->
        {

            Pair<String, String> p;
            try
            {
                p = save();
                logIt(p);
            }
            catch(TTADAOException e)
            {
                System.out.println("Couldnt save it(All).");
            }
        };
        btnSave.setOnAction(eHSave);
        btnList.add(btnSave);

        final EventHandler<ActionEvent>eHReadUpdate = (event)->
        {

            try
            {

                Project project =
                        projectMGMT.getThingByName(detectSelection().getName());
                Pair<Stage, String> p = details(project);
                logIt(p);
                p.getKey().showAndWait();
                bTATA.getObservableList().clear();
                fillTable();
            }
            catch(TTADAOException e)
            {
                System.out.println("There is no Details.");
                alertWindow.accept("Select Properly");
            }

        };
        btnReadAndUpdate.setOnAction(eHReadUpdate);
        btnList.add(btnReadAndUpdate);

        final EventHandler<ActionEvent> eHDelete = (event)->
        {

            Pair<ProjectTableViewModel, String> p = delete();
            try
            {
                if (p.getKey() != null)
                {
                    projectMGMT.removeByName(p.getKey().getName());
                    bTATA.getObservableList().remove(p.getKey());
                    logIt(p);
                }
            }
            catch(TTADAOException e)
            {
                System.out.println("Deleting went Wrong");
            }
        };
        btnDelete.setOnAction(eHDelete);
        btnList.add(btnDelete);

        final EventHandler<ActionEvent> eHSetDataDir = (event)->
        {

            Pair<File, String> p = setDataDir();

            ProjectMGMT pm = (ProjectMGMT)projectMGMT;
            pm.setStandartDir(p.getKey());
            logIt(p);
        };


        btnSetDataDir.setOnAction(eHSetDataDir);
        btnList.add(btnSetDataDir);

        btnStats.setOnAction(statistics);
        btnList.add(btnStats);

        btnVSG.setOnAction(viewStepGroup);
        btnList.add(btnVSG);

        return btnList;
    }

    public static void main(String... args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception
    {

        TextArea info = new TextArea();
        info.setEditable(false);
        info.setStyle("-fx-highlight-fill: lightgray; -fx-highlight-text-fill: firebrick; -fx-font-size: 12px;");
        info.setWrapText(true);

        primaryStage = new
                ButtonsTableAndTxtArea<>
                ("Got it All", getBtns(), COLUMNNAMES, COLUMNACCESS, info);
        projectMGMT = new ProjectMGMT();

        ObjectFilePersistence<Set<String>> ofp = new ObjectFilePersistence<>();
        contextChoice = ofp.loadObject(CONTEXTFILENAME,contextListDir.toString(),contexteFileEnd);

        noteListTyps = ofp.loadObject(NOTETYPEFILENAME,noteListDir.toString(),noteTypsFileEnd);


        bTATA = (ButtonsTableAndTxtArea)primaryStage;

        bTATA.getTableView().setOnMouseClicked(clickOnTable);

        projectMGMT.loadData();
        fillTable();

        InputSpawns.initialize();

        initializeTypsAndChoices();
        InputSpawns.upDateContexte(contextChoice);
        InputSpawns.upDateNoteTitels(noteListTyps);

        btnBindings();//Must be done after bTATA is ready

        primaryStage.show();
    }

    public void btnBindings()
    {

        //Thru the bind these Buttons are only available when
        //a Row in the TableView is selected!!!
        btnReadAndUpdate.disableProperty().bind(bTATA.getTableView().getSelectionModel().selectedItemProperty().isNull());

        btnDelete.disableProperty().bind(bTATA.getTableView().getSelectionModel().selectedItemProperty().isNull());
    }

    public static void initializeTypsAndChoices()
    {
        noteListTyps = new HashSet<>();
        noteListTyps.addAll(ProjectNote.typs);

        contextChoice = new HashSet<>();
        contextChoice.addAll(Step.contextChoice);
    }

    private static void writeToTable(Project project)
    {

        String name = project.getName();
        String status = project.getLastNxtStp().getStatus();
        String goal = project.getGoal();

        ProjectTableViewModel pTVM = new ProjectTableViewModel(name, status, goal);
        bTATA.getObservableList().add(pTVM);
    }

    public static Pair<String, String> save() throws TTADAOException
    {

        projectMGMT.saveData();        
        return new Pair(null, "All Saved");
    }

    public static ProjectTableViewModel detectSelection()
    {
        return bTATA.getTableView().getSelectionModel().getSelectedItem();
    }

    public Pair<Stage, String> details(Project project)
    {

        Stage stage = new DetailStage(project, log);
        String s =  "Detail Stage opened for Project "+project.getName()+".";
        return new Pair(stage, s);
    }

    public static Pair<ProjectTableViewModel, String> delete()
    {


        ProjectTableViewModel pTVM = detectSelection();
        if(pTVM!=null)
        {

            String name = pTVM.getName();
            boolean q = confirm("Are you sure u want to delete Project "+name+" ??");

            if(q)return new Pair(pTVM, "Project: "+name+" deleted.");
            else return new Pair(null, "Project Deletion aborted.");
        }
        else return new Pair(null, "Didnt choose a Project to Delete.");
    }

    public EventHandler<ActionEvent> viewStepGroup = (event)->
    {


    };

    public Pair<File, String> setDataDir()
    {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        directoryChooser.setTitle("Choose Data Directory");
        directoryChooser.setInitialDirectory(new File("/home"));
        File file = directoryChooser.showDialog(null);//Owner Window is null
        Pair<File, String> re;
        String s;
        if(file==null)s="Data Dir Not Changed!";
        else s="Data Dir set to: "+file.getAbsolutePath();
        return new Pair(file, s);
    }

    public EventHandler<ActionEvent> statistics = (event)->
    {

    };

    public EventHandler<MouseEvent> clickOnTable = (event)->
    {

        ProjectTableViewModel pTVM = detectSelection();
        String prjctName="";

        if(pTVM!=null)
        {
            try
            {

                //Todo: Make it colored Text txt = new Text();
                prjctName = pTVM.getName();
                bTATA.setInfoText(projectMGMT.getThingByName(prjctName).toString());
            }
            catch (TTADAOException e)
            {
                System.out.println("Couldnt get a Project with name "+prjctName+".");
            }
        }
    };

    public static Pair<Project,String> create()
    {

        Optional<Project> project = InputSpawns.projectSpawn();

        if(project.isPresent())
        {
            return new Pair(project.get(), "Project: "+project.get().getName()+" created.");
        }
        else
        {
            System.out.println("Project creation failed.");
            return new Pair(null, "Project creation failed.");
        }
    }

    public void fillTable()
    {

        projectMGMT.getThingNames().forEach((name) -> {
            try
            {
                Project p = projectMGMT.getThingByName(name);
                writeToTable(p);
            }
            catch(TTADAOException e)
            {
                System.out.println("Couldnt get A Project with name "+name+".");
            }
        });
    }

    @Override
    public void stop() 
    {
        try
        {
            Pair<String, String> p = save();
            logIt(p);
        }
        catch(TTADAOException e)
        {
            System.out.println("Couldnt save it(All).");
        }

        String t = getNowTimeString();
        StringFilePersistence.saveString("Log File Project Action" + t, logFilesDir.toString(), log);
        ObjectFilePersistence<Set<String>> ofp = new ObjectFilePersistence<>();
        ofp.saveObject(CONTEXTFILENAME,contextListDir.toString(),contexteFileEnd,contextChoice);
        ofp.saveObject(NOTETYPEFILENAME,noteListDir.toString(),"typs",noteListTyps);
    }
}

我也使用这种方法:

   public static <M> TableView<M> tableSetup(ObservableList<M> data, List<String> columns, List<String> columnAccess, int[] columnWidth)
    {

        TableView<M> tv = new TableView<>();

        int n = columns.size();
        int widthSum = 0;

        TableColumn<M,String>[] tColumns = new TableColumn[n];
        for(int i=0;i<n;i++)
        {
            tColumns[i] = new TableColumn<M, String>(columns.get(i));
            final int width = columnWidth[i];
            tColumns[i].setPrefWidth(columnWidth[i]);

            tColumns[i].setCellValueFactory(new PropertyValueFactory<>(columnAccess.get(i)));
            widthSum = widthSum+ columnWidth[i];
            tv.getColumns().add(tColumns[i]);
            tColumns[i].setCellFactory(column->
            {
                return new TableCell<M, String>()
                {
                    @Override
                    protected void updateItem(String item, boolean empty)
                    {
                        super.updateItem(item, empty);

                        if (item == null || empty)
                        {
                            setText(null);
                            setStyle("");
                        }
                        else
                        {
                            Text txt = new Text(item);
                            txt.setWrappingWidth(width-7);
                            setGraphic(txt);
                        }
                    }

                };
            });
        }

        tv.setPrefWidth(widthSum);
        tv.setItems(data);
        return tv;
    }

thanx我期待着学到新的东西。 关于xylo。

1 个答案:

答案 0 :(得分:1)

您使用TextField graphic作为TableCell来显示内容,但您将Text属性设置为null。这样,graphic永远不会被删除。你需要这样做,因为单元格可能变空了:

tColumns[i].setCellFactory(column ->  new TableCell<M, String>() {
    private final Text txt = new Text();

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        if (item == null || empty){
            setGraphic(null);
        } else {
            txt.setText(item);
            txt.setWrappingWidth(width-7);
            setGraphic(txt);
        }
    }

});