Customize jFileChooser vertical scrollbar - java

I'm using a jFileChooser and I'm trying to achieve the following :
https://i.stack.imgur.com/O6MNj.png
I'm trying to force the the LIST view to have a VERTICAL scroll bar or my second option is to disable the size and modified columns from the details view.
EDIT:
Is there any way that I can insert a JScrollBar inside the jFileChooser?

You can access the JList and change the orientation of the list as follows:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.util.List;
class FileChooserList
{
private static void createAndShowUI()
{
JFileChooser fileChooser = new JFileChooser(".");
// Change list orientation
JList list = SwingUtils.getDescendantsOfType(JList.class, fileChooser).get(0);
list.setLayoutOrientation( JList.VERTICAL );
fileChooser.showOpenDialog(null);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
The above code requires the Swing Utils class.
disable the size and modified columns from the details view
Depends on what you mean by "disable".
You can remove those columns from the view of the table:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.util.List;
class FileChooserDetails
{
private static void createAndShowUI()
{
JFileChooser fileChooser = new JFileChooser(".");
// Show the Details view of the file chooser
Action details = fileChooser.getActionMap().get("viewTypeDetails");
details.actionPerformed(null);
// Remove columns from view
JTable table = SwingUtils.getDescendantsOfType(JTable.class, fileChooser).get(0);
TableColumnModel tcm = table.getColumnModel();
tcm.removeColumn( tcm.getColumn(3) );
tcm.removeColumn( tcm.getColumn(1) );
fileChooser.showOpenDialog(null);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Related

Portrayals not Showing

EDIT: Everything displays correctly when either field or hunterField hold no objects in any location. field and hunterField both exclusively hold objects which extend the same class, so I guess it may have something to do with inheritance...?
I have created a simple Agent-Based Model using MASON. The back-end works find, but when I try displaying my agents only "wall" agents are displayed. (Wall Portrayal) My code is below... Any idea?
package sim.app.celai;
import java.awt.Color;
import javax.swing.JFrame;
import sim.app.tutorial3.Tutorial3WithUI;
import sim.display.Controller;
import sim.display.Display2D;
import sim.display.GUIState;
import sim.portrayal.grid.SparseGridPortrayal2D;
import sim.util.Bag;
public class FieldWithGUI extends GUIState {
public Display2D display;
public JFrame frame;
SparseGridPortrayal2D hunterPortrayal = new SparseGridPortrayal2D();
SparseGridPortrayal2D wallPortrayal = new SparseGridPortrayal2D();
SparseGridPortrayal2D childPortrayal = new SparseGridPortrayal2D();
public FieldWithGUI() {
super(new Field(System.currentTimeMillis()));
}
public void setupPortrayals() {
childPortrayal.setField(((Field) state).field);
hunterPortrayal.setField(((Field) state).hunterField);
wallPortrayal.setField(((Field) state).wallField);
childPortrayal.setPortrayalForAll(new sim.portrayal.simple.OvalPortrayal2D(Color.blue));
hunterPortrayal.setPortrayalForAll(new sim.portrayal.simple.OvalPortrayal2D(Color.red));
wallPortrayal.setPortrayalForAll(new sim.portrayal.simple.OvalPortrayal2D(Color.green));
display.reset();
display.repaint();
}
public void quit()
{
super.quit();
if (frame!=null) frame.dispose();
frame = null; // let gc
display = null; // let gc
}
public static void main(String[] args)
{
new FieldWithGUI().createController();
}
public void start()
{
super.start();
// set up our portrayals
setupPortrayals();
}
public void init(Controller c)
{
super.init(c);
// Make the Display2D. We'll have it display stuff later.
display = new Display2D(400,400,this); // at 400x400, we've got 4x4 per array position
frame = display.createFrame();
c.registerFrame(frame); // register the frame so it appears in the "Display" list
frame.setVisible(true);
// specify the backdrop color -- what gets painted behind the displays
display.setBackdrop(Color.black);
// attach the portrayals
display.attach(childPortrayal, "children");
display.attach(hunterPortrayal, "hunter");
display.attach(wallPortrayal, "wall");
}
}

Java Applet Text highlights on rollover

I'm trying to figure out how to make non-editable text (not a JTextField) whose background color changes when the mouse rolls over it. I tried using JButton implementing ActionListener and hiding elements to make the button appear to be just text, but it only allows me to change icons on rollover and detect when the button is clicked. Another thought was to use MouseListener and declare the specific coordinates of a rectangle around the text, where upon mouseMoved it could initiate the highlight. But w/ that there's a problem for varying string lengths and word wrap etc. What is the best object, and listener combo to achieve the effect of a highlighted text field on mouse rollover?
Hmm maybe use a foucs listener and when the field gains foucs select all the text?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextField extends JTextField {
public TextField(String text) {
super(text);
addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent fe) {
selectAll();
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField tf = new JTextField("normal field");
f.add(tf, BorderLayout.CENTER);
TextField ftf =
new TextField("funny text field");
f.add(ftf, BorderLayout.SOUTH);
f.pack();
f.setVisible(true);
}
});
}
}
EDIT:
Hmmm actually found an even better way with the above method you'd have to click on the textfield to gain focus, now i've used a thread to check when the mouse is over the components co-ordinates and then to highlight the field, I used a boolean to control the highlighting as constant highlighting throws an error. Hope this is what you want:
import java.awt.*;
import javax.swing.*;
public class TextFieldHighlight extends JTextField {
static JTextField ftf;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ftf = new JTextField("Highlight");
ftf.setEditable(false);
f.add(ftf, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
Thread thread = new Thread(new Runnable() {
boolean focused = false;
#Override
public void run() {
while (true) {
if (mouseIsOverDisplayPanel()) {
if (ftf.hasFocus() && focused == false) {
ftf.selectAll();
focused = true;
} else if (!ftf.hasFocus()) {
focused = false;
}
}
}
}
});
thread.start();
}
});
}
private static boolean mouseIsOverDisplayPanel() {
if (MouseInfo.getPointerInfo().getLocation().x >= ftf.getLocationOnScreen().x
&& MouseInfo.getPointerInfo().getLocation().x <= ftf.getLocationOnScreen().x + ftf.getWidth()
&& MouseInfo.getPointerInfo().getLocation().y >= ftf.getLocationOnScreen().y
&& MouseInfo.getPointerInfo().getLocation().y <= ftf.getLocationOnScreen().y + ftf.getHeight()) {
return true;
} else {
return false;
}
}
}

