java中fjrame,是否可以将包含自定义JavaFX控件的JAR导入Scene Builder?

I was working on a stage when I noticed I practically had the exact same thing three times. Rather than that (since I hate that), I decided to take what I had those 3 times and turn it into a custom component.

Now I know I can add it in code but I can't predict the layout behavior (two of these will be going into tabs directly, and the third will be going into a grid pane).

I tried importing the .jar that contained the control into Scene Builder. A dialog popped up asking me what in the JAR I wanted to import but it was completely empty.

I've seen before that some individuals have added "custom controls" (a term which I use loosely) only to find that basically it just dumps a bunch of components together to form the control. That may work for some people but I'm not looking for that. To clarify

what I DO want (were I to look into the FXML code):

what I do NOT want:

//bla bla column constraint stuff

//etc, etc

Is this possible? I'm coming off of C# and VS2010 again and I'm a bit spoiled when it comes to custom controls so if it's at all possible to make something like that happen, can someone tell me how?

Is it possible to import a compiled JAR file containing a custom JavaFX control into Scene Builder, such that dropping it in from the library will result in what I described up there?

EDIT 1

Okay this is what I have in my FXML file. According to mlody991, I need 3 files to make this work:

The FXML file (Built with SceneBuilder):

The Java Class file (which will represent the actual object in code):

package DGCSDefiner;

import java.io.IOException;

import static java.util.Arrays.asList;

import javafx.fxml.FXML;

import javafx.fxml.FXMLLoader;

import javafx.scene.control.ColorPicker;

import javafx.scene.control.ComboBox;

import javafx.scene.control.Slider;

import javafx.scene.control.TabPane;

import javafx.scene.layout.GridPane;

import javafx.scene.layout.Pane;

import javafx.scene.layout.StackPane;

public class DGCSDefiner extends Pane { //DigiGames Color Settings Definer.

// Values injected by FXMLLoader

//

//

@FXML private GridPane gpLinearSettings; // fx:id="gpLinearSettings"

@FXML private StackPane spSettings; // fx:id="spSettings"

@FXML private TabPane tabsRadialSettings; // fx:id="tabRadialSettings"

//

//

@FXML private ColorPicker cpSolidColor, // fx:id="cpSolidColor"

cpFirstLinearColor, // fx:id="cpFirstLinearColor"

cpSecondLinearColor, // fx:id="cpSecondLinearColor"

cpFirstRadialColor, // fx:id="cpFirstRadialColor"

cpSecondRadialColor; // fx:id="cpSecondRadialColor"

//

//

@FXML private ComboBox cbxColorStyle; // fx:id="cbxColorStyle"

@FXML private ComboBox cbxLinearAngle; // fx:id="cbxLinearAngle"

//

//

@FXMLprivate Slider sliderRadius, // fx:id="sliderRadius"

sliderHPos, // fx:id="sliderHPos"

sliderVPos; // fx:id="sliderVPos"

//

//

private FXMLLoader Loader;

@FXML // This method is called by the FXMLLoader when initialization is complete

void initialize() {

//

//

assert this.gpLinearSettings != null : "fx:id=\"gpLinearSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.spSettings != null : "fx:id=\"spSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.tabsRadialSettings != null : "fx:id=\"tabsRadialSettings\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

//

//

assert this.cpSolidColor != null : "fx:id=\"cpSolidColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.cpFirstLinearColor != null : "fx:id=\"cpFirstLinearColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.cpSecondLinearColor != null : "fx:id=\"cpSecondLinearColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.cpFirstRadialColor != null : "fx:id=\"cpFirstRadialColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.cpSecondRadialColor != null : "fx:id=\"cpSecondRadialColor\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

//

//

assert this.cbxColorStyle != null : "fx:id=\"cbxColorStyle\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.cbxLinearAngle != null : "fx:id=\"cbxLinearAngle\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

//

//

assert this.sliderRadius != null : "fx:id=\"sliderRadius\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.sliderHPos != null : "fx:id=\"sliderHPos\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

assert this.sliderVPos != null : "fx:id=\"sliderVPos\" was not injected: check your FXML file 'JFXMLColorStyleDefiner.fxml'.";

//

//

//

//

this.cbxColorStyle.getItems().addAll(

asList(ColorStyles.values())

);

for (int x = 0; x < 8; x++)

this.cbxLinearAngle.getItems().add(x * 45);

this.cbxColorStyle.setOnAction(event -> {

ColorStyles CS = this.cbxColorStyle.getValue();

this.cpSolidColor.setVisible(CS == ColorStyles.SOLID);

this.gpLinearSettings.setVisible(CS == ColorStyles.LINEAR);

this.tabsRadialSettings.setVisible(CS == ColorStyles.RADIAL);

});

//

this.Loader = new FXMLLoader(

this.getClass().getResource("DGCSDefiner.fxml")

);

this.Loader.setRoot(this);

this.Loader.setController(this);

//

}

public DGCSDefiner(){

try{ this.Loader.load(); }

catch(IOException e){ throw new RuntimeException(e); }

}

/**

* Get the ColorSettings defined by the control.

* @return Defined Color Settings.

*/

public ColorSettings getColorSettings(){

if (this.cbxColorStyle.getSelectionModel().getSelectedIndex() < 0)

return null;

switch(this.cbxColorStyle.getValue()){

case SOLID:

return new ColorSettings(this.cpSolidColor.getValue());

case LINEAR:

return new ColorSettings(

this.cpFirstLinearColor.getValue(),

this.cpSecondLinearColor.getValue(),

this.cbxLinearAngle.getValue()

);

case RADIAL:

return new ColorSettings(

this.cpFirstRadialColor.getValue(),

this.cpSecondRadialColor.getValue(),

(int)this.sliderRadius.getValue(),

(int)this.sliderHPos.getValue(),

(int)this.sliderVPos.getValue()

);

}

return null; //This should never happen.

}

/**

* Load defined color settings.

* @param cs Predefined color settings.

*/

public void setColorSettings(ColorSettings cs){

this.cbxColorStyle.setValue(cs.Style);

switch(cs.Style){

case SOLID:

this.cpSolidColor.setValue(cs.clrPrimary);

break;

case LINEAR:

this.cbxLinearAngle.setValue(cs.intAngle);

this.cpFirstLinearColor.setValue(cs.clrPrimary);

this.cpSecondLinearColor.setValue(cs.clrSecondary);

break;

case RADIAL:

this.sliderRadius.setValue(cs.intSize);

this.sliderHPos.setValue(cs.intHPos);

this.sliderVPos.setValue(cs.intVPos);

this.cpFirstRadialColor.setValue(cs.clrPrimary);

this.cpSecondRadialColor.setValue(cs.clrSecondary);

}

}

}

