JOptionPane List Actions - java

I want change the icon property of an open JOptionPane upon clicking a list item. (They will correspond with each other)
Is there an equivalent to ActionListener for this? I know how to code for the buttons, unfortunately these actions are not easy?
JOptionPane.showInputDialog(null,
"SELECT A PRIMARY WEAPON FROM THE LIST",
"ARMOURY",
JOptionPane.OK_CANCEL_OPTION,
get.getIcon("shield_and_swords.png"),
character.weaponList(),
"Absolix Polearm")

This is not possible. The JOptionPane.showInputDialog documentation states:
It is up to the UI to decide how best to represent the selectionValues, but usually a JComboBox, JList, or JTextField will be used.
This means the actual GUI element used is implementation-defined and so there couldn't really be a general way to access it, or a consistent action interface to it (it might not even be a clickable list box, for example). Basically, you call showInputDialog() and you get a result back, but beyond that it's a black box and the actual GUI could be anything -- no guarantees are made.
Perhaps you could come up with some really dirty object tree hacks to find the GUI element in most cases, but... consider perhaps creating your own custom dialog with a predictable GUI that you can control instead.

Related

how to make a JTextArea have clickable buttons

As the title says I'm trying to make it so my JTextArea have some strings so that I can call other functions, like a hyperlink of sorts, can that be done?
For reference, I would like to know how the left side of any Tutorialspoint tutorial is made but in Java.
PS: I'm using a CardLayout.
EDIT: Something like this
Forget about using a JTextArea. Take a look at JList instead. This is Swing's basic list class. It supports the selection of one or more items from a list. Although often the list consists of strings, it is possible to create a list of just about any object that can be displayed.
Although a JList will work properly by itself, most of the time you will wrap a JList inside a JScrollPane, so long lists will automatically be scrollable.
A JList generates a ListSelectionEvent when the user makes or changes a selection. This event is also generated when the user deselects a n item. It is handled by implementing ListSelectionListener. This listener specifies only one method, which is called:
void valueChanged(ListSelectionEvent le)
Here, le is a reference to the object that generated the event. Although ListSelectionEvent does provide some methods of its own, often you will interrogate the JList object itself to determine what has occurred.
By default, a JList allows the user to select multiple ranges of items within the list, but you can change this behavior by calling setSelectionMode(int), which is defined by JList. The integer passed to this method must be one of the values defined by the ListSelectionModel interface:
SINGLE_SELECTION
SINGLE_INTERVAL_SELECTION
MULTIPLE_INTERVAL_SELECTION
You can obtain the selected values by calling getSelectedValuesList(), or, if you are using single selection, you can call getSelectedValue(). Once you have the selected the value(s), you can invoke the method(s) dedicated to that/those objects accordingly.
One last tip: In Java, they are called methods, not functions ;)
Happy programming!

how to make a pop-up window using java

I wanted a button to show a pop-up window, I tried using the
JOptionPane.showMessageDialog(null,"");
But I can't put my desired object such as the Table and List. Is it possible?
This is really poorly documented in the Java Docs, because all that tells you is that the "message" parameter is an Object, which can be anything - but does not go into specifics about what happens with different types of objects that may warrant special case handling.
As far as I have gathered from experimenting with it, the "message" can be a subtype of Component - then it will just place the component in the message area of the dialog box as-is, like:
JOptionPane.showMessageDialog(null, new JCheckBox("I'm a checkbox!"));
Otherwise, it will just call the toString method on the object, converting it into a string, which it then will just wrap in a label and place that in the dialog as the message.
But you can also pass in an Array of Objects, in which case it will just place each element in a separate row in the message area:
JOptionPane.showMessageDialog(null, new Object[] {
new JCheckBox("check"),
new JRadioButton("radio"),
"plain text"});
There might be other special cases, but I haven't found them yet.
That said, if what you want to display is a subclass of Component (or JComponent), just passing it in as the message parameter should work. If it doesn't, you might want to edit your question to describe whatever problems you are encountering in more detail, perhaps also providing some sample code.
Start by taking a closer look at the JOptionPane JavaDocs, showMessageDialog clearly states that it accepts a Object as the message parameter
One of the nice features of this, is if the Object is Component, it will be added to the dialog.
For example: JOptionPane displaying HTML problems in Java and How do i make the output come in different columns?

Listeners in forms with JComponents