JRadioButton: how to replace text by IconImage?

I want to replace the text in my radio button list by an icon.
I've tried this:
rotateButton = new JRadioButton(rotateIcon.getImage());
But this replaces the radio button and text by the icon. I would like to keep the radio button and display the image.
What should I do?
What I'm currently getting is:
But I want it to end up with this:
Create a JRadioButton with no text and put a JLabel with the image next to it. You can also create a class to hide complexity.
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeListener;
public class RadioButtonWithImage extends JPanel {
private JRadioButton radio = new JRadioButton();
private JLabel image;
public RadioButtonWithImage(Icon icon) {
image = new JLabel(icon);
add(radio);
add(image);
}
public void addToButtonGroup(ButtonGroup group) {
group.add(radio);
}
public void addActionListener(ActionListener listener) {
radio.addActionListener(listener);
}
public void addChangeListener(ChangeListener listener) {
radio.addChangeListener(listener);
}
public Icon getImage() {
return image.getIcon();
}
public void setImage(Icon icon) {
image.setIcon(icon);
}
} // end class RadioButtonWithImage
public JRadioButton(String text, Icon icon) and simple example here
I just reproduced your described behavior using this source:
import java.awt.Image;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.net.URL;
class RadioWithImage {
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.gravatar.com/avatar/" +
"a1ab0af4997654345d7a949877f8037e?s=128");
Image image = ImageIO.read(url);
final ImageIcon imageIcon = new ImageIcon(image);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JRadioButton radioButton = new JRadioButton("A.T.", imageIcon);
JOptionPane.showMessageDialog(null, radioButton);
}
});
}
}
It seems like a bug to me, though I cannot recall seeing a radio with an icon. How are they supposed to look?
Time to reach into my 'box of hacks'.
import javax.swing.*;
class RadioWithImage {
public static void main(String[] args) throws Exception {
String url = "http://www.gravatar.com/avatar/" +
"a1ab0af4997654345d7a949877f8037e?s=128";
final String html = "<html><body><img src='" +
url +
"' width=128 height=128>";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JRadioButton radioButton = new JRadioButton(html);
JOptionPane.showMessageDialog(null, radioButton);
}
});
}
}
This technique will not work if:
The use-case requires other types of icons (pressed, roll-over, selected etc.)
The button is disabled (it will render incorrectly).
There is no radio button constructor that allows an image as the content argument instead of a text. The only way to replace the text of a radio button by an image it is generate html and pass it as an argument to the default constructor.
import javax.swing.*;
class RadioWithImage {
public static void main(String[] args) throws Exception {
URL url = Windows_ChordsGenerator.class.getResource("/images/img1.png");
final String html = "<html><body><img src='" + url.toString() +"'>";
JRadioButton radioButton = new JRadioButton(html);
}
}

Java: Strange behavior of JEditorPane wrapped inside JScrollPane

