How to link JCheckBoxMenuItem to JInternalFrames controlled by the checkbox - java

I have a JFrame which creates a JInternalFrame which in turn creates JInternalFrames inside itself. The 'outer' JIF has an 'Add Frames' button with a checkbox menu so each 'inner' JIF type can only be created once. There may be up to 6 'inner' JIFs (code example restricted to 2, FRAME A & B).
Creating the inner JIFs works fine, BUT when user deselects a checkbox, how do I find the right inner JIF to close?
And if user closes an inner JIF, how do I link that back to unchecking the right checkbox?
Methods I've tried end up closing ALL the inner JIFs, or if I try to search the list of open JIFs and match their title to the checkbox field, compiler says the info is not available at this time.
Simplified code for the Outer & Inner JIF creation is as shown. Don't tell me I need a layout manager - the JIFs have to be user-movable and resizeable without restraint.
class OUTJIF extends JInternalFrame {
OUTJIF() {
JInternalFrame outerJIF = new JInternalFrame("Outer JInternalFrame", true, true, true, true);
outerJIF.setBounds(50, 50, 600, 400);
outerJIF.getContentPane().setLayout(null);
JButton btnAddFrames = new JButton("Add Frames");
btnAddFrames.setBounds(10, 11, 125, 23);
outerJIF.getContentPane().add(btnAddFrames);
JPopupMenu popMenu = new JPopupMenu();
JCheckBoxMenuItem boxFrameA = new JCheckBoxMenuItem("Frame A");
JCheckBoxMenuItem boxFrameB = new JCheckBoxMenuItem("Frame B");
popMenu.add(boxFrameA);
popMenu.add(boxFrameB);
btnAddFrames.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
popMenu.show(e.getComponent(), e.getX(), e.getY());
}
});
Demo.mainPane.add(outerJIF); // add to invoking JFrame
outerJIF.setVisible(true);
// Class for internal JIF
class intJIF extends JInternalFrame {
intJIF(String intType, int x, int y, int h, int w) {
JInternalFrame innerJIF = new JInternalFrame(intType, true, true, true, true) ;
innerJIF.setBounds(new Rectangle(x, y, h, w));
outerJIF.getContentPane().add(innerJIF);
innerJIF.setVisible(true);
// ISSUE #2 - IF USER CLOSES ONE OF THESE, HOW TO CHANGE CHECKBOX MENU?
}
};
// LISTENERS FOR outerJIF MENU ITEMS
ActionListener listFrameA = new ActionListener() {
public void actionPerformed(ActionEvent event) {
AbstractButton boxFrameA = (AbstractButton) event.getSource();
boolean selected = boxFrameA.getModel().isSelected();
if (selected) { new intJIF("Inner Frame A", 0, 100, 250, 250); }
else { // ISSUE #1 - HOW TO FIND THE RIGHT INTERNAL JIF TO CLOSE?
}
} };
boxFrameA.addActionListener(listFrameA);
ActionListener listFrameB = new ActionListener() {
public void actionPerformed(ActionEvent event) {
AbstractButton boxFrameB = (AbstractButton) event.getSource();
boolean selected = boxFrameB.getModel().isSelected();
if (selected) { new intJIF("Inner Frame B", 50, 50, 250, 250); }
else { // ISSUE #1 - HOW TO FIND THE RIGHT INTERNAL JIF TO CLOSE?
}
} };
boxFrameB.addActionListener(listFrameB);
}
}

I define GUI components as class members when I need to add listeners to them. So if I make the JInternalFrame and the JCheckBox class members, then in the ActionListener of the JCheckBox I can close the JInternalFrame. Similarly I can add an InternalFrameListener to the JInternalFrame and update the JCheckBox in the internalFrameClosing() method. It appears - from the code you posted - that you are unfamiliar with InternalFrameListener. If that is the case, then I suggest reading How to Write an Internal Frame Listener. If you would like more specific help, then for me, you need to post more of your code so that I can download it and run it.

Related

How to add mouse listener to JOptionPane button?