Right now, when I have a form with many JComponents, mainly JTextFields, JTextAreas, JComboboxes, JCheckBoxes and JButtons and want to control their behaviour, for instance the change of focus after a certain key was released, I do the following:
I put all my components in a JComponent[] and cycle through it, adding the appropriate listener. When an event is registered by said listener, I check with "instanceof" what kind of JComponent fired the event and assign the proper reaction.
I use this method for instance to cycle with VK_ENTER through the form, or to "firePropertyChange(..)" after a DocumentListener fires, or to add UndoRedoListeners and so on.
My question : is there a better way to do this and if yes, can you explain to me the benefits ?
but my question refers to the general practice of putting all
JComponents in an array and cycling through them for every listener
and every fired event. It works fine enough, but it feels a bit
"uneconomic",so I wanted to know if it is recommended practice, or if
there is a better way of doing it.
I usually write a custom listener (often as an anonymous class) per type/ instance if I have type/ instance specific behavior so that I can avoid instanceof and other other checks.
You'll want to customise the focus tranfersal system.
Take a look at How to Use the Focus Subsystem, in particular Customizing Focus Traversal

Design for TreeCellRenderer

I have been looking into JTree and TreeCellRenderer. It seems in general, the application (with one JTree) has only one instance of TreeCellRenderer. The application makes multiple calls to TreeCellRenderer's getTreeCellRendererComponent method to decide how each TreeCell is drawn, and such call are made in many occasions (when a cell is selected, deselected, move over, when scrolling, etc.). Why did they decide to do that instead of having multiple instances of TreeCellRenderer, each responsible for one cell??
I am trying to make a JTree where each cell contains a checkbox. The checkbox can be checked/unchecked by the user. Then, the TreeNode userObject's values are set base on the state of these checkboxes. But, from the current JTree design this is impossible - since there is only one instance of JCheckBox, and is only used to show how the Cell looks like (you can't really check it). In some sense I want to separate selection of the TreeCell and the checking of the boxes.
I have some workarounds (implementing MouseAdapter and checking if the mouse click is close by where the checkbox is rendered, then emulate a check on the box by changing its appearence in TreeCellRenderer), but still I want to know if this can be done more directly. Thanks!
Why did they decide to do that instead of having multiple instances of TreeCellRenderer, each responsible for one cell?
This is a nice example of the flyweight pattern.
For a check box tree, I like org.netbeans.swing.outline.Outline, mentioned here, but other examples are available.
Addendum: Reading your question more closely, you ask:
In some sense I want to separate selection of the TreeCell and the checking of the boxes.
This is the correct instinct: The data (checked or unchecked) should be stored in the model (TreeModel), not the view (JCheckBox). The example uses instances of CheckBoxNode in it's (implicit) model, accordingly.

How to trigger Java Swing InputVerifier on enter in JComboBox (actionPerformed)?

I have a Swing JComboBox with an InputVerifier set correctly.
I am using the combo box to set an integer.
If I type "cat" in the field and hit tab, my InputVerifier triggers and resets the value to "0".
If I type "cat" and hit enter, my InputVerifier is never called from actionPerformed. Do I need to explicitly call my InputVerifier from actionPerformed?
What's the best model to validate my JComboBox on tab and enter? It seems like this is something that should be given to me "for free" by the swing model.
The problem is "hit Tab" and "hit Enter" mean two different things in Java Swing. But those two actions mean the same thing to you, me, and the user.
Swing has no single mechanism to detect "when the user is done entering data". Instead, Swing focuses on the mechanics of "is this field losing keyboard focus" and "is the user pressing Enter key while inside a field".
Semantically those two actions mean the same thing from the user's perspective: "I'm done. Here's my input.". But, from what I can tell, Swing fails to offer a way to detect that user intention. I'm as surprised as you by the lack of such a feature, as this seems to be the most basic function of a form in a GUI. What we need, but don't have, is a "dataEntered" event.
There is a workaround…
In a similar context (JTextField instead of JComboBox) the Sun/Oracle Java Tutorial provides the example InputVerificationDemo where a class is created that:
Extends InputVerifier (to handle tabbing/clicking where focus is about to be lost)
Implements ActionListener (to handle pressing Enter key without leaving field)
The good thing about this workaround is that you can locate your handling code all in one place. The downside is that you still have the hassle of:
Creating a separate class.
Instantiating that class.
Passing that instance to both the setInputVerifier and addActionListener methods of your widget (JTextField, etc.).
This is the expected behavior of InputVerifier: the TAB key attempts to change focus, while the ENTER key does not. You can bind the ENTER key to a different action, as described in the tutorial How to Use Key Bindings. Also, consider the informative article Key Bindings, which includes a handy utility application.
When using an editable combo box, focus is on a JTextField which is used as the editor of the combo box. You can add an ActionListener to this text field.
In the ActionListener you could try invoking the transferFocus() method which should be equivalent to tabbing our of the text field. If that doesn't work then tha actionListener should invoke the same editing code as the InputVerifier.

Categories