And then this last file, the purpose of which eludes me:

/*

* To change this license header, choose License Headers in Project Properties.

* To change this template file, choose Tools | Templates

* and open the template in the editor.

*/

package DGCSDefiner;

import java.net.URL;

import java.util.ResourceBundle;

import javafx.fxml.Initializable;

/**

*

* @author Will

*/

public class DGCSDefinerController implements Initializable {

@Override

public void initialize(URL location, ResourceBundle resources) {

}

}

Is it possible for someone to explain to me the purpose of this last file? What is it's function? I can see from the example code with which I was furnished it has been set as the FXML Controller but that still tells me nothing. I've never really even set an FXML controller before since I typically do it in code, so is it's purpose explicitly to make this control importable into the Scene Builder?

EDIT 2 Okay. I had a hunch and it proved correct but it did not help. I removed the control CSS stylesheet reference and it allowed me to add the control, no problem.

However when I dropped it in this was what happened in the FXML file:

It went from this (Relevant portion only shown):

to this:

which is exactly what I DO NOT WANT.

What I would like to see is something to the effect of this:

in the FXML code after I drag and drop the custom control into the designer.

Is that possible? Do I need to compile it into a jar?

Edit 3

To make it a bit more clear, this is exactly what I want to see happen. This looks good but the problem is there is no information about how to import a custom control into Scene Builder such that when I Drag 'n Drop it onto the canvas, I only get somewhere in the neighborhood of a single line of code, vs the book and a half it's writing (which is just silly. If I wanted that I could (and would) do it myself).

解决方案

You do not need .jar file to do that. You can simply create new FXML file with that what you need ex. combo box. Create class file with extending combo box, controller and add controller in FXML file (in scene builder).

Find "Import from JAR/FXML file" in combo box near to left search box in scene builder and then select the file. Now you have new title pane in left accordion with name Custom. There you can find your components.

@edit

There are files.

MyGridPane.fxml

MyGridPane.java

package MyGridPane;

import javafx.fxml.FXMLLoader;

import java.io.IOException;

/**

* Created by Marcin on 2014-09-01.

*/

public class MyGridPane {

MyGridPane(){

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MyGridPane.fxml"));

fxmlLoader.setRoot(this); fxmlLoader.setController(this);

try {

fxmlLoader.load();

} catch (IOException exception) {

throw new RuntimeException(exception);

}

}

}

MyGridPaneController.java

package MyGridPane;

import javafx.fxml.Initializable;

import java.net.URL;

import java.util.ResourceBundle;

/**

* Created by Marcin on 2014-09-01.

*/

public class MyGridPaneController implements Initializable{

@Override

public void initialize(URL location, ResourceBundle resources) {

}

}

Next step is add to Scene Builder

VJOMb.png

and you can add this component.

uRbq5.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值