如何在JavaFX中缩放ListView中的标签

如何在JavaFX中缩放ListView中的标签,java,listview,javafx,layout,scroll,Java,Listview,Javafx,Layout,Scroll,我有一个带有一些标签的列表视图。标签的width属性绑定到ListView的width属性,但它们似乎稍大一些,这意味着列表视图上会显示一个水平滚动条。我想要的是将标签放在列表视图中,而不在底部使用滚动条。我已经查看了标签和列表视图上的各种填充和插入值,但没有发现一个是罪魁祸首(大多数为零) 下面是一个例子来说明这个问题 import javafx.application.Application; import javafx.scene.Node; import javafx.scene.Sc

我有一个带有一些标签的列表视图。标签的width属性绑定到ListView的width属性,但它们似乎稍大一些,这意味着列表视图上会显示一个水平滚动条。我想要的是将标签放在列表视图中,而不在底部使用滚动条。我已经查看了标签和列表视图上的各种填充和插入值,但没有发现一个是罪魁祸首(大多数为零)

下面是一个例子来说明这个问题

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.stage.Stage;

public class ListViewScrollExample extends Application {

   private ListView<Node> listView;

   @Override
   public void start(Stage stage) throws Exception {
       listView = new ListView<>();
       addItem("Some quite long string to demonstrate the problem");

       Scene scene = new Scene(listView);
       stage.setScene(scene);
       stage.show();
    }

    public void addItem(String item) {
        Label label = new Label(item);
        label.setWrapText(true);
        label.maxWidthProperty().bind(listView.widthProperty());
        listView.getItems().add(label);
    }

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

}
导入javafx.application.application;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.control.ListView;
导入javafx.stage.stage;
公共类ListViewScroll示例扩展了应用程序{
私有列表视图列表视图;
@凌驾
public void start(Stage)引发异常{
listView=新建listView();
addItem(“一些相当长的字符串来演示问题”);
场景=新场景(listView);
舞台场景;
stage.show();
}
公共无效附加项(字符串项){
标签=新标签(项目);
label.setWrapText(true);
label.maxWidthProperty().bind(listView.widthProperty());
listView.getItems().add(标签);
}
公共静态void main(字符串[]args){
应用程序启动(args);
}
}

我无法复制该问题,但您可以尝试以下操作,而不是
label.maxWidthProperty().bind(listView.widthProperty())

您可以将2.0更改为更改屏幕所需的任何像素计数。

将填充添加到
列表单元格中(当前版本中的第2316行):

.list单元格{
-外汇填充:0.25em 0.583em 0.25em 0.583em;/*3 7*/
}
使用
节点
实例作为
列表视图
的数据支持通常是个坏主意:在本例中,您应该使用
字符串
,并使用单元格工厂创建一个标签,显示根据需要配置的字符串。以下内容似乎适用于您的示例:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.stage.Stage;

public class ListViewScrollExample extends Application {

   private ListView<String> listView;

