Resizable webview pane in fxml

greetings,
I'm new to java FX and I've been having problems with fxml. I created a custom WebViewPane class that extends from Pane class and the code is pretty much the same with the WebViewPane from the samples of WebViewBrowser. Then I tried to put that class into fxml files that will be used in a conroller class. and basically the fxml files is like this:
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="500.0" styleClass="background" xmlns:fx="http://javafx.com/fxml" fx:controller="lenterastudio.WebViewController" >
<children>
<WebViewPane fx:id="webPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="500.0" />
</children>
<stylesheets>
<URL value="@Form.css"/>
</stylesheets>
</AnchorPane>
the WebViewPane is showed up and successfully load a webpage but the problems are the pane itself is only filled some parts of the AnchorPane and when I tried to resize the form, the WebViewPane didn't align to it and still in the same size with the preferred Height and Width.
can anyone give me advice how can I make the WebViewPane using the same Height and Width as the parent does? and how can I make it resizable using fxml?

See this example https://github.com/tomsontom/e-fx-clipse/blob/master/at.bestsolution.efxclipse.testcases.fxgraph/src/at/bestsolution/efxclipse/testcases/fxgraph/AddressBook.fxml its a test case for my Eclipse Tooling named e(fx)clipse. The next version will provide you with some FXML-Tooling beside the one for my custom DSL.