I want to change appearance of Button on JOptionPane.ShowMessageDialog.
I have managed to change Button caption with
UIManager.put("OptionPane.okButtonText", "Text I want");
Now, my next goal is to make Button work same as buttons in rest of my app. That is, when hovering mouse over it, it changes background and font color.
On rest of my buttons I added mouse listener like this one:
//setting change color on hover
private final MouseListener mouseAction = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(163, 184, 204));
rollOver.setForeground(Color.WHITE);
rollOver.setFont(b);
}
};
#Override
public void mouseExited(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(230, 230, 230));
rollOver.setForeground(Color.BLACK);
rollOver.setFont(f);
}
};
};
Previously in code I have Font varibles set:
Font f = new Font("System", Font.PLAIN, 12);
Font b = new Font("System", Font.BOLD, 12);
I could make new dialogs from scratch and implent this behaviour but that would be overkill.
Is there some way to access Button on JOptionPane and add mouse listener
to it?
UIManager.put("OptionPane.okButtonText", "Text I want");
The above will change the text for all "Ok" buttons on all JOptionPanes that you create.
If you want to change the text on an individual button on a specific JOptionPane then
read the section from the Swing tutorial on Customizing Button Text.
Is there some way to access Button on JOptionPane and add mouse listener to it?
When you use the static showXXX(...) methods a modal JDialog is created so you don't have access to the dialog or its components until the dialog is closed which is too late.
So instead you need to manually create the JOptionPane and add it to a JDialog. The basics of doing this can be found by reading the JOptionPane API and looking at the section titled "Direct Use".
Once you have created the JOptionPane (and before you make the dialog visible) you can then search the option pane for the buttons and add a MouseListener to each button. To help you with this you can use the Swing Utils class. It will do a recursive search of the option pane and return the buttons to you in a List. You can then iterate through the List and add the MouseListener.
The basic code using this helper class would be:
JOptionPane optionPane = new JOptionPane(
"Are you sure you want to exit the application",
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_CANCEL_OPTION);
List<JButton> buttons = SwingUtils.getDescendantsOfType(JButton.class, optionPane, true);
for (JButton button: buttons)
{
System.out.println( button.getText() );
}
If you want to see the same effect inside all OptionPanels, I think the override BasicOptionPaneUI is a good solution
This is a minimal example
public class MyOptionPaneUI extends BasicOptionPaneUI {
#SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
public static ComponentUI createUI(JComponent c) {
return new MyOptionPaneUI();
}
private static final MyMouseListener m = new MyMouseListener();
#Override
public void update(Graphics g, JComponent c) {
super.update(g, c);
}
#Override
protected void installListeners() {
JButton button = (JButton) getButtons()[0];
button.addMouseListener(m);
super.installListeners();
}
#Override
protected void uninstallListeners() {
JButton button = (JButton) getButtons()[0];
button.removeMouseListener(m);
super.uninstallListeners();
}
public static class MyMouseListener extends MouseAdapter{
#Override
public void mouseEntered(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(163, 184, 204));
rollOver.setForeground(Color.WHITE);
}
};
#Override
public void mouseExited(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(230, 230, 230));
rollOver.setForeground(Color.BLACK);
}
};
}
}
inside your frame your main class you can add this code for load the class inside the UIDefoult
static{
UIManager.put("OptionPaneUI", MyOptionPaneUI.getClass().getCanonicalName());
}
Because getButtons()[0], because I see this code inside the BasicOptionPaneUI
else if (type == JOptionPane.OK_CANCEL_OPTION) {
defaultOptions = new ButtonFactory[2];
defaultOptions[0] = new ButtonFactory(
UIManager.getString("OptionPane.okButtonText",l),
getMnemonic("OptionPane.okButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.okIcon"), minimumWidth);
defaultOptions[1] = new ButtonFactory(
UIManager.getString("OptionPane.cancelButtonText",l),
getMnemonic("OptionPane.cancelButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.cancelIcon"), minimumWidth);
} else {
defaultOptions = new ButtonFactory[1];
defaultOptions[0] = new ButtonFactory(
UIManager.getString("OptionPane.okButtonText",l),
getMnemonic("OptionPane.okButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.okIcon"), minimumWidth);
}
inside the method protected Object[] getButtons()
If you want the effect mouse hover on the button I'm working on this library and have the solution for the mouse over.
If you have a possibility to personalize the DefaoultButton inside the library with this constant
UIManager.put("Button[Default].background", new Color(163, 184, 204));
UIManager.put("Button[Default].foreground", Color.WHITE);
UIManager.put("Button[Default].mouseHoverColor", new Color(230, 230, 230));
ps: this is only information if you need to add the mouse hover inside the you project

Java: Adding events to dynamically created components