   @Override
   public void start(Stage stage) throws Exception {
       listView = new ListView<>();
       listView.getItems().add("Some quite long string to demonstrate the problem");

       listView.setCellFactory(lv -> {
           ListCell<String> cell = new ListCell<String>() {

               private Label label = new Label();
               {
                   label.setWrapText(true);
                   label.maxWidthProperty().bind(Bindings.createDoubleBinding(
                           () -> getWidth() - getPadding().getLeft() - getPadding().getRight() - 1, 
                           widthProperty(), paddingProperty()));
                   setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
               }

               @Override
               protected void updateItem(String item, boolean empty) {
                   super.updateItem(item, empty);
                   if (empty) {
                       setGraphic(null);
                   } else {
                       label.setText(item);
                       setGraphic(label);
                   }
               }
           };
           return cell ;
       });

       Scene scene = new Scene(listView);
       stage.setScene(scene);
       stage.show();
    }


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

}
导入javafx.application.application;
导入javafx.beans.binding.Bindings;
导入javafx.scene.scene;
导入javafx.scene.control.ContentDisplay;
导入javafx.scene.control.Label;
导入javafx.scene.control.ListCell;
导入javafx.scene.control.ListView;
导入javafx.stage.stage;
公共类ListViewScroll示例扩展了应用程序{
私有列表视图列表视图;
@凌驾
public void start(Stage)引发异常{
listView=新建listView();
添加(“一些很长的字符串来演示问题”);
listView.setCellFactory(lv->{
ListCell=新ListCell(){
私有标签=新标签();
{
label.setWrapText(true);
label.maxWidthProperty().bind(Bindings.createDoubleBinding(
()->getWidth()-getPadding().getLeft()-getPadding().getRight()-1,
widthProperty(),paddingProperty());
setContentDisplay(仅限ContentDisplay.GRAPHIC_);
}
@凌驾
受保护的void updateItem(字符串项,布尔值为空){
super.updateItem(项,空);
if(空){
设置图形(空);
}否则{
label.setText(项目);
设置图形(标签);
}
}
};
返回单元;
});
场景=新场景(listView);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
应用程序启动(args);
}
}

在这里,我创建了一个列表单元格,将标签显示为其图形,标签文本设置为要显示的字符串。单元格的构造函数将标签的最大宽度绑定到单元格的宽度,减去填充所需的任何空间。调用
setContentDisplay(仅限ContentDisplay.GRAPHIC_)
似乎是必要的,因此单元格不会尝试为文本分配任何空间


可以通过直接在列表单元格上设置文本并在单元格上调用
setWrapText(true)
来实现这一点(毕竟,它也是标记为
的子类),但我无法让它以这种方式工作。

如果允许对文本进行包装,您希望如何计算宽度?我可以缩小列表视图,直到标签每行显示一个单词。@user1803551问题是滚动条出现在列表视图的底部。包装工作正如我所期望的,但标签区域似乎延伸到了一边,即使文本本身没有那么你想删除滚动条?我试图避免使用硬编码常量来缩小标签大小。还有,为什么您使用Double.parseDouble(listView.widthProperty().toString())而不是listView.widthProperty().get()?没有真正的理由使用Double.parse来代替它,但这是我首先想到的,很长一段路。您可以尝试
label.setMaxWidth(listView.getPrefWidth())取而代之。所有这些都应该做相同的事情,但值可能略有不同。如果要使用硬编码的量来缩小它,只需使用相同的绑定方法:
label.maxWidthProperty().bind(listView.widthProperty().subtract(2.0))
另外,
Double.parseDouble(listView.widthProperty().toString())
甚至不起作用:属性的
toString()
方法返回类似于
“ReadOnlyDoubleProperty[bean:ListView@27e7a3d1[styleClass=root列表视图],name:width,value:248.0]“
,这显然不能解析为double。这很有效,谢谢我不知道该如何使用这种方法,但我确实发现绑定中的负1和对setContentDisplay的调用(Con
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.stage.Stage;

public class ListViewScrollExample extends Application {

   private ListView<String> listView;

   @Override
   public void start(Stage stage) throws Exception {
       listView = new ListView<>();
       listView.getItems().add("Some quite long string to demonstrate the problem");

       listView.setCellFactory(lv -> {
           ListCell<String> cell = new ListCell<String>() {

               private Label label = new Label();
               {
                   label.setWrapText(true);
                   label.maxWidthProperty().bind(Bindings.createDoubleBinding(
                           () -> getWidth() - getPadding().getLeft() - getPadding().getRight() - 1, 
                           widthProperty(), paddingProperty()));
                   setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
               }

               @Override
               protected void updateItem(String item, boolean empty) {
                   super.updateItem(item, empty);
                   if (empty) {
                       setGraphic(null);
                   } else {
                       label.setText(item);
                       setGraphic(label);
                   }
               }
           };
           return cell ;
       });

       Scene scene = new Scene(listView);
       stage.setScene(scene);
       stage.show();
    }


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

}