I want to have several JavaFX Buttons that update one Label in my Application with text. For testing purposes it's just Button Text.
What I did at first worked fine and looked like this:
String Text = "...";
public void kons() {
System.out.println("Works...");
System.out.println(Text);
Tekst.setText(Text);
Button G4 = new Button("Spadantes");
G4.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Text = G4.getText();
kons();
}
});
Then I decided to stylize my buttons with CSS and because I wanted to have several groups of buttons stylized in different way I subclassed JavaFX Button class in this way:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
Which still worked. But now I want my event handler to be moved to Button subclass (to avoid copy-pasting exactly same code into each and every button of mine). What I did looks like this:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Main.Text = getText();
Main.kons();
}
});
}
}
Main is my extend Application class
Tekst is my label.
And sadly it throws me exception about calling non-stathic method and variable from static context. From what I understand instances are static and definitions are non-static. I tried to change everything "in the way" to static but it gives me red wall of errors after clicking button (nothing in compilation process). I also tried to call instance of my Application somehow but I have no idea how (from what I understand extend Application class intantiates itself on it's own while starting program so there's no "name" by which I can call it's Label.
What I'm looking for is "quick and dirty solution" to be able to use subclassed buttons (or other sliders, text-fields, etc.) that can call a method that updates something "on screen".
[EDIT] I'm using newest Java there is of course. In case it matters.
Instead of subclassing, why not just write a utility method that creates the buttons for you? I would also not recommend making the text variable an instance variable: just reference the Label directly.
public class SomeClass {
private Label tekst ;
// ...
private Button createButton(String buttonText) {
Button button = new Button(buttonText);
button.getStylesheets().add("Buttons.css") ;
button.setOnAction(e -> tekst.setText(buttonText));
return button ;
}
}
Then, from within the same class, when you need one of those buttons you just do
Button button = createButton("Text");
If you really want to subclass (which just seems unnecessary to me), you need to pass a reference to the label to the subclass:
public class LabelUpdatingButton extends Button {
public LabelUpdatingButton(String text, Label labelToUpdate) {
super(text);
getStylesheets().add("Buttons.css");
setOnAction(e -> labelToUpdate.setText(getText()) );
}
}
Then from your class that assembles the UI you can do
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Label tekst = new Label();
Button someButton = new LabelUpdatingButton("Button text", tekst);
// etc...
}
}
But again, creating a subclass that does nothing other than define a constructor that calls public API methods is redundant, imo.
Also, it's a bit unusual to create an entire stylesheet just for your buttons. Typically you would set a style class on the Button:
button.getStyleClass().add("my-button-class");
and then in the stylesheet you add to the Scene do
.my-button-class {
/* styles for this type of button */
}
Related
This is an actionPerformed in a Swing panel with custom buttons from a framework which scrambles their classes so all methods are a():String or b():void and there is no way to make out what it actually is.
I got a compiler error becaus when I inherit this button class the compiler find a():void an a():String which is not allowed in Java. My solution was to use the adapter pattern like this:
public abstract class FactoryButton {
private CustomButton button;
public FactoryButton(int width, int height) {
button = new DynButton();
button.setSize(width, height);
}
public DynButton getButton() {
return button;
}
}
So my FactoryButton has the CustomButton class as a private member. The FactoryButton is the parent of another Button class named FactorySelectionButton
which has an action performed where I used to be able to get the source of the event:
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource() instanceof FactorySelectionButton) {
// User selected a factory
selectedItem = ((FactorySelectionButton) arg0.getSource()).getFactory();
// Close the screen, so control returns back to the parent window
cancel();
} else {
// other buttons implementation
}
}
But now since I solved one problem with the adapter pattern I have another the arg0.getSource() no longer gives me the FactorySelectionButton but it now gives a CustomButton which gives me no way to know which custom button is pressed.
The reason for not throwing away the custom button is that I am bound to the framework, I have to use it and the amount of factories can grow so I don't want hardcoded buttons.
So anyone have an idea on how I can fix this?
I found a way around it by looping over all my components and checking whether they have the button I need and they double checking whether it's really an instance of the class I want.
#Override
public void actionPerformed(ActionEvent arg0) {
for (FactoryButton component : components) {
if(component.getButton().equals(arg0.getSource()) && component instanceof FactorySelectionButton)
selectedItem = ((FactorySelectionButton) component).getFactory();
return;
}
//other buttons implementation
}
Basically what I am trying to do here is handle click events which panel is suppose to appear to depending on which button is click. For example, if we click button one, the corresponding panel will pop up. But the panel and click event does not know anything about each other. I believe its called anonymous class. I am having trouble trying to implement this. What would be a good way to implement this?
This is my button click event class
public class buttonHandle extends Composite {
private static buttonHandleUiBinder uiBinder = GWT
.create(buttonHandleUiBinder.class);
#UiField Button button;
#UiField Button button_1;
interface buttonHandleUiBinder extends UiBinder<Widget, buttonHandle> {
}
public buttonHandle() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("button")
void onButtonClick(ClickEvent event) {
}
#UiHandler("button_1")
void onButton_1Click(ClickEvent event) {
}
}
This is the class where I am trying to add a new button everytime a button is clicked
public class PanelHandle extends Composite {
private AbsolutePanel absolutePanel = new AbsolutePanel();
public PanelHandle() {
initWidget(absolutePanel);
absolutePanel.setSize("1027px", "636px");
Label lblHello = new Label("Hello");
absolutePanel.add(lblHello, 47, 80);
Label lblHello_1 = new Label("Hello");
absolutePanel.add(lblHello_1, 232, 249);
// TODO Auto-generated constructor stub
}
public void buttonOne()
{
this.absolutePanel.clear();
Button but1 = new Button("button one");
this.absolutePanel.add(but1);
}
}
I tried something like this, but it does not update the panel with a new button
private PanelHandle pHandle = new PanelHandle();
private static buttonHandleUiBinder uiBinder = GWT
.create(buttonHandleUiBinder.class);
#UiField Button button;
#UiField Button button_1;
interface buttonHandleUiBinder extends UiBinder<Widget, buttonHandle> {
}
public buttonHandle() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("button")
void onButtonClick(ClickEvent event) {
Window.alert("hello buttone clicked");
pHandle.buttonOne();
}
#UiHandler("button_1")
void onButton_1Click(ClickEvent event) {
}
}
So far I tried to call the method in my PanelHandle class, but I am encountering errors such stack overflow. In another method I tried, I am unable to update the panel when I add.
I am using a button here instead of panel just for testing until I understand the logic.
Thank You for you help!
Create an own (gwt)event when a button is clicked. You can fire your own event wherever you want. Fill the event with the information you need.
Next add the class which have to handle this event to the gwt eventbus. If a event is fired, your handle class catch the event and work with the data from the event.
This could be helpful: How to use the GWT EventBus
I have the following parent container:
public class ParentContainer extends Composite {
// Contains a bunch of TextButtons (RedButton, GreenButton, etc.).
private LayoutPanel buttonPanel;
// When user clicks a TextButton inside the buttonPanel,
// it changes the content of this contentPanel.
private LayoutPanel contentPanel;
}
So when the user clicks one of the TextButtons inside the buttonPanel, the contentPanel's contents change. I am trying to get each TextButton click to be remembered in history, using the Activities/Places framework. So, if the user clicks the "Red", "Green" and "Blue" buttons respectively, the contentPanel will change three times, and then they can click the Back/Forward browser history buttons and keep moving back and forth in history (and "replaying" the button clicks over and over again, etc.).
I also have the following classes:
com.mywebapp
MainModule.gwt.xml
com.mywebapp.client
MainModule
com.mywebapp.client.places
RedButtonPlace
GreenButtonPlace
BlueButtonPlace
... 1 place for all buttons
com.mywebapp.client.activities
RedButtonActivity
GreenButtonActivity
BlueButtonActivity
... 1 activity for all buttons
com.mywebapp.client.ui
ParentContainer
RedButton
GreenButton
BlueButton
BlackButton
PurpleButton
OrangeButton
I am planning on wiring things up such that:
PlaceController.goTo(new RedButtonPlace()) eventually routes to the RedButtonActivity
PlaceController.goTo(new GreenButtonPlace()) eventually routes to the GreenButtonActivity
etc. (every button has a place and activity per its color)
What I'm stuck on is: if I call PlaceController.goTo(new RedButtonPlace()) from inside a RedButton click handler, how and where do I instruct RedButtonActivity to update contentPanel? For instance:
public class RedButton extends TextButton {
// ... bunch of stuff, nevermind why I am extending TextButton
// this is just to help me connect all the major dots of GWT!
public RedButton() {
this.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// If the RedButton is clicked, we want all the content in RedButtonActivity#RedButtonView
// to go inside ParentContainer#contentPanel.
PlaceController.goto(new RedButtonPlace());
}
});
}
}
public class RedButtonActivity extends AbstractActivity {
public interface RedButtonView extends IsWidget {
// Whatever the RedButton expects to be able to display.
}
private RedButtonView view;
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
// Probably injected via GIN.
view = somehowInjectTheView();
panel.setWidget(view);
}
}
That last line is the key here: panel.setWidget(view). How do we make sure that panel is the ParentContainer#contentPanel? Thanks in advance!
Edit: Per one answer suggests, here is a code update:
public class ParentContainer extends Composite {
// All the stuff that's up above in the first parent container.
public ParentContainer() {
super();
// Again, via GIN.
ActivityManager redButtonActivityManager = getSomehow();
redButtonActivityManager.setDisplay(contentPanel);
}
}
If this is the correct way, then I assume when the start(AcceptsOneWidget panel, EventBus eventBus) method is called, the redButtonActivityManager knows to inject the correct display for the panel argument?
You would pass the ParentContainer#contentPanel to the setDisplay() method of your ActivityManager as part of the manager's initialization.
Hi I use GWT and I have a com.smartgwt.client.widgets.Button that has the following eventHandler:
Button viewCommentsButton = new Button("View ");
viewCommentsButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (!childrenVisible) {
addChildren();
getParent().setTitle("Close");
} else {
removeChildren();
getParent().setTitle("View");
}
}
});
As you can see I tried getParent().setTitle() method but with no effect. The if works fine so I guess I can't get the reference to my button object but the code compiles and getParent returns a widget so most likely my button.
However, the addChildren and removeChildren methods are working properly but my button has the initial title all the time. Any ideas why? Hope this makes sense.
Any suggestions are welcomed. Thanks.
If you are trying to set the title on viewCommentsButton, call viewCommentsButton.setTitle().
If you are trying to set the text in the button, call viewCommentsButton.setText().
For either of these you'll have to mark the button as final - declare it with final Button viewCommentsButton = ...
The context of getParent() is confusing. getParent(), the way you're using it, will return the parent of the widget in which you're defining all of this, NOT the parent of viewCommentsButton and definitely not viewCommentsButton itself.
Make your button a class variable, rather than a method variable and than you would be able to use it (refer it) inside the click handler.
For example:
viewCommentsButton = new Button("View "); //viewCommentButton is the private member.
viewCommentsButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (!childrenVisible) {
addChildren();
viewCommentButton.setTitle("Close");
viewCommentButton.setText("Close");
} else {
removeChildren();
viewCommentButton.setTitle("View");
viewCommentButton.setText("View");
}
}
});
You should use setText
setTitle is the "tooltip"
I am working on a swing gui which have many buttons. I have many actions in which buttons disable and enable at times. I want to set tooltips for only enabled buttons. When the button disables I don't want any tooltip for that button.
I would try extending the Button class, and overloading getTooltip(). Something like:
public class MyButton extends JButton {
public String getTooltip() {
if (this.isEnabled()) {
return super.getTooltip();
}
return null;
}
}
Of course, this depends on Swing using getTooltip to get the info to draw the button; anyway I would try it.
Add an extended JButton class:
import javax.swing.*;
public class MyButton extends JButton
{
private String toolTip;
#Override
public void setToolTipText(String text)
{
super.setToolTipText(text);
if (null != text) toolTip = text;
}
#Override
public void setEnabled(boolean b)
{
super.setEnabled(b);
super.setToolTipText(b ? toolTip : null);
}
}
and use it instead.
You have to remove tooltip text.
You can also create your own class with overriden methods for enable/disable and doing it automatically.