Правая граница Java Swing не работает в Microsoft Windows

Я не могу получить стандарт BorderFactory.createEmptyBorder работает правильно в Java Swing.

Я попробовал это с простым Java-приложением, которое создает Spinner View и объявляет пустую рамку вокруг него. Граница показана везде, кроме правой части вида счетчика. но это произошло только в Windows, в OSX все работает как задумано.

Чтобы прояснить использование границы: в моем реальном приложении у меня есть видимая граница с внешней стороны счетчика, а затем я хочу центрировать текст внутри. Я нашел createCompoundBorder свойство очень полезно для этого.

import javax.swing.*;
import java.awt.*;
import javax.swing.border.Border;

class HelloWorldSwing {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(
                UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {}

        Runnable guiCreator = new Runnable() {
            public void run() {
                JFrame fenster = new JFrame("Hallo Welt mit Swing");
                fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                SpinnerNumberModel model = new SpinnerNumberModel(1,1,9,1);
                JSpinner spinner = new JSpinner(model);

                JFormattedTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
                textField.setOpaque(true);
                // textField.setBackground(Color.);

                spinner.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));

                spinner.setUI(new javax.swing.plaf.basic.BasicSpinnerUI() {
                    protected Component createNextButton() {
                        Component c = new JButton();
                        c.setPreferredSize(new Dimension(0, 0));
                        c.setFocusable(false);
                        return c;
                    }

                    protected Component createPreviousButton() {
                        Component c = new JButton();
                        c.setPreferredSize(new Dimension(0, 0));
                        c.setFocusable(false);
                        return c;
                    }
                });
                spinner.setBackground(Color.LIGHT_GRAY);
                fenster.add(spinner);

                fenster.setSize(300, 200);
                fenster.setVisible(true);
            }
        };

        SwingUtilities.invokeLater(guiCreator);
    }
}

РЕДАКТИРОВАТЬ: я не хочу найти решение, которое реализует еще один элемент пользовательского интерфейса. Это было бы легким и простым решением (спасибо Эндрю Томпсону). Причина в том, что это просто маленький проект, в который я попал в эту ошибку. В небольших проектах я в основном хочу чистый и красивый код, что означает, что такие ошибки исправляются попыткой исправить испорченный код, а не обходным путем.

заранее спасибо

1 ответ

Решение

Похоже, что JSpinner использует собственный менеджер компоновки и неправильно обрабатывает границу.

Я изменил ваш код, чтобы дать кнопкам ширину правого края границы минус 1. Я предполагаю, что менеджер макета оставляет зазор в 1 пиксель между краем текстового поля и кнопкой.

Кажется, работает на Windows, но это может испортить OSX?

import javax.swing.*;
import java.awt.*;
import javax.swing.border.Border;

class HelloWorldSwing {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(
                UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {}

        Runnable guiCreator = new Runnable() {
            public void run() {
                JFrame fenster = new JFrame("Hallo Welt mit Swing");
                fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                SpinnerNumberModel model = new SpinnerNumberModel(1,1,9,1);
                JSpinner spinner = new JSpinner(model);

                JFormattedTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
                textField.setOpaque(true);
                // textField.setBackground(Color.);

                spinner.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 0));

                spinner.setUI(new javax.swing.plaf.basic.BasicSpinnerUI() {
                    protected Component createNextButton() {
                        Component c = new JButton();
                        c.setPreferredSize(new Dimension(9, 0));
                        c.setVisible(false);
                        return c;
                    }

                    protected Component createPreviousButton() {
                        Component c = new JButton();
                        c.setPreferredSize(new Dimension(9, 0));
                         c.setVisible(false);
                        return c;
                    }
                });
                spinner.setBackground(Color.LIGHT_GRAY);
                fenster.setLayout( new FlowLayout() );
                fenster.add(spinner);

                fenster.setSize(300, 200);
                fenster.setVisible(true);
            }
        };

        SwingUtilities.invokeLater(guiCreator);
    }
}

Другое решение - не использовать JSpinner. Вы можете легко использовать JTextField и написать собственное действие для стрелок вверх / вниз. Немного больше работы, но она будет работать на всех платформах.

Также, поскольку вы, кажется, беспокоитесь о создании дополнительных компонентов, это будет гораздо более эффективным в этом отношении. JSpinner сам по себе является сложным компонентом, а JFormattedTextField гораздо сложнее, чем простой JTextField.

Другие вопросы по тегам