我一直在空闲时间学习JavaFX,我觉得一个简单的日程安排应用程序会是一个很好的实践.我目前的目标是输出ArrayList的所有成员,并且每个成员都有按钮,允许将任务标记为已完成,或编辑任务.然而,我正在为按钮放置而苦苦挣扎,我有一个包含一个标签和两个按钮的HBox,我可以将它们隔开,但由于任务是不同大小的字符串,我无法使按钮彼此对齐.有没有办法让他们的位置在左边,而不是在绳子后面的右边?

以下是我当前的代码:

@FXML
public Node createPage(int pageIndex){
    ListView<Event> eventView = new ListView<>();
    int fromIndex = pageIndex * maxPerPage;
    int toIndex = Math.min(fromIndex + maxPerPage, schedule.size());
    List<Event> eventString = schedule.subList(fromIndex, toIndex);
    //testing buttons
    eventView.setCellFactory(param -> new ListCell<Event>(){
        @Override
        protected void updateItem(Event item, boolean empty){
            super.updateItem(item,empty);
            if(empty || item == null){
                setText(null);
                setGraphic(null);
            } else{
                Label label = new Label(item.display());

                Button editButton = new Button ("Edit");

                Button completedButton = new Button ("Completed");

                editButton.setOnAction(event ->{
                    System.out.println("done");
                });

                completedButton.setOnAction(event ->{
                    System.out.println("done");
                });

                HBox eventHbox = new HBox(label);

                HBox buttonHbox = new HBox(editButton,completedButton);

                buttonHbox.setSpacing(50);

                buttonHbox.setAlignment(Pos.CENTER_RIGHT);

                HBox.setMargin(buttonHbox,new Insets(0,0,0,200));

                HBox hbox = new HBox(eventHbox,buttonHbox);

                setGraphic(hbox);
            }
        }

    });
}

另外,最终我需要弄清楚如何将按钮与之对齐的元素发送到函数中,以便在按钮被按下时使用,如果有人对此有提示的话

我试过用BASELINE_RIGHT代替CENTER_RIGHT,如果我再改变setMargin()的传球方式,或者改成Max之类的,我就会滚动查看

编辑:: 试图弄清楚TableView,但没有得到它,对于想要照片的人来说,(想要拥有的数据都是用相同大小的数据创建的,理想情况下按钮放置不依赖于数据长度)

here is what I currently have:currently have

and here is what I want to have want to have

推荐答案

Use Region as a spacer-filler in a single HBox

[警告:我不是Java FX方面的专家.]

我问了a similar Question个,更狭隘地关注于一种只使用一个HBox而不是嵌套多个HBox对象来完成标签按钮-按钮布局的方法.

Answer there by makki saud alghamdi至少为您提供了部分可能的解决方案.答案是使用Region对象作为标签和按钮之间的空间,以填补空白,有效地将按钮向右推.

代码的关键行是:

// Mind the gap between label and buttons.
Region spacer = new Region ( );
HBox.setHgrow ( spacer , Priority.ALWAYS );

HBox rowBox = new HBox ( label , spacer , editButton , completedButton );

