set RTL Orientation of scrollbar inside JFileChoos

2019-01-26 22:12发布

问题:

I have a JFileChooser and I want to make it oriented from right-to-left, and to do so I use:

applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

but an issue shows up. The horizontal scrollbar is still set to the left despite the JFileChooser dialog is oriented RTL correctly. Look at this image:

How can I fix it?

Here is an SSCCE:

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileView;
import java.io.File;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
public class MyFileChooser extends JFileChooser
{
    private String extension;
    private String title;
    public MyFileChooser(String extension, String title)
    {
        super();
        this.extension = extension;
        this.title = title;
        addChoosableFileFilter(new FileNameExtensionFilter(String.format("(*.%1$s) فقط %1$s ملفات", extension), extension));
        applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
    }

    @Override public String getDialogTitle()
    {
        return title;
    }
}

Main:

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import java.awt.event.*;
    public class MainFrame extends JFrame implements ActionListener
    {
        public MyFileChooser chooser;
        public MainFrame()
        {
            super("Main Frame");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
            catch(Exception e){ System.out.println("Unable to load Windows look and feel");}
            setPreferredSize(new Dimension(300, 100));
            ((JPanel) getContentPane()).setBorder(new EmptyBorder(13, 13, 13, 13) );
            setLayout(new FlowLayout());
            JButton btn = new JButton("Open");
            btn.setActionCommand("myButton");
            btn.addActionListener(this);
            add(btn);
            JPanel panel = new JPanel();

            chooser = new MyFileChooser("aaa", "The Title");
            chooser.setAcceptAllFileFilterUsed(false);
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
            chooser.setFileHidingEnabled(false);

            pack();
            setLocationRelativeTo(null);
            setVisible(true);
            setResizable(false);
        }
        public void actionPerformed(ActionEvent e)
        {
            if(e.getActionCommand().equals("myButton"))
            {
                int status = chooser.showOpenDialog(null);
                // blah blah
            }
        }
        public static void main(String[] args)
        {
            new MainFrame();
        }
    }

Also, I thought about the following solution but it didn't affect:

JScrollBar scr = new JScrollBar();
scr.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
UIManager.put("JScrollPane.ScrollBar", scr);

回答1:

.... I think that by adding PropertyChangeListener to the JFileChooser you can listnening for isVisible(); or isDisplayable ... and extract JComponents JFileChooser (compound component) and then call getMyComponents();

private void getMyComponents() {
    Component findList = getJList(chooser);
    JList myList = (JList) findList;
    //find fileName in the JList and move with ViewPort view to the expected Rectangle
    Component myScrollPane = getJScrollPane(chooser);
    JScrollPane scrollPane = (JScrollPane) myScrollPane;
    JViewport vport = scrollPane.getViewport();
    //move with ViewPort view to the expected Rectangle
}

private Component getJList(Component comp) {
    if (comp.getClass() == JList.class) {
        return comp;
    }
    if (comp instanceof Container) {
        Component[] components = ((Container) comp).getComponents();
        for (int i = 0; i < components.length; i++) {
            Component child = getJList(components[i]);
            if (child != null) {
                return child;
            }
        }
    }
    return null;
}

private Component getJScrollPane(Component comp) {
    if (comp.getClass() == JScrollPane.class) {
        return comp;
    }
    if (comp instanceof Container) {
        Component[] components = ((Container) comp).getComponents();
        for (int i = 0; i < components.length; i++) {
            Component child = getJScrollPane(components[i]);
            if (child != null) {
                return child;
            }
        }
    }
    return null;
}


回答2:

Your attempt to call UIManager.put("JScrollPane.ScrollBar", scr); is good. I think that it did not work because the FileChooser overrides this setting or is created before you perform this call.

I'd suggest you to try to "discover" the file chooser after it has been created as a JContainer. Find your scroll bar (or probably JScrollPane) and call applyComponentOrientation. I have not tried this yet but I will need such functionality soon, so I'd be glad to know whether this is working for you.

Good luck.