I'm trying to create JPanel with two different buttons which one of them increasing and second decreasing size of text or window. I have class with button declaration. Everything is working when I put these buttons on JFrame separately.
I don't know how to get Action Listener in JPanel of each buttons. All I possibly do is listener of mouse click on JPanel...
Could you help me? I'm really begginer with coding so be polite please :]
public class ButtonMy extends Component {
private ButtonIncrease increase;
private PropertyChangeSupport propertyChangeSupport;
public ButtonMy() {
setPreferredSize(new Dimension(30,30));
kolor = Color.blue;
setForeground(kolor);
propertyChangeSupport = new PropertyChangeSupport(this);
increase = ButtonIncrease.Powieksz;
}
public ButtonIncrease getIncrease() {
return increase;
}
public void setIncrease(ButtonIncrease increase) {
ButtonIncrease oldIncrease = this.increase;
this.increase = increase;
propertyChangeSupport.firePropertyChange("increase", oldIncrease, increase);
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
There is JPanel for bind 2 buttons. Here is the biggest problem :/ I'm lack of ideas.
public class ButtonB extends JPanel implements ActionListener{
public ButtonMy b1 = new ButtonMy();
public ButtonMy b2 = new ButtonMy();
public ButtonB (){
init();
}
public final void init(){
setLayout(new GridLayout(1,2));
this.przycisk1.setIncrease(ButtonIncrease.Powieksz);
this.przycisk2.setIncrease(ButtonIncrease.Zmniejsz);
add(b1);
add(b2);
}
}
JFrame where I test this component is very common. Code below shows only function for inc and dec size when separate button is clicked (not in JPanel).
private void buttonMy3MouseClicked(java.awt.event.MouseEvent evt) {
switch(buttonMy3.getIncrease()) {
case Powieksz: setSize(1);
break;
case Zmniejsz: setSize(0);
break;
}
}
I didn't paste full of my code. There some of math functions left which I think they are not needed here (setSize for example).
I'm not sure if i understand the problem correctly but I think under the actionListener class you should have a method called actionPerformed& it will say that if button1 is clicked increase the number, if button2 is clicked decrease the number:
public void actionPerformed( ActionEvent event ) {
if (event.getSource()== b1) // your "increase size" code
if(event.getSource()== b2)// your "decrease size" code
}
button listeners are actually different from mouse listeners; buttons implements ActionListeners and have the actionPerformed method with event variable. you could handle the event by:
getSource() -this method is inherited from java.util.EventObject and returns the OBJECT on which the event initially occurred (the button itself)
or by getActionCommand() -this method is available to action events, or any event that inherits from ActionEvent and returns the command STRING associated with this action.
however mouse listeners implements MouseListener and has a lot of methods depending on what the mouse does (pressed, clicked, released, etc.).
Related
How would I call an Action from another class in Java? I got a CloseTabButton class online that allows a simple close tab button on each JTabbedPane, but when the tab is closed, I would like a dialog to pop up based on information (if file is not saved, ask to save it, etc.). This is the file:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class CloseTabButton extends JPanel implements ActionListener {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
close.addActionListener(this);
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
#Override
public void actionPerformed(ActionEvent e) {
int i = pane.indexOfTabComponent(this);
String fileName = pane.getToolTipTextAt(i);
// Where I want to ask if user wants to save, etc.
if (fileName == "Untitled") {
// Do stuff
}
pane.remove(i); // Removes the tab
// If tab count < 1, then disable the save and save as buttons on menu
if (pane.getTabCount() < 1) {
JFrame frame = (JFrame) pane.getParent().getParent().getParent().getParent().getParent(); // Yes, there is that many in my code to get the parent JFrame
int menuCount = frame.getJMenuBar().getMenuCount();
for (int a = 0; a < menuCount; a++) {
int itemCount = frame.getJMenuBar().getMenu(a).getItemCount();
for (int b = 0; b < itemCount; b++) {
Component component = frame.getJMenuBar().getMenu(a).getMenuComponent(b);
if (!(component instanceof JSeparator)) {
// Not a seperator
String itemName = frame.getJMenuBar().getMenu(a).getItem(b).getAccessibleContext().getAccessibleName();
if (itemName == "Save As..") {
frame.getJMenuBar().getMenu(a).getItem(b).setEnabled(false);
}
}
}
}
}
}
}
In my main class I have actions listed like this:
static Action Close = new AbstractAction("Close") {
public void actionPerformed(ActionEvent e) {
closeCurrentWindow(); // function that will close tab
}
}
The other menu items are Actions as well, and as you can see, what I'm currently doing in the CloseTabButton class is quite frustrating, and most likely the wrong way to code it. Is there a much simpler way to do what I'm doing?
The first thing I might do is provide ActionListener support to the CloseTabButton, for example...
public class CloseTabButton extends JPanel {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
close.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
fireActionPerformed();
}
});
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
protected void fireActionPerformed() {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "You could provide you own action command for each tab here");
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
Basically, this now allows you to register your own ActionListeners to the CloseTabButton
Next, this, fileName == "Untitled", is not how you compare Strings in Java, you should be using something more like "Untitled".equals(fileName)
If you're menus are based on actual Actions, then you can simply disable the Actions themselves. This would require a little bit of work, but a lot less of "guess" work then you're doing now.
Basically, you would monitor the JTabbedPane itself, monitoring for changes to the selected tab and updating the states of the individual Actions themselves
There a number of ways you could do this, like passing a reference of the JTabbedPane to the Actions so they can perform there own monitoring (but I'd use some kind of management interface which could more easily provide information to the Actions and decouple the code and the reliance on JTabbedPane directly, then you could be free to use JInternalFrames instead).
You could have a "menu manager" which did a similar job, monitoring changes to the document container and changing the state of the menu Actions based on the current state, as an example
Updated
If you're making use of the Action API (which I would recommend), then you could simply do something like...
public class CloseTabButton extends JPanel {
private JTabbedPane pane;
public CloseTabButton(JTabbedPane pane, Action action, int index) {
this.pane = pane;
setOpaque(false);
// CloseIcon class just had a button with an x painted on it
Icon closeIcon = new CloseIcon();
JButton close = new JButton(action);
close.setIcon(closeIcon);
close.setPreferredSize(new Dimension(closeIcon.getIconWidth(), closeIcon.getIconHeight()));
add(new JLabel(pane.getTitleAt(index), pane.getIconAt(index), JLabel.LEFT));
add(close);
pane.setTabComponentAt(index, this);
}
}
Passing in the Action for the close operation, then use the same action for both the JMenuItem and JTabbedPane.
The "core" issue would be how you would identify the "current" tab and document in a uniform manner
I have a JPanel with a bunch of different check boxes and text fields, I have a button that's disabled, and needs to be enabled when specific configurations are setup.
What I need is a listener on the the whole JPanel looking for events, whenever anything changes.
I believe I need an action listener but I can't find anything to bridge the action Listener with the JPanel
JPanel Window = new JPanel();
Window.addActionListener(new ActionListener(){
//Check if configurations is good
}
I figure I can copy and paste my code a bunch of times into every listener in the panel, but that seems like bad coding practice to me.
First off as #Sage mention in his comment a JPanel is rather a container than a component which do action. So you can't attach an ActionListener to a JPanel.
I figure I can copy and paste my code a bunch of times into every
listener in the panel, but that seems like bad coding practice to me.
You're totally right about that, it's not a good practice at all (see DRY principle). Instead of that you can define just a single ActionListener and attach it to your JCheckBoxes like this:
final JCheckBox check1 = new JCheckBox("Check1");
final JCheckBox check2 = new JCheckBox("Check2");
final JCheckBox check3 = new JCheckBox("Check3");
final JButton buttonToBeEnabled = new JButton("Submit");
buttonToBeEnabled.setEnabled(false);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean enable = check1.isSelected() && check3.isSelected();
buttonToBeEnabled.setEnabled(enable);
}
};
check1.addActionListener(actionListener);
check2.addActionListener(actionListener);
check3.addActionListener(actionListener);
This means: if check1 and check3 are both selected, then the button must be enabled, otherwise must be disabled. Of course only you know what combination of check boxes should be selected in order to set the button enabled.
Take a look to How to Use Buttons, Check Boxes, and Radio Buttons tutorial.
A suggestion could be to derive a class from each of the components you're using and add an ActionListener that bubbles up the Container tree and looks for the first Container that implements a custom interface like this:
public interface MyCommandProcessor {
void execute(String actionCommand);
}
public class MyButton extends JButton {
public MyButton(string actionCommand) {
setActionCommand(actionCommand);
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
Container traverser = MyButton.this;
while (traverser != null && !(traverser instanceof MyCommandProcessor))
traverser = traverser.getParent();
if (traverser != null)
((CommandListener)traverser).execute(ae.getActionCommand());
}
});
}
}
public class MyApp extends JFrame implements MyCommandListener {
public MyApp() {
JPanel panel = new Panel();
panel.add(new MyButton("MyButton got pressed"));
}
public void execute(String actionCommand) {
System.out.println(actionCommand);
}
}
You need to create custom component listener. Look here:
Create a custom event in Java
Creating Custom Listeners In Java
http://www.javaworld.com/article/2077333/core-java/mr-happy-object-teaches-custom-events.html
I do it throw the standard ActionListener
Example
public class MyPanel extends JPanel {
private final JComboBox<String> combo1;
private final JButton btn2;
.......
//catch the actions of inside components
btn2.addActionListener(new MyPanelComponentsActionListener());
........
//assign actionlistener to panel class
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
//handle registered listeners from components used MyPanel class
protected void fireActionPerformed(ActionEvent event) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
ActionEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ActionListener.class) {
// Lazily create the event:
if (e == null) {
String actionCommand = event.getActionCommand();
if(actionCommand == null) {
actionCommand = "FontChanged";
}
e = new ActionEvent(FontChooserPanel.this,
ActionEvent.ACTION_PERFORMED,
actionCommand,
event.getWhen(),
event.getModifiers());
}
// here registered listener executing
((ActionListener)listeners[i+1]).actionPerformed(e);
}
}
}
//!!! here your event generator
class MyPanelComponentsActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//do something usefull
//.....
fireActionPerformed(e);
}
}
....
}
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 added a JPanel to a JRadioButton - so that I may display whatever I want in the radio button.
This all worked as expected. But to allow for text wrapping, I used a JTextArea and added it to the JPanel contained within the radio button.
Now I have an issue where, if the user clicks on the JTextArea, then the JTextArea consumes the mouseEvent and as a result there is no response from the radio button (it doesn't 'select').
Is there a way get the JTextArea to ignore the mouse click, so that the parent may handle it instead?
I tried add the JTextArea's listeners to the radioButton instead.
I also tried to remove its listeners completely, but both these attempts failed.
Anyone have any suggestions?
Strong beware
Most JSomething are not meant to be used as containers even though it's possible - the outcome of doing it anyway is more or less visually and behaviourally undetermined!
That said, did it recently, to implement something similar to a Windows task dialog. If the requirement includes keeping the button clickable (and why else would you mis-use it as a container :-) the main problem (layout apart) is to make all added components completely mouse-transparent. Which is more difficult than can be expected. The minimum is to not allow adding of mouseListeners and disable the acceptance of mouseEvents:
final JTextArea area = new JTextArea("replacement ..") {
#Override
public synchronized void addMouseListener(MouseListener l) {
LOG.info("adding here ...?");
}
#Override
public synchronized void addMouseMotionListener(
MouseMotionListener l) {
}
#Override
public synchronized void addMouseWheelListener(
MouseWheelListener l) {
}
#Override
public void addNotify() {
disableEvents(AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK);
super.addNotify();
}
};
Plus make sure it's not focusable
area.setEditable(false);
area.setFocusable(false);
area.setRequestFocusEnabled(false);
Plus unregister dragging and tooltips
ToolTipManager.sharedInstance().unregisterComponent(area);
area.setDragEnabled(false);
Nevertheless, there might still be surprises ahead, f.i. call the following twice (that is disable and enable again), which will internally re-enable mouseEvent:
area.setAutoscrolls(!area.getAutoscrolls());
So at the end of the day, we might get away with it - but never be entirely certain that we succeeded.
What about this? Create and add your own MouseListener to TextArea
JPanel p = new JPanel();
JTextArea t = new JTextArea("line \n line");
t.addMouseListener(new MyMouseListener());
p.add(t);
jRadioButton1.add(p);
jRadioButton1.addMouseListener(new MyRadioButtonMouseListener());
And in the MyMouseListener Dispatch event
private class MyMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
Component source = (Component) e.getSource();
source.getParent().getParent().dispatchEvent(e); // 2x getParent() because JTextArea->JPanel->JRadio
}
.
.
.
}
And finally RadioButtonMouseListener
private class MyRadioButtonMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("CLICK ON RADIOBUTTON !!");
}
.
.
.
}
this program suppose to create a window that has a status bar under it that shows how many times the mouse was clicked without being moved on the screen. when you move the mouse and click it suppose to start a new count. it also distinguishes different mouse buttons. I've followed this code exactly as a tutorial I saw, but it doesn't work. I just get the window with a status bar that never changes.
public class Adapter_class extends JFrame {
private String details;
private JLabel statusBar;
public Adapter_class() {
super("Adapter mouse:");
this.statusBar = new JLabel("Default");
add(this.statusBar, BorderLayout.SOUTH);
addMouseListener(new MouseClass());
}
private class MouseClass extends MouseAdapter {
public void MouseClicked (MouseEvent event) {
details = String.format("You clicked the mouse %d", event.getClickCount());
//this is for using a mouse from a mac
if (event.isMetaDown())
details += " with the right mouse button";
else if (event.isAltDown())
details += " with the center mouse button";
else
details += " with the left mouse button";
statusBar.setText(details);
}
}
}
this is the main:
import javax.swing.JFrame;
public class Adapter_main {
public static void main(String[] args) {
Adapter_class window = new Adapter_class();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400, 300);
window.setVisible(true);
}
}
You have written the method MouseClicked with capital M. Use the lower case version
public void mouseClicked(MouseEvent event) { ... }
Otherwise you are creating a new method and not override the adapter's one. You may also want to include a #Override annotation which would force the compiler to show you the issue.
public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener {
/**
* {#inheritDoc}
*/
public void mouseClicked(MouseEvent e) {}
Use this:
private class MouseClass extends MouseAdapter {
public void mouseClicked (MouseEvent event){
Here the function you have to write is **mouseClicked** not **MouseClicked**
Thats why it helps to use annotations.
#Override would have helped you immediately.