下面是一个完整的示例应用程序.

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class HelloApplication  extends Application
{
    @Override
    public void start ( Stage stage ) throws IOException
    {
        record Event( String title , LocalDate when ) { }
        ObservableList < Event > events =
                FXCollections.observableList (
                        List.of (
                                new Event ( "A bit of text" , LocalDate.now ( ) ) ,
                                new Event ( "Even more text than that." , LocalDate.now ( ).plusDays ( 1 ) ) ,
                                new Event ( "Lots and lots and lots of text for a very long line." , LocalDate.now ( ).plusDays ( 2 ) )
                        )
                );
        ListView < Event > eventView = new ListView <> ( events );
        eventView.setCellFactory ( ( ListView < Event > listView ) -> new ListCell < Event > ( )
        {
            Button editButton = new Button ( "Edit" );
            Button completedButton = new Button ( "Completed" );
            Label label = new Label (  );
            Label labelTwo = new Label( );
            Region spacer = new Region ( );
            VBox vBox = new VBox(label, labelTwo);
            HBox rowBox = new HBox ( vBox , spacer , editButton , completedButton );            
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd");
            {
                // Mind the gap between label and buttons.
                HBox.setHgrow ( spacer , Priority.ALWAYS );
                rowBox.setAlignment ( Pos.CENTER );
                rowBox.setSpacing ( 7 );
            }
                   
            
            @Override
            protected void updateItem ( Event item , boolean empty )
            {
                super.updateItem ( item , empty );
                if ( empty || item == null )
                {
                    setText ( null );
                    setGraphic ( null );
                } 
                else
                {                   
                    label.setText(item.title());
                    labelTwo.setText("\tDue: " + item.when().format(dateTimeFormatter));
                    editButton.setOnAction ( actionEvent ->
                    {                        
                        System.out.println ( "DEBUG - Edit the Event: " + item.title() );
                    });
                    completedButton.setOnAction ( actionEvent ->
                    {
                        System.out.println ( "DEBUG - Completed the Event: " + item.title());
                    });
                    
                    setGraphic ( rowBox );
                }
            }
        } );

        BorderPane pane = new BorderPane ( );
        pane.setCenter ( eventView );

        Scene scene = new Scene ( pane , 700 , 300 );
        stage.setScene ( scene );
        stage.setTitle ( "Schedule Example" );
        stage.show ( );
    }

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

还有一张截图.

Screenshot of example app with a ListView showing buttons pushed to the right

我可能不会认为这个解决方案是完整的.如果用户缩小窗口的宽度,按钮将从窗口的右边缘消失.理想情况下,按钮在窗口内始终可见,过长的标签将被截断.我不知道那个问题的解决方案.

将域对象绑定到操作按钮

另外,最终我需要弄清楚如何将按钮与之对齐的元素发送到函数中,以便在按钮被按下时使用,如果有人对此有提示的话

将每个域对象绑定到按钮是一个与小部件布局相关的问题.因此,你应该就那个特定的问题单独提出一个问题.

但简单地说,…

请注意,向您的cell factory传递了对该项目的引用,该项目是您的Event类的对象,将由ListView显示.在这一行中:

protected void updateItem ( Event item , boolean empty ) … 

…第一个参数Event item是关键.请注意,在实例化每个Label时,我如何在对item.toString的调用中使用该引用.

Label label = new Label ( item.toString ( ) );

我们也可以在您的按钮操作处理程序中添加类似的调用.

Button editButton = new Button ( "Edit" );
Button completedButton = new Button ( "Completed" );
editButton.setOnAction ( ( ActionEvent actionEvent ) ->
{
    System.out.println ( "DEBUG - Edit the Event: " + item.toString ( ) );
} );
completedButton.setOnAction ( ( ActionEvent actionEvent ) ->
{
    System.out.println ( "DEBUG - Completed the Event: " + item.toString ( ) );
} );

顺便说一句,尤其是在学习的过程中,您可能会发现扩展lambdas中的参数类型很方便.这样做有助于让你的头脑保持清醒,准确地知道在每一个点上都有哪些物体在发挥作用.

所以这就是:

editButton.setOnAction ( ( ActionEvent actionEvent ) -> …

…而不是这样:

editButton.setOnAction ( actionEvent -> …

Java相关问答推荐

Java 22模式匹配不适用于记录模式匹配.给出汇编问题

如何在Docker容器中使用wireock—Webhooks阻止请求?

Springdoc Whitelabel Error Page with Spring V3

确定Java中Math.Ranb()输出的上限

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

对某一Hyroby控制器禁用@cacheable

如何才能使我的程序不会要求两次输入?

JPanel透支重叠的JComcoBox

Java流传输一个列表并创建单个对象

把一条整型短裤和两条短裤装成一条长的

使用Room Database删除Jetpack合成中的所有项目后,UI未重新合成

我的Spring Boot测试显示&IlLegalStateException:无法加载某事的ApplicationContext.

扩展视图高度,并将其拖动到较低的视图上,而不是将其向下推?

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

将双倍转换为百分比

向Java进程发送`kill-11`会引发NullPointerException吗?

Oracle中从JSON中提取和插入数据

JPA无手术同品种器械可能吗?

OAuth:登录后无法查看Google邮箱地址

语句打印在错误的行(Java Token 问题)