我的问题如下,
为了这个问题,我在一个新项目中重现了这个问题。
假设我有一个带有组合框的应用程序,那里可能有一个或多个项目。我希望当用户点击组合框中的某个项目时,会发现这样的事情。发生的情况。
我制作了以下代码:
CREATE PROCEDURE dbo.GenerateTable
(
@SourceTable VARCHAR(128),
@TargetTable VARCHAR(128)
)
AS
BEGIN
DECLARE @SQL NVARCHAR(4000) = N'
SELECT * INTO ' + QUOTENAME(@TargetTable) + '
FROM ' + QUOTENAME(@SourceTable) + '
-- any false returning condition will do
WHERE 1 = 0'
EXEC (@SQL)
END
GO
当应用程序启动并且第一次选择项目时,此方法有效。当组合框中有2个或更多项目时(当用户单击项目1,然后单击项目2,然后单击项目1时),这也适用。
但是我的问题是,当组合框中只有1个项目时,请说" item1"。然后用户重新打开组合框并点击" item1"再一次,它不会重做行动。
它只会打印该行" Item Clicked"当一个新的'单击项目。
我希望它能说清楚我遇到的问题是什么,如果没有请求澄清,我会在需要时给予。
提前致谢!
答案 0 :(得分:5)
组合框的功能是向用户显示可供选择的选项列表。当您使用意味着选择的控件时,您应该确保UI始终与所选的选项一致。如果这样做,那么当用户“重新选择”相同选项时(因为UI已经处于所需状态),“重复动作”是没有意义的。一种方法是在组合框的值上使用绑定或侦听器:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ComboBoxExample extends Application {
@Override
public void start(Stage primaryStage) {
ComboBox<Item> choices = new ComboBox<>();
for (int i = 1 ; i <=3 ; i++) {
choices.getItems().add(new Item("Choice "+i, "These are the details for choice "+i));
}
Label label = new Label();
choices.valueProperty().addListener((obs, oldItem, newItem) -> {
label.textProperty().unbind();
if (newItem == null) {
label.setText("");
} else {
label.textProperty().bind(newItem.detailsProperty());
}
});
BorderPane root = new BorderPane();
root.setCenter(label);
root.setTop(choices);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public class Item {
private final String name ;
private final StringProperty details = new SimpleStringProperty() ;
public Item(String name, String details) {
this.name = name ;
setDetails(details) ;
}
public String getName() {
return name ;
}
@Override
public String toString() {
return getName();
}
public final StringProperty detailsProperty() {
return this.details;
}
public final String getDetails() {
return this.detailsProperty().get();
}
public final void setDetails(final String details) {
this.detailsProperty().set(details);
}
}
public static void main(String[] args) {
launch(args);
}
}
在这种情况下,当用户“重新选择”相同的选项时,永远不需要重复动作,因为代码始终确保UI与所选择的内容一致(如果是,则无需执行任何操作用户选择已选择的选项。通过在显示详细信息的UI部分中使用绑定(在这种情况下只是一个简单的标签),我们可以确保,如果数据在外部发生变化,UI将保持最新状态。 (显然在实际应用中,这可能要复杂得多,但基本策略仍然完全相同。)
另一方面,如果用户选择相同的功能,则需要重复动作的功能更好地被视为向用户呈现一组“动作”。对此的适当控制包括菜单,带按钮的工具栏和MenuButton
s。
一组可重复动作的示例是:
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MenuButtonExample extends Application {
@Override
public void start(Stage primaryStage) {
MenuButton menuButton = new MenuButton("Items");
Label label = new Label();
Item[] items = new Item[3];
for (int i = 1 ; i <=3 ; i++) {
items[i-1] = new Item("Item "+i);
}
for (Item item : items) {
MenuItem menuItem = new MenuItem(item.getName());
menuItem.setOnAction(e -> item.setTimesChosen(item.getTimesChosen() + 1));
menuButton.getItems().add(menuItem);
}
label.textProperty().bind(Bindings.createStringBinding(() ->
Stream.of(items)
.map(item -> String.format("%s chosen %d times", item.getName(), item.getTimesChosen()))
.collect(Collectors.joining("\n")),
Stream.of(items)
.map(Item::timesChosenProperty)
.collect(Collectors.toList()).toArray(new IntegerProperty[0])));
BorderPane root = new BorderPane();
root.setCenter(label);
root.setTop(menuButton);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Item {
private final String name ;
private final IntegerProperty timesChosen = new SimpleIntegerProperty();
public Item(String name) {
this.name = name ;
}
public String getName() {
return name ;
}
@Override
public String toString() {
return getName();
}
public final IntegerProperty timesChosenProperty() {
return this.timesChosen;
}
public final int getTimesChosen() {
return this.timesChosenProperty().get();
}
public final void setTimesChosen(final int timesChosen) {
this.timesChosenProperty().set(timesChosen);
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:0)
这个想法是在ListView窗格上设置一个侦听器,该窗格在您单击ComboBox时出现。一旦将ComboBox首次加载到JavaFX场景中,便创建了ListView实例。因此,我们在ComboBox上添加了一个侦听器以检查它何时出现在场景中,然后通过“ lookup”方法获得ListView并向其添加侦听器。
private EventHandler<MouseEvent> cboxMouseEventHandler;
private void initComboBox() {
ComboBox<String> comboBox = new ComboBox<String>();
comboBox.getItems().add("Item 1");
comboBox.getItems().add("Item 2");
comboBox.getItems().add("Item 3");
comboBox.sceneProperty().addListener((a,oldScene,newScene) -> {
if(newScene == null || cboxMouseEventHandler != null)
return;
ListView<?> listView = (ListView<?>) comboBox.lookup(".list-view");
if(listView != null) {
cboxMouseEventHandler = (e) -> {
Platform.runLater(()-> {
String selectedValue = (String) listView.getSelectionModel().getSelectedItem();
if(selectedValue.equals("Item 1"))
System.out.println("Item 1 clicked");
});
}; // cboxMouseEventHandler
listView.addEventFilter(MouseEvent.MOUSE_PRESSED, cboxMouseEventHandler);
} // if
});
} // initComboBox