JavaFX(8)警报:不同的按钮大小
考虑一个带有两个按钮的JavaFX(8)警报对话框: 生成的对话框有两个按钮,两个按钮的宽度都相同,看起来很傻 是否有办法将两个按钮调整到实际文本长度?部分解决方案(不完全是文本长度,但您可以设置自己的大小):JavaFX(8)警报:不同的按钮大小,javafx,dialog,javafx-8,Javafx,Dialog,Javafx 8,考虑一个带有两个按钮的JavaFX(8)警报对话框: 生成的对话框有两个按钮,两个按钮的宽度都相同,看起来很傻 是否有办法将两个按钮调整到实际文本长度?部分解决方案(不完全是文本长度,但您可以设置自己的大小): 下面是自定义对话框的示例。一个纯代码和一个MCV 纯代码 模型控制器视图(更像控制器视图) Main import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Pa
下面是自定义对话框的示例。一个纯代码和一个MCV 纯代码 模型控制器视图(更像控制器视图) Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author blj0011
*/
public class JavaFXApplication8 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
控制器
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
/**
*
* @author blj0011
*/
public class FXMLDocumentController implements Initializable {
@FXML
private void handleButtonAction(ActionEvent event) {
showDialog((Node)event.getSource());
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
private Stage showDialog(Node sourceNode)//You can add String title and String headerText and String bodyText
{
Stage dialog = new Stage();
try
{
Parent rootDialog = FXMLLoader.load(getClass().getResource("test.fxml"));
dialog.setTitle("Title of Alert");
dialog.initOwner(sourceNode.getScene().getWindow());
dialog.initStyle(StageStyle.UTILITY);
dialog.setScene(new Scene(rootDialog));
ArrayList<Node> childrenNodes = getAllNodes(rootDialog);
Button yesButton = (Button)childrenNodes.stream().filter((node) -> (node instanceof Button && ((Button)node).getText().equals("Yes"))).collect(Collectors.toList()).get(0);//Find the yes button in the test fxml
Button noButton = (Button)childrenNodes.stream().filter((node) -> (node instanceof Button && ((Button)node).getText().contains("No"))).collect(Collectors.toList()).get(0);//Fin the no button in the test fxml
//Yes button event handler
yesButton.setOnAction((aEvent)->{
System.out.println("continue with restart!");
dialog.close();
});
//No button event handler
noButton.setOnAction((aEvent)->{
System.out.println("continue without restart!");
//code to restart
dialog.close();
});
dialog.show();
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
return dialog;
}
public static ArrayList<Node> getAllNodes(Parent root) {
ArrayList<Node> nodes = new ArrayList();
addAllDescendents(root, nodes);
return nodes;
}
private static void addAllDescendents(Parent parent, ArrayList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
nodes.add(node);
if (node instanceof Parent)
addAllDescendents((Parent)node, nodes);
}
}
}
import java.io.IOException;
导入java.net.URL;
导入java.util.ArrayList;
导入java.util.ResourceBundle;
导入java.util.stream.collector;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.fxmloader;
导入javafx.fxml.Initializable;
导入javafx.scene.Node;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.stage.stage;
导入javafx.stage.StageStyle;
/**
*
*@author blj0011
*/
公共类FXMLDocumentController实现可初始化{
@FXML
私有无效把手按钮操作(ActionEvent事件){
showDialog((节点)event.getSource());
}
@凌驾
公共void初始化(URL、ResourceBundle rb){
//待办事项
}
private Stage showDialog(Node sourceNode)//您可以添加字符串标题、字符串标题文本和字符串正文文本
{
阶段对话框=新阶段();
尝试
{
父rootDialog=FXMLLoader.load(getClass().getResource(“test.fxml”);
对话框.setTitle(“警报标题”);
initOwner(sourceNode.getScene().getWindow());
initStyle(StageStyle.UTILITY);
setScene(新场景(rootDialog));
ArrayList childrenNodes=getAllNodes(rootDialog);
Button yesButton=(Button)childrenNodes.stream().filter((node)->(Button和((Button)node的节点实例)。getText().equals((Yes)).Collector(Collectors.toList()).get(0);//在测试fxml中找到Yes按钮
Button noButton=(Button)childrenNodes.stream().filter((node)->(node instanceof Button&((Button)node.getText().contains(“No”)).collect(Collectors.toList()).get(0);//Fin测试fxml中的No按钮
//是按钮事件处理程序
yesButton.setOnAction((aEvent)->{
System.out.println(“继续重新启动!”);
dialog.close();
});
//无按钮事件处理程序
noButton.setOnAction((aEvent)->{
System.out.println(“继续而不重新启动!”);
//要重新启动的代码
dialog.close();
});
dialog.show();
}
捕获(IOEX异常)
{
System.out.println(例如toString());
}
返回对话框;
}
公共静态ArrayList getAllNodes(父根){
ArrayList节点=新的ArrayList();
addAllsubstants(根、节点);
返回节点;
}
私有静态void addallsubstants(父-父、ArrayList节点){
for(节点:parent.getChildrenUnmodifiable()){
nodes.add(node);
if(父节点的节点实例)
addAllSubstants((父)节点,个节点);
}
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication8.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="250.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox maxHeight="80.0" style="-fx-background-color: #E4E4E4;">
<children>
<StackPane prefWidth="300.0" style="-fx-background-color: #E4E4E4;">
<children>
<Label text="Header Text Goes Here!" StackPane.alignment="CENTER_LEFT">
<padding>
<Insets left="20.0" />
</padding>
<font>
<Font size="16.0" />
</font>
</Label>
</children>
</StackPane>
<ImageView fitHeight="80.0" fitWidth="80.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
<VBox maxHeight="170.0" style="-fx-background-color: #F8F8F8;">
<children>
<AnchorPane minHeight="130.0">
<children>
<Label alignment="TOP_LEFT" text="Body Text Goes Here!" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<padding>
<Insets left="20.0" top="15.0" />
</padding>
</Label>
</children>
</AnchorPane>
<HBox alignment="CENTER_RIGHT" spacing="10.0">
<children>
<Button mnemonicParsing="false" text="Yes" />
<Button mnemonicParsing="false" text="No, continue without restart" />
</children>
<padding>
<Insets bottom="10.0" right="20.0" />
</padding>
</HBox>
</children>
</VBox>
</children>
</VBox>
在有人给出答案之前,这可能是一个解决办法。一个扩展了对话框的警报
,包装了一个。对话框窗格
分为不同的部分,其中一个部分是“按钮栏”。正如预期的那样,这一部分是所有按钮的位置。按钮栏可以是任意的节点
,但是对话框窗格
的默认实现使用适当命名的控件。这一点记录在(emphasismine)中:
此方法可以由子类重写以提供按钮栏。请注意,通过重写此方法,开发人员必须承担多重责任:
开发人员必须立即遍历所有按钮类型,并依次调用createButton(ButtonType)
开发人员必须向按钮类型列表添加一个侦听器,当该列表更改时,根据需要更新按钮栏
同样,开发人员必须注意可扩展内容属性的更改,添加和删除详细信息按钮(通过createDetailsButton()方法创建)
此方法的默认实现创建并返回一个新的ButtonBar实例。
默认情况下,按钮栏
将所有按钮的大小调整为最宽按钮的宽度
均匀钮扣尺寸
默认情况下,所有按钮在ButtonBar中的大小是一致的,这意味着所有按钮都采用最宽按钮的宽度。可以在每个按钮的基础上选择不使用该选项,但使用布尔值false调用setButtonUniformSize(Node,boolean)方法
如果某个按钮被排除在统一大小之外,则该按钮的大小将被排除在其首选大小之外,也将被排除在测量过程之外,因此其大小不会影响为ButtonBar中的所有按钮计算的最大大小
正如上面Javadoc中提到的,可以使用静态方法禁用此行为。只需使用getButtonTypes()
和lookupButton(ButtonType)
在按钮上循环,并将每个按钮的统一大小设置为false
Alert alert = ...;
DialogPane pane = alert.getDialogPane();
pane.getButtonTypes().stream()
.map(pane::lookupButton)
.forEach(btn-> ButtonBar.setButtonUniformedSize(btn, false));
请注意,如果不使用默认设置,则需要事先配置按钮类型
如果涉及自定义对话框窗格
s,则这取决于实现。例如,可能自定义的对话框窗格
没有使用按钮栏
。但是,您的代码没有显示使用自定义对话框窗格的指示,因此上述解决方案应该可以正常工作。I n
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication8.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="250.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox maxHeight="80.0" style="-fx-background-color: #E4E4E4;">
<children>
<StackPane prefWidth="300.0" style="-fx-background-color: #E4E4E4;">
<children>
<Label text="Header Text Goes Here!" StackPane.alignment="CENTER_LEFT">
<padding>
<Insets left="20.0" />
</padding>
<font>
<Font size="16.0" />
</font>
</Label>
</children>
</StackPane>
<ImageView fitHeight="80.0" fitWidth="80.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
<VBox maxHeight="170.0" style="-fx-background-color: #F8F8F8;">
<children>
<AnchorPane minHeight="130.0">
<children>
<Label alignment="TOP_LEFT" text="Body Text Goes Here!" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<padding>
<Insets left="20.0" top="15.0" />
</padding>
</Label>
</children>
</AnchorPane>
<HBox alignment="CENTER_RIGHT" spacing="10.0">
<children>
<Button mnemonicParsing="false" text="Yes" />
<Button mnemonicParsing="false" text="No, continue without restart" />
</children>
<padding>
<Insets bottom="10.0" right="20.0" />
</padding>
</HBox>
</children>
</VBox>
</children>
</VBox>
Alert alert = ...;
DialogPane pane = alert.getDialogPane();
pane.getButtonTypes().stream()
.map(pane::lookupButton)
.forEach(btn-> ButtonBar.setButtonUniformedSize(btn, false));