我正在尝试实施类似于剧院,电影院等席位选择以及他们的不同意见。
使用此代码:
int[] rowsColumns = getRowsNColumns(); // [0] = rows : [1] = columns
TableColumn [] tableColumns = new TableColumn[rowsColumns[1]];
Callback<TableColumn, TableCell> cellFactory =
new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn p) {
TableCell<MyObject,Boolean> cell = new DisponibilityCell();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler());
return cell;
}
};
for (int i = 0; i < rowsColumns[1]; i++) {
tableColumns[i] = new TableColumn<MyObject, Boolean>(String.valueOf(i+1));
tableColumns[i].setPrefWidth((table.getPrefWidth()-15)/rowsColumns[1]);
tableColumns[i].setCellValueFactory(new PropertyValueFactory<MyObject, Boolean>("disponibility"));
tableColumns[i].setCellFactory(cellFactory);
tableColumns[i].setSortable(false);
}
table.getColumns().addAll(tableColumns);
List<MyObject> list = new ArrayList<>();
for (int i = 0; i < rowsColumns[0]; i++) {
list.add(new MyObject(i,true));
}
table.getItems().addAll(list);
table.getSelectionModel().setCellSelectionEnabled(true);
我能够得到这个,这是我想要的视觉效果(没有样式)。
问题是它实际上是为第一列生成行,而另一个只是值的副本。
我认为我在理论上理解这一点,但不知道如何实际解决。如果我理解正确,它会考虑每一行的对象,并在所有列中显示对象属性(disponibility
),因为它们都使用相同的get。
我希望每个对象都由一个单元格表示,而不是一行。
所有行中的所有单元格都具有相同的属性,即座位的disponibility
,但每个单元格应该是一个独立的对象。
答案 0 :(得分:1)
TableView
的工作解决方案可能是这样的:
首先,我们需要在MyObject
中保存给定行的每一列的信息。为此,我们使用ObservableList
以及列的所有布尔属性:
class MyObject {
public MyObject(int tam, boolean disponibility){
cols = FXCollections.observableArrayList();
IntStream.range(0, tam).boxed()
.forEach(i->cols.add(new SimpleBooleanProperty(disponibility)));
}
private final ObservableList<BooleanProperty> cols;
public void setColDisponibility(int col, boolean disponibility){
cols.get(col).set(disponibility);
}
public boolean getColDisponibility(int col){
return cols.get(col).get();
}
public BooleanProperty colDisponibilityProperty(int col){
return cols.get(col);
}
}
现在,为简单起见,我们将基于DisponibilityCell
定义自定义单元格CheckBox
。通过调用setColDisponibility()
,此框中的监听器将帮助我们保持模型的同步。
class DisponibilityCell extends TableCell<MyObject, Boolean> {
private final CheckBox box = new CheckBox();
public DisponibilityCell(int col){
box.setOnAction(e -> {
getTableView().getItems().get(getIndex()).setColDisponibility(col, box.isSelected());
});
}
@Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if(item!=null && !empty){
box.setSelected(item);
setGraphic(box);
}
else {
setText(null);
setGraphic(null);
}
}
}
最后,我们可以创建表格。首先,我们提供所有数据,设置为每个单元格为真。然后我们创建列。对于每列,我们设置其id
以跟踪列数。我们提供基于colDisponibilityProperty(int col)
属性的单元格值工厂,以及基于DisponibilityCell
的单元工厂。
@Override
public void start(Stage primaryStage) {
TableView<MyObject> table = new TableView<>();
table.setPrefSize(800, 600);
int[] rowsColumns = new int[]{10,20}; // [0] = rows : [1] = columns
ObservableList<MyObject> list = FXCollections.observableArrayList();
for (int i = 0; i < rowsColumns[0]; i++) {
list.add(new MyObject(rowsColumns[1],true));
}
List<TableColumn<MyObject,Boolean>> tableColumns = new ArrayList<>(rowsColumns[1]);
IntStream.range(0, rowsColumns[1]).boxed().forEach(i-> {
TableColumn<MyObject,Boolean> tableColumn = new TableColumn<>(String.valueOf(i+1));
tableColumn.setId(String.valueOf(i));
tableColumn.setPrefWidth((table.getPrefWidth()-15)/rowsColumns[1]);
tableColumn.setCellValueFactory(param -> {
int col=Integer.parseInt(param.getTableColumn().getId());
return param.getValue().colDisponibilityProperty(col);
});
tableColumn.setCellFactory(param ->
new DisponibilityCell(Integer.parseInt(param.getId())));
tableColumn.setSortable(false);
tableColumns.add(tableColumn);
});
table.getColumns().addAll(tableColumns);
table.getItems().addAll(list);
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
Scene scene = new Scene(table, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
请注意,您可以随时访问更新的模型。例如,您可以根据某个按钮点击打印它:
button.setOnMouseClicked(e->{
table.getItems().forEach(r->{
IntStream.range(0, rowsColumns[1]).boxed()
.forEach(i->System.out.print(" "+(r.getColDisponibility(i)?1:0)));
System.out.println("");
});
});
答案 1 :(得分:0)
我不会使用TableView,它会强制将座位布局设置为严格的行/列布局。剧院或其他地方的座位大多不同。因此,我将根据剧院规范建立自己的座位布局,例如:
public class Seats extends Application {
String theater1 = "20x__16x\n.20x__16x\n__18x__14x\n.20x__16x\n20x__16x\n.20x__16x\n20x__16x\n";
String theater2 = "11x_10x_11x\n11x_10x_11x\n11x_10x_11x\n\n11x_10x_11x\n11x_10x_11x\n11x_10x_11x\n";
static class Seat extends Group {
Color freeColor = Color.rgb(30, 250, 40);
Color reservedColor = Color.rgb(170, 40, 40);
BooleanProperty iamReserved = new SimpleBooleanProperty(false);
int myNo;
public Seat(int no) {
myNo = no;
Circle pillow = new Circle(12);
pillow.setFill(freeColor);
pillow.setStrokeWidth(1);
pillow.setStroke(Color.rgb(30, 40, 40));
getChildren().add(pillow);
Text lable = new Text(""+no);
lable.setFont(lable.getFont().font(7));
lable.setTextAlignment(TextAlignment.CENTER);
lable.setTextOrigin(VPos.CENTER);
lable.setLayoutX(-lable.getLayoutBounds().getWidth()/2);
getChildren().add(lable);
iamReserved.addListener((e, o, n) -> {
pillow.setFill(n ? reservedColor : freeColor);
});
setOnMouseClicked(m -> {
iamReserved.set(!iamReserved.get());
});
}
static double width() { return 26; }
static double height() { return 36; }
}
Pane theater1(Pane pane, String theater) {
double x = 20;
double y = 40;
int no = 1;
for (String row : theater.split("\n")) {
int count = 0;
for (int c : row.toCharArray()) {
switch (c) {
case 'x':
while (count-- > 0) {
Seat seat = new Seat(no++);
seat.setLayoutX(x);
x+= Seat.width();
seat.setLayoutY(y);
pane.getChildren().add(seat);
}
count = 0;
break;
case '0': case '1': case '2': case '3': case '4': case '5': case'6': case '7': case '8': case '9':
count = 10*count + (c-'0');
break;
case '_':
x+= Seat.width();
break;
case '.':
x+= Seat.width()/2;
break;
default: System.out.println("Unknown char: '"+(char)c+"'");
}
}
y += Seat.height();
count = 0;
x = 20;
}
return pane;
}
LinkedList<Node> myPages = new LinkedList<Node>();
void addTab(String label, Region node) {
myPages.add(node);
node.setBackground(new Background(new BackgroundFill(Color.rgb(200, 170, 200), new CornerRadii(0), new Insets(0))));
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Background of Panes");
BorderPane border = new BorderPane();
Pagination pages = new Pagination();
Scene scene = new Scene(border,900,400,Color.WHITE);
primaryStage.setScene(scene);
addTab("1", theater1(new Pane(), theater1));
addTab("2", theater1(new Pane(), theater2));
pages.setPageCount(myPages.size());
pages.setPageFactory(no -> myPages.get(no));
border.setCenter(pages);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
}
产生免费布局,如:
和