Design for TreeCellRenderer - java

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.

Related

Java Swing How can I create a Color Swatch in my custom ColorChooserPanel?

I'm working on my custom ColorChooserPanel class, but I don't know how to create a ColorSwatch.
I found a class named ColorSwatch or something like that but its package private and I can't access it.
How can I ensure that I have a proper color chooser?
First, you need to think about the way this should work, to formulate your goals into action points that you can always check and see whether and how they are fulfilled:
it should be displayed
it should handle click events
it should be able to return a color (the last chosen color, or a default in lack of that)
Now, a very common way of supporting color choosers is to have something like in this image:
However, this is way too complex for a first implementation. You should first have something which "works", that is, you are able to choose colors to taste success and then work out the subsequent details. Unless you say otherwise, I'm assuming that the Basic colors section is good for now. In that case, you can create a class, which contains a JPanel, containing clickable elements. Your class needs to have a Color member, which one can get calling a getter and which is set when a clickable item inside your JPanel is clicked. The clickable items can be JPanels on their own, for example.
If you prefer something ready-made, then kindly read these:
https://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html
https://coderanch.com/t/332515/java/Color-Palette

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!

JOptionPane List Actions

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.

Java DefaultMutableTreeNodes: Interactive displays given by my cell renderer?

In the program I'm writing, I have a JTree storing some objects of my own design. I made my own extension of DefaultTreeCellRenderer and overrode getTreeCellRendererComponent to return a JPanel with some buttons and things. What I found was that the buttons I added didn't act like buttons, which makes think that interaction with the components is being "stolen" by the tree cell. (If you click on the button, the container surrounding the button is also being clicked on, and the tree has its own response to being clicked.)
So my question is this:
If what I want is the basic functionality of a tree, plus some buttons, what approach should I use?
Continue on the same route; add a mouse listener of some kind to manually add the functionality to the button.
Continue on the same route; remove the existing mouse listener and add your own to achieve the right behavior.
Extend or implement a slightly different class or interface than you did - maybe not DefaultMutableTreeNodes, maybe not DefaultTreeCellRenderer, etc. - use the existing XXXX to do what you're trying to do.
Avoid using JTree; make your own, it's not that hard.
I'm leaning toward the last option - there's a decent chance I don't actually want the folding behavior of a tree anyway, so I may just make my own structure. However, even if I choose that option, I'd like to know what I should have done.
You'll also need a TreeCellEditor, illustrated here.
Avoid using JTree; make your own, it's not that hard
I wish you good luck wit that ;-)
What is happening is that the components returned by the renderer are only used as a 'stamp'. So the JTree does not really contain the returned components, they are only painted. Hence no interaction with your button. It only looks like a button. It seems the JTree tutorial does not contain a real section on this, but it is basically the same concept as for tables, which is explained in the 'Renderers and editors' part of the tutorial.
That also explains why a typical renderer class extends JLabel and can simply use return this after it made customizations to itself, without affecting the other nodes in the tree. For example the source code of the DefaultTreeCellRenderer, which extends JLabel, contains
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel,
boolean expanded,
boolean leaf, int row,
boolean hasFocus) {
//...
setText(stringValue);
//...
return this;
}
How to fix this: create an editor as well, as suggested by #trashgod

JTree selection without generating event

I have a JTree, a JTable and a JList which displays the same set of objects, but in different order and with different information. If an item is selected from one of the Component, I want to select the same object on the other two Components (meaning they should be highlighted). Naturally I monitor the selection events with a Listener. Here is the problem, when a Component retrieves the selected object, I'll have to make sure the object is selected on the other Components by calling selection methods on them. This, will then notify the selection listeners on the other two components. But each of those events will in turn call selection events on components other than itself, causing an infinite loop going among the three Components.
I see one solution is to use a boolean flag, and make the listeners not propagate the selection if the flag is set. However, this seems cumbersome and not elegant. Is there a way to simply tell JTree, JTable and JList to make the selection but not fire any events (as oppose to fire an event and then catching and stopping it with a boolean flag)?
Take a look at SharedModelDemo. I think it does what you're looking for.
I would use a flag indicating whether it's user changes or internal changes but yu can also remove listeners before selection call and add them after to prevent events firing.

Categories