【问题标题】:How do I reset a JavaFX ComboBox's scrollbar back to the top?如何将 JavaFX ComboBox 的滚动条重置回顶部?
【发布时间】:2020-01-12 14:03:52
【问题描述】:

我有一个 ComboBox,我填充了一个长的 ObservableList,因此它有一个滚动条。如果我进行选择,比如在 ComboBox 列表的底部,然后单击 CLEAR 按钮,我希望 ComboBox 没有选择并且滚动条重置到顶部。我似乎无法让滚动条回到顶部。谁能告诉我我做错了什么?

ComboBoxView.fxml:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="154.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="comboboxscroll.ComboBoxViewController">
   <children>
      <ComboBox fx:id="myCB" prefWidth="150.0" />
      <Button layoutX="51.0" layoutY="35.0" mnemonicParsing="false" onAction="#clearCB" text="CLEAR" />
   </children>
</AnchorPane>

ComboBoxViewController.java:

package comboboxscroll;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;

public class ComboBoxViewController implements Initializable
{
    @FXML
    private ComboBox<String> myCB;

    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
        ObservableList<String> myList = FXCollections.observableArrayList("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P");
        myCB.getItems().clear();
        myCB.setItems(myList);
    }

    @FXML
    private void clearCB(ActionEvent event)
    {
        myCB.getSelectionModel().clearSelection();

        // I thought this would position the scrollbar back to the top but it doesn't
        myCB.setValue(null);
    }
}

ComboBoxScroll.java:

package comboboxscroll;

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

public class ComboBoxScroll extends Application {

    @Override
    public void start(Stage stage) throws Exception
    {
        try
        {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("ComboBoxView.fxml"));
            Scene scene = new Scene((Parent) loader.load());
            stage.setScene(scene);
            stage.setTitle("ComboBox Scroll Test");
            stage.show();
        }
        catch (IOException ignored)
        {
        }
    }

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

【问题讨论】:

  • 顺便说一句:在设置新列表之前无需清除旧项目 - 如果这有所不同,则说明某处有问题(不一定在您的代码中,可能是错误 :)
  • @kleopatra 对于 TableView 是否也是如此?使用 TableView.getItems().addAll(ObservableList) 设置新列表之前不需要做清除?

标签: javafx combobox scrollbar


【解决方案1】:

ComboBox 本身没有用于滚动其列表的 api,但在弹出窗口中显示的 ListView 可以(尽管默认情况下,它不会将所选项目滚动到可见区域):基本上你必须像

listView.scrollTo(comboBox.getSelectionModel().getSelectedIndex())

这样做的一个好位置是comboBox 中的onShowing 处理程序——那时,listView 保证被实例化(在comboBox 的皮肤中完成)并且可访问(通过comboBoxSkin)。

一个小例子:

public class ComboBoxScroll extends Application {

    int count;
    private Parent createContent() {
        List<String> data = Stream.generate(() -> "item " + count++).limit(30).collect(toList());
        ComboBox<String> combo = new ComboBox<>(observableArrayList(data));

        // scroll just before the comboBox is showing
        combo.setOnShowing(e -> {
            // Beware: type of skin is an implementation detail!
            ListView list = (ListView) ((ComboBoxListViewSkin) combo.getSkin()).getPopupContent();
            list.scrollTo(Math.max(0, combo.getSelectionModel().getSelectedIndex()));
        });

        // to see the handler working initially
        combo.getSelectionModel().select(25);
        // a button to clear see the handler working on clearing selection
        Button clear = new Button("clear selection");
        clear.setOnAction(e -> combo.getSelectionModel().clearSelection());
        BorderPane content = new BorderPane(combo);
        content.setBottom(new HBox(10, clear));
        return content;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        //stage.setTitle(FXUtils.version());
        stage.show();
    }

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

【讨论】:

    【解决方案2】:

    不幸的是,JavaFX ComboBox 组件阻止您直接使用滚动条。您只能管理三个相关事件(onScrollonScrollStartedonScrollFinished),但在这里没有用处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-31
      • 2023-01-15
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      相关资源
      最近更新 更多