Как устранить эту ошибку, когда один класс, если я использую его, вызывает заражение интерфейсов других классов

Мой случай:

У меня странная ошибка

Мне нужно использовать 2 класса из 1 основного класса, который выглядит следующим образом:

  • 1 основной класс, который водит оба класса YumYumYum

  • 2 других класса, которые являются только пользовательскими интерфейсами, как показано ниже:

    а) MyJSlider главный создатель ошибок

    б) Volume второй класс, который просто показывает черное окно с зеленым индикатором на нем

Теперь я подготовил SSCCE в одном файле, и demo.xml также доступен здесь.

Проблема:

Если я закомментирую строку private MyJSlider _______BUG__BUG__BUG_______ = new MyJSlider(); это работает, но когда я использую это, это вызывает все проблемы. Как я могу это исправить?

import java.awt.*;
import java.net.URL;
import javax.swing.*;
import javax.swing.plaf.synth.SynthLookAndFeel;

public class YumYumYum {
  //
  // Step 1: using 2 class from here
  //
  private MyJSlider _______BUG__BUG__BUG_______ = new MyJSlider();    
  private static JFrame f = new JFrame();    
  public YumYumYum() {
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setLayout(new FlowLayout());
    f.setPreferredSize(new Dimension(300, 200));         
    f.getContentPane().add(new JButton("Show me as Swing only - Then i am correct"));    
    f.pack();
    f.setVisible(true);    
  }
  public void test() {
    Volume a = new Volume();
    a.up(100);
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        YumYumYum s = new YumYumYum();
        s.test();
      }
    });
  }

  //
  // Step 2: Creates the problem
  //
  public class MyJSlider extends JSlider {
    public MyJSlider() {     
      try {
        SynthLookAndFeel laf = new SynthLookAndFeel();
        //laf.load(MyJSlider.class.getResourceAsStream("/ui/demo.xml"), MyJSlider.class);      
        laf.load(new URL("file:///var/tmp/demo.xml"));
        UIManager.setLookAndFeel(laf);
      } catch (Exception e) {
        e.printStackTrace();
      }       
      setOrientation(JSlider.VERTICAL);
      //setMinimum(-24);
      setMaximum(12);
      setOpaque(false);
    }
  }

  //
  // Step 3: Does not show its actual user interface when Step 2 is involved
  //
  public class Volume extends JWindow {
    private JPanel panelFirst;
    private JProgressBar a;
    public Volume() {    
      setLayout(new BorderLayout());
      setBounds(10, 40, 350, 60);
      panelFirst = new JPanel();        
      panelFirst.setBackground(Color.BLACK);    
      panelFirst.setLayout(new FlowLayout(FlowLayout.LEFT, 8,5));        
      a = createJP(100); 
      panelFirst.add(a);
      add(panelFirst);
      setVisible(true);
      setAlwaysOnTop(true);
    }

    public JProgressBar createJP(int input) {
      JProgressBar jp = new JProgressBar(JProgressBar.VERTICAL, 0, 100);
      jp.setPreferredSize(new Dimension(15, 50));
      jp.setValue(input);
      jp.setBackground(Color.RED);
      jp.setVisible(true);
      return jp;  
    }
    public void up(int input) {
      a.setForeground(Color.GREEN);
    }
  }

}

Следовать за:

  • Протестировано в Java 6 и Java 7 оба одинаковых результата в Linux

2 ответа

Решение

Альтернативное решение этой проблемы приведено ниже:

Поместите это там, где Synth не является предпочтительным.

  //
  // Step 3: Makeing this work
  //
  public class Volume extends JWindow {
    private JPanel panelFirst;
    private JProgressBar a;
    public Volume() {
      try {
                  // Set cross-platform Java L&F (also called "Metal")
              UIManager.setLookAndFeel(
                  UIManager.getCrossPlatformLookAndFeelClassName());
          } 
          catch (UnsupportedLookAndFeelException e) {
            // handle exception
          }
          catch (ClassNotFoundException e) {
            // handle exception
          }
          catch (InstantiationException e) {
            // handle exception
          }
          catch (IllegalAccessException e) {
            // handle exception
          }      
      setLayout(new BorderLayout());
      setBounds(40, 40, 350, 60);
      panelFirst = new JPanel();        
      panelFirst.setBackground(Color.BLACK);    
      panelFirst.setLayout(new FlowLayout(FlowLayout.LEFT, 8,5));        
      a = createJP(100); 
      panelFirst.add(a);
      add(panelFirst);
      setVisible(true);
      setAlwaysOnTop(true);
    }

    public JProgressBar createJP(int input) {
      JProgressBar jp = new JProgressBar(JProgressBar.VERTICAL, 0, 100);
      jp.setPreferredSize(new Dimension(15, 50));
      jp.setValue(input);
      jp.setBackground(Color.BLACK);
      jp.setVisible(true);
      return jp;  
    }
    public void up(int input) {
      a.setForeground(Color.GREEN);
    }
  }

Я подозреваю, что звонок UIManager.setLookAndFeel портит ваш интерфейс (я проверял это под Mac OSx и у меня не было проблем...)

Попробуйте сделать звонок setLookAndFeel в main метод перед invokeLater вызов...

public static void main(String[] args) {
    SynthLookAndFeel laf = new SynthLookAndFeel();
    //laf.load(MyJSlider.class.getResourceAsStream("/ui/demo.xml"), MyJSlider.class);      
    laf.load(new URL("file:///var/tmp/demo.xml"));
    UIManager.setLookAndFeel(laf);
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        YumYumYum s = new YumYumYum();
        s.test();
      }
    });
}

Это может помочь

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