I'm building a UI in Java. I want to create new components, like a JLabel, using a button. So every time I click a button it creates a new JLabel and places them in a specific JPanel.
Then, I want to be able to do some things with the labels based on how the user clicks on them.
With a left mouse press I want them to be able to drag the labels around the screen.
With a right mouse click I want to be open a new window where certain data can be entered, tied to the label (which might involve dynamically creating variables).
I've been toying around with some code I've Googled around for. I can get a button to create new labels in a panel, but when I try to get them to drag, I can only get one label at a time to appear, and after a second button press, moving the label isn't smooth, it jumps around.
I haven't even tried to implement any of the right mouse click things yet. If anyone can point me in the right direction, I'd appreciate it.
public class Testing {
JFrame frame;
//Launch the application.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
Testing window = new Testing();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//Create the application.
public Testing() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
JPanel area;
JButton btnCreate;
JLabel dragLabel;
frame = new JFrame();
frame.setBounds(100, 100, 511, 542);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setVisible(true);
area = new JPanel();
area.setBounds(10, 11, 477, 404);
frame.getContentPane().add(area);
area.setLayout(new BorderLayout());
btnCreate = new JButton("Create Label");
dragLabel = new JLabel("Drag Me");
btnCreate.setBounds(10, 425, 477, 67);
frame.getContentPane().add(btnCreate);
btnCreate.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
area.add(dragLabel);
area.revalidate();
DragListener drag = new DragListener();
dragLabel.addMouseListener(drag);
dragLabel.addMouseMotionListener(drag);
}
});
}
}
class DragListener extends MouseInputAdapter
{
Point location;
MouseEvent pressed;
public void mousePressed(MouseEvent me) {
pressed = me;
}
public void mouseDragged(MouseEvent me)
{
if(SwingUtilities.isLeftMouseButton(me)){
Component component = me.getComponent();
location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}
}
}
EDIT - I'm fairly certain the primary issue is in how the JLabel itself is being added to the panel. Every time the button is being pushed it's adding the same label over again, and this is gumming up the works.
Unfortunately, I'm not sure how to deal with that. I've done a bit more digging, and since dynamic variables aren't possible, I'm going to have to use an array or a map or some sort. With that, it appears I can declare arrays of components. Would something like that be necessary for my purposes?
Really odd stuff in your code. I don't want to go everything, and I'm not an expert by any stretch of the imagination, but I tried to remove redundant or contradictory stuff. I suspect a part of what you did was just copy pasting bits without really fitting them into the code.
Anyway, you needed to create the label inside the listener, so that it creates a new one everytime you click. Otherwise you only ever create one label and just reuse the same everytime.
I implemented a dialog on right click to enter the label name, don't know what you wanted to do but at least it detects right clicks.
Also in general it's easier to use layout managers instead of hardcoding everything. Here you had a borderlayout but were ignoring it.
class Main {
//Launch the application.
public static void main(String[] args) {
DrageableLabel window = new DrageableLabel();
}
}
public class DrageableLabel {
public DrageableLabel() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
JFrame frame = new JFrame();
Container area = frame.getContentPane();
area.setLayout(new BorderLayout());
JButton btnCreate = new JButton("Create Label");
btnCreate.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
/*
This is where you create your new window
for now I've added a dialog that takes a string parameter and creates a label with that string
I moved the method code to create a new drageable label outside the actionlistener to make it less confusing and reuseable
Either build w-e you want directly in here
or call a method that does it (which I prefer)
*/
String string = JOptionPane.showInputDialog(frame, "Enter your message", "Messages", JOptionPane.CANCEL_OPTION);
addDrageableLabel(string, area);
} else if (SwingUtilities.isLeftMouseButton(e)) {
addDrageableLabel("Drag me", area);
}
}
});
area.add(btnCreate, BorderLayout.SOUTH);
frame.setBounds(100, 100, 511, 542);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
// This is the method that creates and adds a drageable label
public void addDrageableLabel(String labelName, Container container) {
JLabel dragLabel = new JLabel(labelName);
container.add(dragLabel, BorderLayout.CENTER);
container.validate();
DragListener drag = new DragListener();
dragLabel.addMouseListener(drag);
dragLabel.addMouseMotionListener(drag);
}
}
class DragListener extends MouseInputAdapter {
Point location;
MouseEvent pressed;
#Override
public void mousePressed(MouseEvent me) {
pressed = me;
}
#Override
public void mouseDragged(MouseEvent me) {
Component component = me.getComponent();
location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}
}

JOptionPane always returning -1