Similar Messages

  • Analysis crashing when resizing any pane

    Hello,
    I am on BI 4.1 SP4. When I resize any pane in analysis in any of our systems, dev, qa, or prod analysis will crash. The error is attached in a screenshot, kind of useless in terms of figuring out why this is happening, typical. Has anyone experienced this?
    Cheers,

    Hi Tammy,
    I am also using a BEx query as a source.
    Here is a sample from the log generated with the error.
    FILE_TYPE:DAAA96DE-B0FB-4c6e-AF7B-A445F5BF9BE2
    ENCODING:UTF-8
    RECORD_SEPARATOR:30
    COLUMN_SEPARATOR:124
    ESC_CHARACTER:27
    COLUMNS:Location|Guid|Time|Tzone|Trace|Log|Importance|Severity|Exception|DeviceName|ProcessID|ThreadID|ThreadName|ScopeTag|MajorTick|MinorTick|MajorDepth|MinorDepth|RootName|RootID|CallerName|CallerID|CalleeName|CalleeID|ActionID|DSRRootContextID|DSRTransaction|DSRConnection|DSRCounter|User|ArchitectComponent|DeveloperComponent|Administrator|Unit|CSNComponent|Text
    SEVERITY_MAP: |None| |Success|W|Warning|E|Error|A|Assertion
    HEADER_END
    .\sisecserver_impl.cpp:366:-: TraceLog message 1975
    |9f7ece35-be1d-2d14-1bc2-7bff07613dad|2014 08 18 11:08:47:073|-0400|Error| |>>|E| |cms_<systemname>.CentralManagementServer| 3064|3912|| |16|0|2|0|.pleaseDoIt|<systemname>:4672:77.17037:1|BIPSDK.SecurityInfo2:getKnownRightsByPlugin|<systemname>:4672:77.17037:8|cms_<systemname>.CentralManagementServer.processSerializedBatch|localhost:3064:3912.1341290:1|Cms7JKToqE96nzxl5QO0Pa4b6|||||gmartins||||||assert failure: (.\sisecserver_impl.cpp:366). (wireProps != NULL : no message).
    .\sisecserver_impl.cpp:366:-: TraceLog message 1976
    ....repeats the message for a bit....
    .\DatabaseSubsystem_impl.cpp:239:-: TraceLog message 2016
    |12bb289b-9a11-3d24-baab-52530a8702d3|2014 08 18 11:09:21:115|-0400|Error| |  |E| |cms_<systemname>.CentralManagementServer| 3064|3376|| |1|0|1|0|BIPSDK.InfoStore:query|<systemname>:4200:180.2885205:1|BIPSDK.InfoStore:query|<systemname>:4200:180.2885205:1|cms_<systemname>.CentralManagementServer.queryEx3|localhost:3064:3376.1341396:1|Clv9aDJov0qNppgGcs7bqRE145af6|||||||||||Database deadlock encountered.  Ensure database is correctly tuned and that data statistics are up to date.
    the final message in the log...
    .\apsfactory.cpp:581:-: TraceLog message 6704
    |6bfeabe8-db02-3604-0bca-6d8f8ef5dfea|2014 08 19 08:58:14:514|-0400|Error| |  |E| |cms_<systemname>.CentralManagementServer| 3064|3820|| |41|0|3|0|BIlaunchpad.WebApp|<systemname>:1388:139.5236:1|BIPSDK.SessionMgr:getSession|<systemname>:11220:3743.13726:3|cms_<systemname>.CentralManagementServer.newService|localhost:3064:3820.1810951:1|Cm6vhIXsBENNl1QI42PAtf817c9|||||||||||Failed to get session id from handle and handle is not set to bypass nor server-server discovery

  • Resizing glass pane

    Disabling GUI controlls causing the loose of the controls beauty.
    However, sometimes it is neccessary, to display the control in
    a uneditable mode, especially when the input can not be consumed.
    The perfect idea to maintain the beauty of the GUI contorls and
    make them uneditable, is to put a glass infront of them, so you just
    look from pattern :).
    This is a greate idea provided through GlassPane in the Swing API.
    But, still there is a limitation, why?
    The glass pane should be as large as the JRootPane, which means
    that you have to cover the whole top-level container :(.
    Take this example:
    I have a TabbedPane that consists of multiple tabs and the tabbed pane is loacted in a JApplet. I need to move between the tabs while making the controls in side the tabbs uneditable. Here I was constrained by the
    Glass Pane since it covers the whole applet's area, and no more accessability to the tabbs.
    Some one said: redispatch the event to the TabbedPane, I said: Ok, but
    no method in the TabbedPane tells me which tab has the x,y point.
    I suggest to make the GlassPane resizable, and to provide a method in
    the TabbedPane which takes the x,y a returns the index of the selected
    tab.
    Please what do you think ? :-)

    I think it is not useful because you can create your own glasspane for any component you want !
    Look at this thread :
    http://forum.java.sun.com/thread.jsp?forum=57&thread=268566
    I hope this helps,
    Denis

  • Resizing connector pane

    Is there anyway to resize the connector pane, just for the easy handling while assigning connections? And it seems the maximum number of connection that one can have on a connector pane are limited to 24. Is there anyway to add more?
    Does adding up more connection to the connector pane, slow down the vi?
    Thanks,
    Deepak
    LAB View 2010 SP1

    jcarmody wrote:
    Take a look at this and this (by this person).
    Thanks for the link.  Pretty cool!
    Reese, (former CLAD, future CLD)
    Some people call me the Space Cowboy!
    Some call me the gangster of love.
    Some people call me MoReese!
    ...I'm right here baby, right here, right here, right here at home

  • Resize Window panes, show contact time?

    I recently upgraded to the latest version 7.0.0.102 of Skype and there are two things which I cannot stand. 
    I want to resize the Message window to be larger. It feels clausterphobic. 
    In the previous version when one clicked on the contact to IM them, it would show the location and time. I'd like to be able to see what time it is without having to double click on the contact to see the location and time zone. This is important as to avoid bothering people at certain times, even if they are online. 
    If these aren't posssible, is there a link to the previous version?
    Solved!
    Go to Solution.

    The latest Skype 7.2 re-adds the information about your contact's time and timezone back to their profile: www.skype.com/go/download
    Follow the latest Skype Community News
    ↓ Did my reply answer your question? Accept it as a solution to help others, Thanks. ↓

  • Problem viewing AS pane on screen..

    Hi All
    a really daft one this...
    i cant see all of the AS in the AS code pane (f9) the pane is
    to long and i
    cant see how you can resize it?
    i can change the width, but the bottom of the pane is below
    by monitor
    window..
    i have tried changing my monitor resolution so can grab the
    bottom resize
    bar, but even then its still to long to view it?
    any ideas...
    thanks in advance
    keen to learn..

    Reize from the top down...
    Thanks - Soooooo simple when you know how eh ;0)
    as ever
    keen to learn..
    "r_critchlow" <[email protected]> wrote in message
    news:fhv13m$188$[email protected]..
    > You can resize the panes in Flash from the top down,
    then grab the title
    > bar
    > and drag them up. Side-to-side you can do something
    similar, grab the
    > title bar
    > and drag the pane until you can see one edge or the
    other. Drop it then
    > resize
    > the visible side, then drag where it needs to be. Repeat
    as needed.
    >
    > However, if this doesn't work, you can resort to
    selecting Window =>
    > Workspace
    > => Default and everything will return to the Flash
    default settings.
    > However,
    > you will probably have to turn on or off any other panes
    to get back to
    > your
    > preferred layout (unless you have saved your
    preferences).
    >
    > Hope that helps.
    >

  • Dragged the line tween message list and preview pane so far up that i can't get the double arrow to drag it back down; now the window is only 10% for mess. list

    I like to keep my window about 60% message pane - above the line - and 40% for the open message. To see an entire message, I resized the panes with the double arrow. No more double arrow and it's 80% open message and 20% list of messages.
    Also, since I have you, Can Lightning show an event on the monthly grid Without Adding the time in the box, or at least allow something like 7p or 2:30p, e.g. ? Thank you for what you do!
    Susan

    Try F8 to get control of the message pane.
    As far as the Lightning question, are you wanting to shorten the time so that more of the description is displayed?

  • How do I resize partitons?

    Ok i downloaded the yosemite beta a while ago, i looked up some post on google and tried  to get rid of the os and try to combine my partitions but from the past forums on here it seems that it still does not work, i still do not have a option to combine the partitions. I tried the terminal code "diskutil cs revert disk1" does not seem to work, I tried some apps through the app store still does not give me the option to combine "resize" back to one. Right now im back with 10.9.5 mavericks and deleted yosemite but it still shows the separate partition!

    In the Drop Zone inspector, you should find Pan and Scale parameters. Use the Scale to resize and Pan to position.

  • Resizing a JScrollPane

    Hi, I have a JScrollPane that contains a JTable inside. Basically, when a user clicks a button or selects an option, the Table Model changes and the table is populated with a different set of data, of a different size. The scrollpane starts off at a size of 500x255, but sometimes there are only a few rows of data to display, and the rest of the scrollpane shows up (below the table) as grey space. An example would be like this:
    http://img205.imageshack.us/img205/4899/grrrlu2.png
    I've been trying everything I can think of, and I can't get it to work properly. I've tried this:
    if(skillTable.getHeight() <= 255){
                        scrollPane.setPreferredSize(new Dimension(500,skillTable.getHeight() + 19));
                        scrollPane.revalidate();
                   else{
                        scrollPane.setPreferredSize(originalDimensions);
                        scrollPane.revalidate();
                   }and it doesn't update right away... I need to click another option (or the same one) again to get it to resize properly. So basically, if I click the same button twice, the pane resizes. If I click one button, then another, it resizes the pane to what the size should've been when I clicked the previous button. Does nayone have any idea what might be causing this? Thanks in advance!

    I would suggest you keep the scrollpane at a constant height and width, and allow the content to scroll automatically. Couldnt see that picture so not sure about the exact error.
    You can let the table scroll by setting the resize mode to AUTO_RESIZE_OFF. About the gray scrollpane background that can be fixed by making it blend with the table row color eg scrollpane.getViewport().setBackground(Color.white)
    ICE

  • How to override components when resize component

    I tested this code which resize tab pane when the tab is double clicked.
    final Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
    tabPane.setOnMouseClicked(new EventHandler<MouseEvent>()
                private double sizeX, sizeY;
                private boolean first = true;
                @Override
                public void handle(MouseEvent me)
                    if (first)
                        sizeX = mainPane.getWidth();
                        sizeY = mainPane.getHeight();
                        first = false;
                    if (me.getButton().equals(MouseButton.PRIMARY) && me.getClickCount() % 2 == 0)
                        if (sizeX != mainPane.getWidth() || sizeY != mainPane.getHeight())
                            mainPane.setPrefSize(sizeX, sizeY);
                        else
                            mainPane.setPrefSize(primaryScreenBounds.getWidth(), primaryScreenBounds.getHeight());
    I want the affected panel to take precedence over all other panels. For example make the panel to overlay all other panels or maybe to hide all other panels.

    I tested this code which resize tab pane when the tab is double clicked.
    final Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
    tabPane.setOnMouseClicked(new EventHandler<MouseEvent>()
                private double sizeX, sizeY;
                private boolean first = true;
                @Override
                public void handle(MouseEvent me)
                    if (first)
                        sizeX = mainPane.getWidth();
                        sizeY = mainPane.getHeight();
                        first = false;
                    if (me.getButton().equals(MouseButton.PRIMARY) && me.getClickCount() % 2 == 0)
                        if (sizeX != mainPane.getWidth() || sizeY != mainPane.getHeight())
                            mainPane.setPrefSize(sizeX, sizeY);
                        else
                            mainPane.setPrefSize(primaryScreenBounds.getWidth(), primaryScreenBounds.getHeight());
    I want the affected panel to take precedence over all other panels. For example make the panel to overlay all other panels or maybe to hide all other panels.

  • Splitter (BUG?) Resize work-aroun​d needed

    I have a GUI which I really like but I ran into a problem that has stumpted me.  I have a single vertical splitter on the left side of the screen is a bunch of controls like a side bar.  I have the controls to resize with pane (LV 8.2) and it works great.  The only problem is that when the user moves the splitter all the war to lhe left the left pane width becomes zero ane the control width becomes huge then the control nolonger resizes correctly.  Can I limit the movement of the splitter to now allow the user to drag it past a minimum side?  I tried with events with no suscess, mouse move did not update fast enough. Is there a work around, I really like the splitter with resize with pane option.  What to do?
    Paul
    Paul Falkenstein
    Coleman Technologies Inc.
    CLA, CPI, AIA-Vision
    Labview 4.0- 2013, RT, Vision, FPGA

    Typically you don't want controls to resize themselves in that fashion. Something like a graph indicator is a good candidate for that behavior. The "Multi-Panel Front Panel using Splitter Bars" example is a good example of this. With respect to the behavior I'm not seeing exactly what you're seeing. When I place a vertical splitter and then place a rectangular button in the left pane and select the "Scale Object with Pane" for the button, LabVIEW will not let me move the splitter beyond a certain point. I certainly can't move it all the way to the left, so it's not clear, at least to me, what is going on with your implementation. Could you post the VI, or at least just the relevant parts?
    One simple work-around that I can think of off the top of my head is to read the splitter position in the Timeout event case and then coerce the position if it's less than some value. Sort of like this:
    Message Edited by smercurio_fc on 08-17-2007 09:12 AM
    Attachments:
    splitter.PNG ‏6 KB

  • Using setId on a component to change CSS dynamically

    Hi all -- I'm hoping that one of the JavaFX wizards can help me out with this one. I'm trying to set up a webview component with scrollbars that are initially transparent, but then appear on a given trigger (e.g., a mouse press) and then disappears (e.g., on mouse release) -- similar to how a scrollbar is rendered on a tablet interface (e.g., such as w/Android), for instance. Of course, the first complication is that a webview manages its own scrollbars. So this is what I thought might work:
    1) Create a webview. Set the webview's ID to a given CSS style that overrides the default scrollbar colors so they're transparent. Hence, the scrollbar is still rendered, but it's just not visible. (Yes, I know it may be "easier" to deal with opacity/visibility, but I haven't found an obvious way to affect just the scrollbars).
    2) Add an eventFilter to the webview to catch MOUSE_PRESSED. Once this happens, then I change the webview's CSS style by changing it's ID to another style, this one where the scrollbar's colors are not transparent.
    3) Similarly, another eventFilter is added to catch a MOUSE_RELEASED on the webview, and that restores the webview's CSS to the original transparent scrollbar colors.
    Okay, it's a bit convoluted, I know -- but seeing as that the scrollbars are potentially created/destroyed by the webview when pages are loaded, this seemed like a good solution. The basic code is as follows:
    final WebView browser=new WebView();
    final WebEngine webEngine=browser.getEngine();
    browser.setId("transparentScroll");
    browser.addEventFilter(MouseEvent.MOUSE_PRESSED,new EventHandler<MouseEvent>() {
      public void handle(MouseEvent me) {
        browser.setId("visibleScroll");
    browser.addEventFilter(MouseEvent.MOUSE_RELEASED,new EventHandler<MouseEvent>() {
      public void handle(MouseEvent me) {
        browser.setId("transparentScroll");
    });Unfortunately, this isn't quite working as expected. The events are captured and executed, and the setIds do take place. However, the webview isn't refreshing the scrollbars until something moves over them (like the mouse pointer). I tested this with a different (simpler) component, like a Button:
    public void start(Stage primaryStage) {
      Group root=new Group();
      Scene scene=new Scene(root,1150,700,Color.rgb(32,32,32));
      scene.getStylesheets().add("jfx.css");
      primaryStage.setScene(scene);
      final Button b=new Button("Click me");
      b.setId("test1");
      b.addEventFilter(MouseEvent.MOUSE_PRESSED,new EventHandler<MouseEvent>() {
        public void handle(MouseEvent me) {
          b.setId("test2");
      b.addEventFilter(MouseEvent.MOUSE_RELEASED,new EventHandler<MouseEvent>() {
        public void handle(MouseEvent me) {
          b.setId("test1");
      root.getChildren().add(b);
      primaryStage.show();
    }And the code with the Button class works as I expected -- the change in the CSS style is rendered immediately.
    Anyone have any ideas how to achieve this same effect with webview? Am I missing something? I would have thought that the setId would have propagated a change immediately, but apparently something is blocking the refresh. (And yes, I've tried doing a requestLayout(), and even tinkering with getting the scrollbars directly from the webview, but to no avail).
    All thoughts/ideas would be greatly appreciated. Thanks in advance!

    I won't try to solve your problem here, but will give you a couple of things to think about.
    You may want to make a feature request at http://javafx-jira.kenai.com/ to add a setting to webview to enable/disable scrolling - not sure that it would get high priority treatment though as it seems a pretty specialized case. If you need supporting reasons for such a thing, I was creating some custom controls wrapping jquery ui components and didn't want the scrollbars to appear, but just wanted any extra white space in the document clipped when the webview was sized smaller, so maybe if you also provide that use-case, that might help.
    You are setting the id on the webview component itself. The webview is a complex control, and has other controls (like the scroll bars) encapsulated in it which you don't directly get access to via the public api. So, perhaps depending on what css you used, you may need to set the id on the actual scrollbars inside the webview rather than the webview. To get a hold of them you can try running a css lookup in your code. Now the css lookup to get the webview controls is not publicly documented, but you can work it out by dumping the webview and all of it's child nodes to system.out. See here for an example of how to do this Re: Pie Chart and legend symbols (follow links from the forum post too - the example uses a chart, but the basic principle of peeking inside the complex control to get nodes via a css lookup should still work for the webview as long as you aren't trying to get the actual rendered dom objects). Once you have the scrollbars from the lookup, you could try setting their maxsize to 0,0 when you don't want them seen and removing the maxsize restriction when you want them available.
    One other thing you could try is, when you don't want the scroll bars to be visible, make the webview a bit bigger than the visible area you want to display it in and clipping it to the right size so that the scrollbars are just clipped off the display. Doing this may require a bit of fiddling around if you are using the resizable layout panes as they may want to keep resizing the webview to fit the visible area, also Nodes clip property seemed either buggy or difficult to work with from my past experience with it.

  • CS3 issues fixed in CS4?

    Have the following issues in CS3 been fixed in CS4:
    (Note: a few of these I've found already in the forum, but I am including an all comprehensive list anyway).
    1. Self resizing title pane.
    2. Still tiff image import incorrectly interpreted as an image sequence.
    3. Crash when exporting timeline directly to encore for disc burning.
    4. Audible clicks at audio edit points in final render.
    5. Missing shortcut menu items.
    6. Crash on rendering directly to cineform HD file (vs. AVI with cineform as compressor).
    7. Crash on rendering tiff images when more than one layer of images overlaps, (work around is to render images as video clips and replace - a pain).
    In the past three years I've upgraded three times and I'm getting tired of drinking the cool-aide.

    I agree that moving AME to standalone was a good decision. But I've been cntl-shift-Ming frames for years. Handing that chore off to a separate application is like swatting flies with a canon.
    How does CS4 handle single tiff images? I render animations as image sequences and edit in CS3. It's no issue if I import those sequences as image sequences (selecting the image sequence checkbox). However, CS3 treats single image files from sequences as single frame video clips. I have to copy the image to a separate folder and re-import.
    The bigger issue is that I'm fed up with three complete upgrades and have not had any significant improvement. I recall having better results and smoother workflows with CS 1.3.1.
    I'm only two projects left open on CS3, then I have to make a serious decision and maybe demo that Studio 2 package my local mac vendor has been bugging me to do.

  • How do I create an infinite drawing canvas in a ScrollPane?

    I wanted to figure this out on my own, but it is time to ask for help. I've tried too many different things. The closest I've come to the behaviour I want is with this code:
    final BorderPane root = new BorderPane();
    final Pane canvasWrapper = new Pane();
    canvasWrapper.setPrefSize(800, 500);
    canvasWrapper.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    canvasWrapper.setStyle("-fx-background-color: lightgray; -fx-border-color: green; -fx-border-width: 2px;");
    final Group canvas = new Group();
    canvasWrapper.getChildren().add(canvas);
    final ScrollPane scroll = new ScrollPane();
    scroll.setContent(canvasWrapper);
    root.setCenter(scroll);
    // event code for adding circles and lines to the canvas
    I want the ScrollPane to be filled with the Pane, so it can catch events for drawing. When the stage is resized, the ScrollPane is resized too. This the result of the BorderPane. What I want is to expand the window and have canvasWrapper expand to fill the entire ScrollPane viewport. When the stage is made smaller the ScrollPane shrinks, but I want the canvasWrapper to retain its size. The idea is the drawing canvas can only grow. When it gets too large for the current stage/ScrollPane size, the scrollpane can be used to navigate around the canvas.
    I tried using
    scroll.setFitToHeight(true);
    scroll.setFitToWidth(true);
    but this causes the Pane to be made smaller when the viewport is made smaller.

    I figured it out!
    Use
    scroll.setFitToHeight(true);
    scroll.setFitToWidth(true);
    to resize the Pane as the view port changes.
    Save the canvas' size as the Pane's size.
    canvas.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
                @Override
                public void changed(ObservableValue<? extends Bounds> ov, Bounds t, Bounds t1) {
                    canvasWrapper.setMinSize(t1.getMaxX(), t1.getMaxY());
    This forces the Pane to always be as large as the group is.
    Missed a piece of code - jrguenther

  • Variable size array in a FlowPane

    If i have an array of variable size (for example a array of cards).
    How can i build something to show the elements(in a FlowPane for example) and each of them having its own controller (fxml + controller for each card), so the container (flow pane) of the elements (cards) can have it's elements swaped, removed or added new ones?
    Controller:
    public class HandController extends FlowPane implements Initializable{
        @Override public void initialize(URL arg0, ResourceBundle arg1){
        public void setHand(ArrayList<Cards> Hand){
            //this would work if the hand were static
            for(int i = 0; i < Hand.size(); ++i){
                FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("CardView.fxml"));
                CardController controller = new CardController();
                fxmlLoader.setController(controller);
                fxmlLoader.setRoot(controller);
                Parent card = (Parent)fxmlLoader.load();
                fxmlLoader.setRoot(card);
                this.getChildren().add(card);
                controller.setCard(Hand.get(i));
    }Fxml:
    <fx:root type="FlowPane" xmlns:fx="http://javafx.com/fxml"
             stylesheets="view/Style.css">
        <children>
            <!--should i put something here?-->
        </children>
    </fx:root>

    Well, I was bored...
    This "game" has a hand of up to five cards. You can deal from a deck to the hand, and then play (or discard) a card by double-clicking on it.
    The model comprises a Card class, a Deck class, and a GameModel class. The last one tracks the hand and deck and the relationship between them. Card and Deck were written from my memory of reading an example of using Enums by Josh Bloch.
    Card.java
    package cardgame;
    public class Card {
         public enum Rank {
              Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
         public enum Suit {
              Clubs, Diamonds, Hearts, Spades
         private final Rank rank;
         private final Suit suit;
         public Card(Rank rank, Suit suit) {
              this.rank = rank;
              this.suit = suit;
         public Rank getRank() {
              return rank;
         public Suit getSuit() {
              return suit;
         @Override
         public String toString() {
              return String.format("%s of %s", rank, suit);
         @Override
         public int hashCode() {
              final int prime = 31;
              int result = 1;
              result = prime * result + ((rank == null) ? 0 : rank.hashCode());
              result = prime * result + ((suit == null) ? 0 : suit.hashCode());
              return result;
         @Override
         public boolean equals(Object obj) {
              if (this == obj)
                   return true;
              if (obj == null)
                   return false;
              if (getClass() != obj.getClass())
                   return false;
              Card other = (Card) obj;
              if (rank != other.rank)
                   return false;
              if (suit != other.suit)
                   return false;
              return true;
    }Deck.java
    package cardgame;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Random;
    import cardgame.Card.Rank;
    import cardgame.Card.Suit;
    public class Deck {
         private final List<Card> cards;
         private Deck() {
              cards = new LinkedList<Card>();
              for (Suit suit : Suit.values())
                   for (Rank rank : Rank.values())
                        cards.add(new Card(rank, suit));
         public static Deck newDeck() {
              return new Deck();
         public static Deck shuffledDeck() {
              return newDeck().shuffle();
         public Deck shuffle() {
              final List<Card> copy = new ArrayList<Card>(cards.size());
              Random rng = new Random();
              while (cards.size() > 0) {
                   int index = rng.nextInt(cards.size());
                   copy.add(cards.remove(index));
              cards.clear();
              cards.addAll(copy);
              return this;
         public Card deal() {
              return cards.remove(0);
         public int size() {
              return cards.size();
    }GameModel.java
    package cardgame;
    import javafx.beans.binding.BooleanBinding;
    import javafx.beans.property.BooleanProperty;
    import javafx.beans.property.ReadOnlyBooleanProperty;
    import javafx.beans.property.SimpleBooleanProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    public class GameModel {
         private ObservableList<Card> hand;
         private Deck deck;
         private BooleanProperty canDeal;
         public GameModel() {
              this.hand = FXCollections.observableArrayList();
              this.deck = Deck.newDeck().shuffle();
              this.canDeal = new SimpleBooleanProperty(this, "canDeal");
              canDeal.bind(new BooleanBinding() {
                        super.bind(hand);
                   @Override
                   protected boolean computeValue() {
                        return deck.size() > 0 && hand.size() < 5;
         public ObservableList<Card> getHand() {
              return hand;
         public ReadOnlyBooleanProperty canDealProperty() {
              return canDeal;
         public boolean canDeal() {
              return canDeal.get();
         public void deal() throws IllegalStateException {
              if (deck.size() <= 0) {
                   throw new IllegalStateException("No cards left to deal");
              if (hand.size() >= 5) {
                   throw new IllegalStateException("Hand is full");
              hand.add(deck.deal());
         public void playCard(Card card) throws IllegalStateException {
              if (hand.contains(card)) {
                   hand.remove(card);
              } else {
                   throw new IllegalStateException("Hand does not contain " + card);
    }The CardController is the controller for a CardView. It takes a reference to a Card and its initialize method initializes the view to display it (the view is just a simple label).
    CardController.java
    package cardgame;
    import javafx.fxml.FXML;
    import javafx.scene.control.Label;
    public class CardController {
         private final Card card;
         @FXML
         private Label label;
         public CardController(Card card) {
              this.card = card;
         public void initialize() {
              label.setText(String.format("%s%nof%n%s", card.getRank(),
                        card.getSuit()));
    }The HandController is the controller for the display of the hand. This is where most of the action happens. The trick here is that it requires a reference to a GameModel, which needs to be injected from somewhere, so we need a setModel(...) method, or something similar. I didn't want to assume the order of events: i.e. whether the model is injected before or after the initialize() method is invoked. To keep this flexibility, I used an ObjectProperty to wrap the model, and listen for changes to it. When the model is updated, I register a listener with the hand (exposed by the model). This listener in turn rebuilds the views of the cards when the hand changes. There's also a "deal" button, whose disabled state is managed by binding to a property in the model (using a neat trick from the Bindings class to allow the model value to be dynamic).
    HandController.java
    package cardgame;
    import java.io.IOException;
    import javafx.beans.binding.Bindings;
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleObjectProperty;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.collections.ListChangeListener;
    import javafx.event.EventHandler;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Node;
    import javafx.scene.control.Button;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.Pane;
    public class HandController {
         private ObjectProperty<GameModel> model;
         @FXML
         private Pane container;
         @FXML
         private Button dealButton;
         public HandController() {
              this.model = new SimpleObjectProperty<GameModel>(this, "model", null);
              final ListChangeListener<Card> handListener = new ListChangeListener<Card>() {
                   @Override
                   public void onChanged(Change<? extends Card> change) {
                        container.getChildren().clear();
                        try {
                             for (Card card : model.get().getHand()) {
                                  container.getChildren().add(loadCardView(card));
                        } catch (IOException e) {
                             e.printStackTrace();
              model.addListener(new ChangeListener<GameModel>() {
                   @Override
                   public void changed(
                             ObservableValue<? extends GameModel> observable,
                             GameModel oldValue, GameModel newValue) {
                        if (oldValue != null) {
                             oldValue.getHand().removeListener(handListener);
                        if (newValue != null) {
                             newValue.getHand().addListener(handListener);
         public void setModel(GameModel model) {
              this.model.set(model);
         public void initialize() {
              dealButton.disableProperty().bind(
                        Bindings.selectBoolean(model, "canDeal").not());
         private Node loadCardView(final Card card) throws IOException {
              FXMLLoader loader = new FXMLLoader(getClass().getResource(
                        "CardView.fxml"));
              CardController controller = new CardController(card);
              loader.setController(controller);
              Node cardView = (Node) loader.load();
              cardView.setOnMouseClicked(new EventHandler<MouseEvent>() {
                   @Override
                   public void handle(MouseEvent event) {
                        if (event.getClickCount() == 2) {
                             model.get().playCard(card);
              return cardView;
         public void dealCard() {
              model.get().deal();
    }Here are the FXML files:
    CardView.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.StackPane?>
    <?import javafx.scene.control.Label?>
    <?import java.lang.String?>
    <StackPane xmlns:fx="http://javafx.com/fxml" prefHeight="150" prefWidth="80" minWidth="80" maxWidth="80" minHeight="150" maxHeight="150">
         <Label fx:id="label" >
         </Label>
         <styleClass>
              <String fx:value="card"/>
         </styleClass>
    </StackPane>Hand.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.FlowPane?>
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.ScrollPane?>
    <?import java.lang.String?>
    <BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="cardgame.HandController" >
         <center>
              <FlowPane hgap="5" vgap="10" fx:id="container">
              </FlowPane>
         </center>
         <bottom>
              <Button text="Deal" onAction="#dealCard" fx:id="dealButton"/>
         </bottom>
    </BorderPane>The overall application is managed by a Game.fxml:
    <?xml version="1.0" encoding="UTF-8"?>
    <?import javafx.scene.layout.BorderPane?>
    <BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="cardgame.GameController">
         <center>
              <fx:include source="Hand.fxml" fx:id="hand" />
         </center>
    </BorderPane>with a GameController:
    package cardgame;
    import javafx.fxml.FXML;
    public class GameController {
         @FXML private HandController handController ;
         private GameModel model ;
         public GameController() {
              model = new GameModel();
         public void initialize() {
              handController.setModel(model);
    }Game.java is the main class:
    package cardgame;
    import java.io.IOException;
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    public class Game extends Application {
         @Override
         public void start(Stage primaryStage) throws IOException {
              Scene scene = new Scene(FXMLLoader.<Parent>load(getClass().getResource("Game.fxml")), 600, 400, Color.DARKGREEN);
              scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
              primaryStage.setScene(scene);
              primaryStage.show();
         public static void main(String[] args) {
              launch(args);
    }and then a style sheet
    style.css:
    @CHARSET "US-ASCII";
    .card {
         -fx-background-color: white ;
         -fx-border-color: black ;
         -fx-border-radius: 5 ;
         -fx-border-style: solid ;
         -fx-padding: 5 ;
    .card .label {
         -fx-text-alignment: center ;
    }

Maybe you are looking for