Am new to JavaFX and changing only a component of a scene on button click while other components of the scene remain unchanged is giving me hard times.
I have a splitpane with 2 divisions. One part containing a HBox with buttons and a VBox on the other. How can I replace the VBox depending on button clicked ? thanks in advance, Below is my sample code:
public class ShoolLibrary extends Application {
BorderPane b_pane;
SplitPane common;
Scene scene;
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("The Library");
b_pane = new BorderPane();
common = commonGround();
b_pane.setCenter(common);
scene = new Scene(b_pane, 700, 480);
primaryStage.setScene(scene);
primaryStage.show();
}
//Main Content
private SplitPane commonGround(){
HBox hb = new HBox(); //Holds Buttons for Action
VBox vb = new VBox(); //This should change depending on button click
Button btn1 = new Button("library profile");
Button btn2 = new Button("Books");
Button btn3 = new Button("Members");
//Button Action
btn1.setOnAction(actionEvent -> /*Replace vb with profile()*/);
btn2.setOnAction(actionEvent -> /*Replace vb with books()*/);
btn2.setOnAction(actionEvent -> /*Replace vb with members()*/));
hb.getChildren().addAll(btn1,btn2,btn3);
SplitPane sp = new SplitPane();
sp.setOrientation(Orientation.HORIZONTAL);
sp.getItems().addAll(hb,vb);
return sp;
}
private VBox profile(){
txt = new Text("Inside library profile");
VBox vbx1 = new VBox();
vbx1.getChildren().add(txt);
return vbx1;
}
private VBox books(){
txt = new Text("Inside books");
VBox vbx1 = new VBox();
vbx1.getChildren().add(txt);
return vbx1;
}
private VBox members(){
txt = new Text("Inside Members");
VBox vbx1 = new VBox();
vbx1.getChildren().add(txt);
return vbx1;
}
public static void main(String[] args) {
launch(args);
}
}
How about using a wrapper pane in which you place your vBoxes?
Pane wrapperPane = new Pane();
sp.getItems().addAll(hb, wrapperPane);
then:
VBox library = profile()
btn1.setOnAction(actionEvent ->
wrapperPane.getChildren().clear();
wrapperPane.getChildren().add( library );
);
VBox books = books()
btn2.setOnAction(actionEvent ->
wrapperPane.getChildren().clear();
wrapperPane.getChildren().add( books );
);
and so on...
Related
I've checked How can I remove a JPanel from a JFrame? but when I tried to do frame.remove(mainScreen) the whole thing just froze. I also tried mainScreen.setVisible(false); but that showed the balls but they were static (they should move).
// important variables
FlowLayout fL = new FlowLayout();
// create frame
JFrame frame = new JFrame("Ball");
frame.setTitle("GaoMolecules");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setResizable(false);
Rectangle fDim = frame.getBounds(); // frameDimensions
// add panel to frame
JPanel mainScreen = new JPanel();
mainScreen.setLayout(fL);
fL.setAlignment(FlowLayout.TRAILING);
frame.add(mainScreen);
// other panel components
JTextField numBallsField = new JTextField(4);
JLabel numBallsLabel = new JLabel("Enter the number of balls to generate");
JButton startButton = new JButton("START");
mainScreen.add(numBallsLabel);
mainScreen.add(numBallsField);
mainScreen.add(startButton);
// add listener to button
startButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//System.out.println("Button Working!");
mainScreen.setVisible(false);
frame.add(new DrawManager());
start = true;
}
});
// this needs to be the very LAST
frame.setVisible(true);
Any time you do a remove(), you should call
frame.validate();
frame.repaint();
This example creates the ToolBar and attempts to add the same ToolBar to 2 different JFrames.
I was expecting that both JFrames would have the identical ToolBar, but apparently the ToolBar is being added only to the 2nd JFrame.
If the code for the 2nd JFrame is commented out then the ToolBar gets added to the 1st Frame as expected.
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.*;
public class ToolBarSample {
public static void main(final String args[]) {
JFrame frame = new JFrame("JToolBar Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JToolBar toolbar = new JToolBar();
toolbar.setRollover(true);
JButton button = new JButton("button");
toolbar.add(button);
toolbar.addSeparator();
toolbar.add(new JButton("button 2"));
toolbar.add(new JButton("button 3"));
toolbar.add(new JButton("button 4"));
Container contentPane = frame.getContentPane();
contentPane.add(toolbar, BorderLayout.NORTH);
contentPane.setPreferredSize(new Dimension(10,10));
JTextArea textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
contentPane.add(pane, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setVisible(true);
JFrame frame2 = new JFrame("JToolBar Example 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane2 = frame2.getContentPane();
contentPane2.add(toolbar, BorderLayout.NORTH);
frame2.setSize(500, 500);
frame2.setVisible(true);
}
}
Why is the JToolBar only being added to the 2nd JFrame and not both?
You can add a JToolbar (Component) into only 1 JFrame (Container) at the same time. Because Swing/AWT component's struct is a tree. A tree's node can not have more than 1 parent.
In your case, you can implement a method to create a JToolbar. Then, you create 2 JToolbar and add to 2 JFrame as follows:
class ToolBarSample {
public static void main(final String args[]) {
JFrame frame = new JFrame("JToolBar Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.add(createToolbar(), BorderLayout.NORTH);
contentPane.setPreferredSize(new Dimension(10, 10));
JTextArea textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
contentPane.add(pane, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setVisible(true);
JFrame frame2 = new JFrame("JToolBar Example 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane2 = frame2.getContentPane();
contentPane2.add(createToolbar(), BorderLayout.NORTH);
frame2.setSize(500, 500);
frame2.setVisible(true);
}
private static JToolBar createToolbar() {
JToolBar toolbar = new JToolBar();
toolbar.setRollover(true);
JButton button = new JButton("button");
toolbar.add(button);
toolbar.addSeparator();
toolbar.add(new JButton("button 2"));
toolbar.add(new JButton("button 3"));
toolbar.add(new JButton("button 4"));
return toolbar;
}
}
I have a button called add new user by hitting that a pop up window should come out containing a add user form .
Here is my function for that button :
public void btnAddeNewClicked(){
final TextField name = new TextField() ;
final TextField addr = new TextField() ;
final TextField wp = new TextField() ;
final TextField state = new TextField() ;
final TextField loginName = new TextField() ;
final Label labelUsername = new Label();
final Label labelAddress = new Label();
final Label labelWebPage = new Label();
final Label labelState = new Label();
final Label labelloginName = new Label();
final Button btn = new Button("Add");
Stage dialog = new Stage();
dialog.initStyle(StageStyle.UTILITY);
Scene scene = new Scene(btn);
dialog.setScene(scene);
dialog.show();
}
the problem is I don't know how to add my form into my Stage . Any help is strongly appreciated :)
Use any of the layout to add the content of your popup. Later, add this layout as the root of the scene.
In the following example, I have used a GridPane.
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Button button = new Button("Show Popup");
button.setOnAction(e -> btnAddeNewClicked());
Scene scene = new Scene(new StackPane(button), 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public void btnAddeNewClicked(){
final TextField name = new TextField() ;
final TextField addr = new TextField() ;
final TextField wp = new TextField() ;
final Label labelUsername = new Label("Username");
final Label labelAddress = new Label("Address");
final Label labelWebPage = new Label("Web Page");
final Button btn = new Button("Add");
GridPane gridPane = new GridPane();
gridPane.setVgap(10);
gridPane.setHgap(10);
gridPane.setPadding(new Insets(10));
gridPane.add(labelUsername, 0, 0);
gridPane.add(name, 1, 0);
gridPane.add(labelAddress, 0, 1);
gridPane.add(addr, 1, 1);
gridPane.add(labelWebPage, 0, 2);
gridPane.add(wp, 1, 2);
gridPane.add(btn, 0, 3, 2, 1);
GridPane.setHalignment(btn, HPos.CENTER);
Stage dialog = new Stage();
dialog.initStyle(StageStyle.UTILITY);
Scene scene = new Scene(gridPane);
dialog.setScene(scene);
dialog.show();
}
}
OUTPUT
Choose a suitable layout Parent to add your Nodes to. There are a lot of possibilities, so I just demonstrate it with a very simple one: VBox, which just puts the places all children in a vertical row:
final TextField name = new TextField() ;
final TextField addr = new TextField() ;
final TextField wp = new TextField() ;
final TextField state = new TextField() ;
final TextField loginName = new TextField() ;
final Label labelUsername = new Label();
final Label labelAddress = new Label();
final Label labelWebPage = new Label();
final Label labelState = new Label();
final Label labelloginName = new Label();
final Button btn = new Button("Add");
VBox root = new VBox();
root.getChildren().addAll(name,
addr,
wp,
state,
loginName,
labelUsername,
labelAddress,
labelWebPage,
labelState,
labelloginName,
btn);
Stage dialog = new Stage();
dialog.initStyle(StageStyle.UTILITY);
Scene scene = new Scene(root);
dialog.setScene(scene);
dialog.show();
Note that these layouts could be used as children of other layouts too, if a more complex layout is needed. Using SceneBuilder may be easier for a beginner, but you should know how the layouts position the children regardless. It's easy to see the child-parent relationships in the resulting fxml file reproduce the same layout in java code.
I'm developing a simple GXT widget - it's a TreePanel with a ToolBar added using setTopComponent.
The problem is that as soon as the tree is large enough so that it can be scrolled, the scroll-bar doesn't scroll the tree only, but scrolls the ToolBar as well.
What should be change so that ToolBar remains on the top of page, and only the tree is scrolled.
public class TreePanelExample extends LayoutContainer {
#Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
Folder model = getTreeModel();
TreeStore<ModelData> store = new TreeStore<ModelData>();
store.add(model.getChildren(), true);
final TreePanel<ModelData> tree = new TreePanel<ModelData>(store);
tree.setDisplayProperty("name");
tree.setAutoLoad(true);
ToolBar toolBar = new ToolBar();
toolBar.setBorders(true);
toolBar.add(new Button("Dummy button", new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
Info.display("Dummy button", "I'm so dumb!");
}
}));
ContentPanel panel = new ContentPanel();
panel.setHeaderVisible(false);
panel.setCollapsible(false);
panel.setFrame(false);
panel.setAutoWidth(true);
panel.setAutoHeight(true);
// setting fixed size doesn't make any difference
// panel.setHeight(100);
panel.setTopComponent(toolBar);
panel.add(tree);
add(panel);
}
The problem is that
TreePanelExample extends LayoutContainer
while instead it should extend Viewport.
Additionally I shouldn't have used
panel.setAutoWidth(true);
panel.setAutoHeight(true);
Plus it is necessary to add the main panel using
new BorderLayoutData(LayoutRegion.CENTER);
Here is the complete solution:
public class TreePanelExample extends Viewport {
public TreePanelExample() {
super();
setLayout(new BorderLayout());
Folder model = getTreeModel();
TreeStore<ModelData> store = new TreeStore<ModelData>();
store.add(model.getChildren(), true);
final TreePanel<ModelData> treePanel = new TreePanel<ModelData>(store);
treePanel.setDisplayProperty("name");
treePanel.setAutoLoad(true);
ToolBar toolBar = new ToolBar();
toolBar.setBorders(true);
toolBar.add(new Button("Dummy button", new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
Info.display("Dummy button", "I'm so dumb!");
}
}));
ContentPanel panel = new ContentPanel();
panel.setBodyBorder(false);
panel.setHeaderVisible(false);
panel.setTopComponent(toolBar);
panel.setLayout(new FitLayout());
panel.add(treePanel);
BorderLayoutData centerData = new BorderLayoutData(LayoutRegion.CENTER);
centerData.setMargins(new Margins(5, 5, 5, 5));
centerData.setCollapsible(true);
panel.syncSize();
add(panel, centerData);
}
I have a Jframe declared and adda JTabbedPane to it.
There are 4 tabbedPane and each has a table content.
Now, I need to add a refresh button to each tab, how can I do this?
This is how I'm doing:
frmSql = new JFrame();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Events", retrieveData("events"));
tabbedPane.addTab("Completed Events", retrieveData("completed"));
frmSql.add(tabbedPane);
Any suggestions?
static void createAndShowGui() {
JFrame frmSql = new JFrame();
JTabbedPane tabbedPane = new JTabbedPane();
Action refreshEvents = null, refreshCompletedEvents = null;
tabbedPane.addTab("Events", createTab(retrieveData("events"), refreshEvents));
// more tabs
tabbedPane.addTab("Completed Events", createTab(retrieveData("completed"), refreshCompletedEvents));
frmSql.setContentPane(tabbedPane);
}
static JComponent createTab(JComponent content, Action refreshAction) {
JPanel p = new JPanel(new BorderLayout());
p.add(content, BorderLayout.CENTER);
JPanel btns = new JPanel();
BoxLayout layout = new BoxLayout(btns, BoxLayout.LINE_AXIS);
btns.setLayout(layout);
JButton refreshBtn = new JButton(refreshAction);
btns.add(refreshBtn);
btns.add(Box.createHorizontalGlue());
p.add(btns, BorderLayout.PAGE_END);
return p;
}
Of course, if retriveData is time-consuming, it shouldn't be called from EDT