I want to double check the delete operation to prevent accidental deletion.
(Here the Yes button would only be enabled if the checkbox is checked.)
But both Yes and No Buttons are returning -1.
This is a snippet of my program.
public class class1 extends javax.swing.JInternalFrame {
JCheckBox cbConfirmDelete;
JPanel outer = new JPanel(new BorderLayout());
final JButton btnYes = new JButton("Yes");
final JButton btnNo = new JButton("No");
public class1() {
......
//Button btnYes ActionListener for JOptionPane
btnYes.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = getOptionPane((JComponent) e.getSource());
pane.setValue(btnYes);
}
});
//Button btnNo ActionListener for JOptionPane
btnNo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = getOptionPane((JComponent) e.getSource());
pane.setValue(btnNo);
}
});
//layout for JOptionPane
JPanel nested1 = new JPanel();
nested1.add(cbConfirmDelete);
JPanel nested2 = new JPanel();
nested2.add(btnYes);
nested2.add(btnNo);
outer.add(nested1, BorderLayout.NORTH);
outer.add(nested2, BorderLayout.CENTER);
}
protected JOptionPane getOptionPane(JComponent parent) {
JOptionPane pane = null;
if (!(parent instanceof JOptionPane)) {
pane = getOptionPane((JComponent) parent.getParent());
} else {
pane = (JOptionPane) parent;
}
return pane;
}
private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {
int dialogResult = JOptionPane.showOptionDialog(null, "Are you sure you want to Delete the Reference ?", "Delete Reference", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{outer}, btnYes);
System.out.println("DialogResult: " + dialogResult);
}
}
The Output DialogResult is always -1. Why is that happening ?
If I pass the following object in JOptionPane it works fine..
new Object[]{cbConfirmDelete, btnYes, btnNo}
But this is not working
new Object[]{outer}
I see a couple of problems here. Since you're creating a Yes/No option dialog, your Object[] array should contain two, and only two, components that correspond to yes or no.
For your example that works, your Object[] array contains the checkbox, the yes button, and the no button. That's one too many components. When you set the pane value in the yes or no action listener, you're setting it to 1 or 2 instead of 0 or 1, since positionally, those components are the second and third. This isn't necessarily a big problem, but usually when you return from a yes/no dialog box, you check for JOptionPane.YES_OPTION (0) or JOptionPane.NO_OPTION (1) to see if the user chose yes or no. In your scenario, you're going to have to check for 1 or 2 since the checkbox is component 0.
For your non-working scenario, the problem is that your object array only contains one object, the outer panel containing the checkbox and the yes/no buttons. Technically what's happening is that you're telling the option pane that there's only one selectable component, a JPanel. Calling pane.setValue() with any component other than the outer panel will have no effect, since the pane's selection value is -1 (uninitialized value) to begin with, and it will only change if you call setValue(outer).

How can I click on a picture and then make that picture appear in a new JFrame? [duplicate]

This question already has answers here:
How to find JLabel that was clicked and show ImageIcon from it?
(2 answers)
Closed 7 years ago.
I have a JFrame opening with 12 different pictures. I want to click on one and then in the new JFrame, show that same picture. In my code, shirts is my JFrame with the 12 pictures and I want the clicked picture to appear in the new JFrame called sizes. I made an ArrayList of type JLabel called select. Here is my code:
final JFrame shirts = new JFrame("T-shirts");
JPanel panel = new JPanel(new GridLayout(4, 4, 3, 3));
for (int i = 1; i < 13; i++) {
l = new JLabel(new ImageIcon("T-shirts/"+i+".jpg"), JLabel.CENTER);
l.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
l.setFont(l.getFont().deriveFont(20f));
panel.add(l);
select.add(l);
}//end of for loop
panel.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
sizes = new JFrame("Shopping");
sizes.setVisible(true);
sizes.setSize(500, 500);
sizes.setLocation(100,200);
shirts.dispose();
for(int i=0; i<12; i++){
if(e.getSource()==select.get(i)){
JLabel addition = newJLabel(newImageIcon(select.get(i).getText()));
//sizes.add(select.get(i));//Picture isn't added!!
}//end of if
}//end of for
}//end of method
});//end of listener
shirts.setContentPane(panel);
shirts.setSize(1000, 1000);
shirts.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shirts.setVisible(true);
Start with How to Write a Mouse Listener.
Basically, you want to register a MouseListener with the JLabel which represents your picture and implement it's mouseClicked method.
You then want to get the Icon property of the JLabel that was clicked and pass that to your new frame, which you can simply use to set the Icon property of another JLabel
Something like...
addition.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
JLabel label = (JLabel) e.getComponent();
Icon icon = label.getIcon();
// Create new frame and pass it the icon value
}
});
as an example
You might also like to take a look at The Use of Multiple JFrames, Good/Bad Practice? and consider using either a CardLayout or JDialog instead of another JFrame ... which could become messy
You can use a JButton and make it look like a JLabel:
JButton button = new JButton( new ImageIcon("..." ));
button.setBorderPainted( false );
button.setContentFilled( false );
button.setFocusPainted( false );
button.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JButton button = (JButton)e.getSource();
Icon icon = button.getIcon();
// do something with the Icon.
}
});
Then you can add an ActionListener to the button.
An ActionListener is more reliable than using a MouseListener and handling the mouseClicked event. The mouseClicked event is only generated when a mousePressed and mouseReleased event is generated at the same mouse point. So if the mouse moves by even pixel between the two event you will not get a mouseClicked event which users think is a random problem.
Try making each picture a JButton, or at least placing an invisible button behind each picture. Then, when they are pressed in the ActionListener extended class, have the new JFrame be created, with the picture large.

