我在空闲时间学习 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 但没有得到它,对于想要照片的人来说,(想要的数据是用相同大小的数据创建的,理想情况下按钮放置不依赖于数据长度)
最佳答案
在单个 HBox
中使用 Region
作为间隔填充符
[警告:我不是 JavaFX 专家。]
我问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 ( );
}
}
还有屏幕截图。
我可能不认为这个解决方案是完整的。如果用户缩小窗口的宽度,按钮就会从窗口的右边缘消失。理想情况下,按钮在窗口中始终保持可见,并且太长的标签会被截断。我不知道该问题的解决方案。
将域对象绑定(bind)到您的操作按钮
also eventually I will need to figure out how to send the element the button is aligned with into the function for when the button is pressed if anyone has tips for that
将每个域对象绑定(bind)到按钮是小部件布局的正交问题。因此,您应该就该特定问题撰写一个单独的问题。
但简单来说......
请注意,您的 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 ( ) );
} );
顺便说一句,尤其是在学习时,而且通常更普遍的是,您可能会发现扩展 lambda 中的参数类型很方便。这样做有助于您清楚地了解每个点上到底有哪些对象在起作用。
所以这个:
editButton.setOnAction ( ( ActionEvent actionEvent ) -> …
...而不是这个:
editButton.setOnAction ( actionEvent -> …
关于java - HBox 内的左对齐按钮(如果重要的话,在 pagnition 内),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77298240/