I'm trying to build a simple help system to my software.
The help system built from JEditorPane(Loaded with HTML file) wrapped inside of JScrollPane, inside of the same window there is a JLabel.
When the user move the mouse over the JEditorPane on a specific word - more explanations appear in the JLabel.
I succeed doing it, but the problem is, that for some reason it work just on the beginning of the text.(the HTML file is long and must be scrolled...)
After i scroll down the page and hover over a word, it throw me BadLocationException.
On the code below there is a JEditorPane wrapped inside JScrollPane.
When the user move the mouse it print the current letter which the mouse point on.(on the help system i find the value of the word by this position and print explanations to the JLabel according to it)
But, as i said it work just on the beginning of the text.
Why ?
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Point;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.text.BadLocationException;
public class JEditorPaneTestApp extends JFrame {
private JEditorPane editorPan;
private JScrollPane scrollPan;
public JEditorPaneTestApp() {
super();
try {
editorPan = new javax.swing.JEditorPane("file:///path/toHTML/file/helpFile.html");
}
catch (IOException e) {e.printStackTrace();}
scrollPan = new JScrollPane(editorPan);
this.add(scrollPan);
editorPan.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(java.awt.event.MouseEvent evt) {
Point p = new Point(evt.getX(), evt.getY());
int pos = editorPan.viewToModel(p);
try {
System.out.println(editorPan.getText(pos--, pos).charAt(0));
}
catch (BadLocationException e1) {
System.out.println("Invalid location");/* e1.printStackTrace();*/
}
}
});
scrollPan.setViewportView(editorPan);
this.add(scrollPan);
//
this.getContentPane().setLayout(new LayoutManager() {
#Override public Dimension preferredLayoutSize(Container arg0) {return null;}
#Override public Dimension minimumLayoutSize(Container arg0) {return null;}
#Override public void removeLayoutComponent(Component arg0) {}
#Override public void addLayoutComponent(String arg0, Component arg1) {}
#Override public void layoutContainer(Container conter) {
scrollPan.setBounds(0, 0, conter.getWidth(), conter.getHeight());
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
JEditorPaneTestApp test = new JEditorPaneTestApp();
}
}
Thanks
System.out.println(editorPan.getText(pos--, pos).charAt(0));
should be:
System.out.println(editorPan.getText(pos--, 1).charAt(0));

Changing selected files in a JFileChooser in response to an event

I would like my JFileChooser to allow multiple file selection, but with a limit on the number of files that can be selected simultaneously.
Ideally I would like to constrain the selection in real-time, with priority given to the most-recently selected file, i.e. when a 3rd file is selected, the 1st file (i.e the one that was selected earliest) should be deselected automatically.
I thought that a PropertyChangeListener like this one would work:
public static void main(String[] args) throws IOException {
final JFileChooser fc = new JFileChooser(didir);
fc.setMultiSelectionEnabled(true);
fc.addPropertyChangeListener(new PropertyChangeListener() {
private final Set<File> selected = Sets.newLinkedHashSet();
public void propertyChange(PropertyChangeEvent evt) {
if (JFileChooser.SELECTED_FILES_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
File[] selectedFiles = fc.getSelectedFiles();
if (selectedFiles.length > 2) {
selected.addAll(Arrays.asList(selectedFiles));
int numToRemove = Math.max(0, selected.size() - 2);
Iterables.removeIf(Iterables.limit(selected, numToRemove),
Predicates.alwaysTrue());
fc.setSelectedFiles(selected.toArray(new File[0]));
}
}
}
});
fc.showOpenDialog(null);
}
However the call to fc.setSelectedFiles() has no effect (although it fires an event, it does not update the selection in the list.)
Is there any way to programatically force a change to the selection while the JFileChooser is open? Or is there another way to limit the size of the selection?
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import javax.swing.JFileChooser;
public class MyClass {
final static JFileChooser fc = new JFileChooser("/");
public static void main(String[] args) throws IOException {
fc.setMultiSelectionEnabled(true);
fc.addPropertyChangeListener(new ChangeListener());
fc.showOpenDialog(null);
}
private static class ChangeListener implements PropertyChangeListener{
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (JFileChooser.SELECTED_FILES_CHANGED_PROPERTY.equals(evt.getPropertyName())) {
File[] selectedFiles = fc.getSelectedFiles();
File[] allowedFiles = new File[2];
if (selectedFiles.length > 2) {
allowedFiles[0] = selectedFiles[1];
allowedFiles[1] = selectedFiles[0];
fc.setSelectedFiles(allowedFiles);
}
}
}
}
}
I have discovered that this bug is specific to the Macintosh look-and feel. setSelectedFile and setSelectedFiles do not work at all on the Mac (even before the dialog is opened.) My sample code works fine with the Metal look-and-feel.
Possible workarounds include:
Use a different look-and-feel
Use a FileDialog instead of a JFileChooser (does not support multiple file selection)

Categories

Resources