JColorChooser and JFileChooser open problem

I want to show the dialogs JColorChooser and JFileChooser programmatically from
a method called when I submit a buttons.
After the button is clicked the method is invoked but the dialogs won't display.
I have a JFrame with a null layout (absolute positioning) and, e.g., the following code:
public class _TEST_ extends JFrame
{
private JColorChooser color_chooser;
private JFileChooser file_chooser;
public _TEST_()
{
super("_TEST_");
setLayout(null);
final JButton b = new JButton("Color chooser");
final JButton b2 = new JButton("File chooser");
ActionListener al = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == b)
{
createJColorChooser();
}
else if (e.getSource() == b2)
{
createJFileChooser();
}
}
};
b.addActionListener(al);
b2.addActionListener(al);
b.setBounds(1, 1, 160, 20);
b2.setBounds(1, 30, 160, 20);
add(b);
add(b2);
}
public void createJColorChooser()
{
color_chooser = new JColorChooser();
color_chooser.setBounds(1, 70, 225, 50);
add(color_chooser);
repaint();
}
public void createJFileChooser()
{
file_chooser = new JFileChooser();
file_chooser.setBounds(330, 70, 225, 50);
add(file_chooser);
repaint();
}
public static void main(String args[])
{
_TEST_ window = new _TEST_();
window.setSize(800, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setLocationRelativeTo(null);
}
}
what's wrong?
If you are adding to a frame that has already been made visible, you need to revalidate the frame:
frame.validate();
From the JavaDocs for frame.add(...):
Note: If a component has been added to a container that has been displayed, validate must
be called on that container to display the new component.
If you want to make the color chooser show in a separate dialog (the usual approach), do this:
final Color color = JColorChooser.showDialog(null, "Choose a color", Color.BLUE);
For JFileChooser here is a typical approach:
JFileChooser ch = new JFileChooser();
ch.showOpenDialog(null);
The JavaDocs for these two dialogs have good working examples.
(See the comments in #Steve McLeod's answer for context.)
JColorChooser and JFileChooser are not regular JComponents. You can add them to a container but you don't see anything because JColorChooser's UI doesn't paint, and JFileChooser doesn't even have a UI.
As in Steve's answer, you can use JColorChooser#showDialog and JFileCHooser#showOpenDialog to get modal dialog, which is the right way to use them.
If you really want, you can call JColorChooser#createDialog then grab its content pane (you could do this for any top-level container):
public void createJColorChooser()
{
...
add(JColorChooser.createDialog(this, "", false, color_chooser, null, null).getContentPane());
...
}
And you could override JFileChooser to publicize its createDialog, but please, please don't do that. File chooser should always be modal dialogs.
Generally I add components to a specific panel and not the frame directly so I would use:
panel.add( someComponent );
panel.revalidate();
panel.repaint(); // sometimes required
But in this case you can just use the validate() method:
color_chooser.setSize( color_chooser.getPreferredSize() );
add(color_chooser);
validate();
repaint();
file_chooser.setSize( file_chooser.getPreferredSize() );
add(file_chooser);
validate();
repaint();
Edit: of course you should also use the preferred size of the component so that the entire component is visible. Now all you need to do is add all the code to respond when a user makes a selection. That is a lot of work, which is why it is better to use the dialog version of each class.

Categories