2010-06-28 6 views
0

다음 예제 코드를 사용하십시오. Swing에는, HTML이 포함 된 경우 비활성화 된 구성 요소가 비활성화 된 것으로 렌더링되지 않는 버그가 있습니다. 동료가 이미 처리하기를 희망하는 문제를보고하는 것 외에 문제를 해결할 수있는 좋은 방법이 있습니까?JCheckBox의 비활성화 된 모양을 어떻게 복제 할 수 있습니까?

내가 취하는 해결책은 무엇이든간에 응용 프로그램의 모든 확인란에 해킹해야하는 것과는 달리 글로벌 수정이 필요합니다. ,

나는 이전과 그림 후 setForeground를 호출하는 확인란에 대한 사용자 지정 UI를 만드는 시도,하지만 setForeground를 호출하여, 그것이 렌더러를 호출 repaint()를 호출에 궁극적으로 결과 이벤트를 발생시킵니다 것으로 나타났다. ..

import java.awt.GridLayout; 
import java.util.Arrays; 

import javax.swing.BorderFactory; 
import javax.swing.JCheckBox; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class TestCheckBoxes extends JFrame 
{ 
    public TestCheckBoxes() 
    { 
     JCheckBox checkBox1 = new JCheckBox("Enabled, plain text"); 
     JCheckBox checkBox2 = new JCheckBox("<html><p>Enabled, HTML"); 
     JCheckBox checkBox3 = new JCheckBox("Disabled, plain text"); 
     checkBox3.setEnabled(false); 
     JCheckBox checkBox4 = new JCheckBox("<html><p>Disabled, HTML"); 
     checkBox4.setEnabled(false); 

     setLayout(new GridLayout(4, 1)); 

     for (JCheckBox checkBox : Arrays.asList(checkBox1, checkBox2, checkBox3, checkBox4)) 
     { 
      checkBox.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); 
      add(checkBox); 
     } 

     ((JComponent) getContentPane()).setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); 
     pack(); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       TestCheckBoxes frame = new TestCheckBoxes(); 
       frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

거기에 HTML이 필요한 이유는 무엇입니까? 위의 발췌문 에서처럼 나는 아무 것도 찾을 수 없었습니다. – Nivas

+0

이것은 문제를 재현 할 수있는 최소한의 예일뿐입니다. 실제 응용 프로그램에는 두 개의 비슷한 모양의 체크 상자가 나란히 있으므로 대담한 단어가 강조되어 있습니다. – Trejkaz

답변

0

대신 렌더러를 사용하는 것이 좋습니다. 당신은 (JLabel 등) 렌더러 내부에 HTML을 사용할 수 있으며 문제 자체 :)으로 사라집니다

자세한 내용은 확인 단순히 http://java.sun.com/docs/books/tutorial/uiswing/components/combobox.html#renderer

+0

슬프게도 JCheckBox는 셀 렌더러를 지원하지 않습니다.그렇지 않으면 나는 확실히 그것을 사용하여 기본 렌더러를 대체하는 사용자 정의 UI를 만듭니다. – Trejkaz

+0

무엇을 의미합니까? 나는 당신에게 그것을 수행하는 방법에 대한 링크를주었습니다. 단지 사용자 정의 ComboBoxRenderer를 만드십시오. 렌더러는 ListCellRenderer를 기반으로해야합니다. 그것은 확실히 작동합니다 - 나는 그것을 여러 번 사용했습니다. –

+0

콤보 상자 렌더러를 확인란에 어떻게 적용할까요? – Trejkaz

1

에서 당신은 체크 박스를 분리 할 수 ​​있고 자신의 구성 요소로 라벨을하고있는 레이블이없는 체크 박스. 또한 패널을 직접 패널에 추가하고 패널의 setEnabled() 메서드를 재정 의하여 확인란을 선택/해제하고 레이블의 색상을 변경할 수 있습니다. 예를 들어,이 코드를 가지고 : checkbox 및 레이블은 우리의 패널의는, setEnabled()`방법을 사용하는 것이 최종해야한다는

final JCheckBox checkbox = new JCheckBox(); 
final JLabel label = new JLabel(); 
JPanel panel = new JPanel() { 
    @Override 
    public void setEnabled(boolean enabled) { 
     super.setEnabled(enabled); 
     checkbox.setEnabled(enabled); 
     if (enabled) 
      label.setForeground(Color.BLACK); 
     else 
      label.setForeground(Color.GRAY); 
    } 
}; 
panel.add(checkbox); 
panel.add(label); 

참고. HTML을 체크 박스에 삽입하는 빈도에 따라이 작업을 수행하기 위해 언제든지 자신의 구성 요소 클래스를 만들 수 있습니다.

public class HTMLCheckBox extends JPanel { 
    private JCheckBox checkbox = new JCheckBox(); 
    private JLabel label = new JLabel(); 
    private Color disabledColor = Color.GRAY; 
    private Color enabledColor = Color.BLACK; 

    public HTMLCheckBox(String text) { 
     label.setText(text); 
     add(checkbox); 
     add(label); 
    } 

    public boolean isSelected() { 
     return checkbox.isSelected(); 
    } 

    @Override 
    public void setEnabled(boolean enabled) { 
     super.setEnabled(enabled); 
     checkbox.setEnabled(enabled); 
     if (enabled) 
      label.setForeground(enabledColor); 
     else 
      label.setForeground(disabledColor); 
    } 
} 

원하는 생성자 및 메서드를 추가하십시오. 예를 들어, setBackground()을 재정 의하여 패널, 확인란 및 레이블의 배경을 설정합니다. 레이블 텍스트를 변경하는 방법은 setText() 일 수도 있습니다. 네가하고 싶은게 뭐든간에. 그리고 이것들을 마음대로 변경할 수 있도록 enabledColordisabledColor을 세팅 할 수도 있습니다.

+0

eugener의 제안처럼 렌더러를 수정하는 것도 매우 유용합니다. 렌더러를 수정하면 HTML 태그가 표시되는 문제가 발생했습니다. 조금 까다 롭습니다. 때로는 더 깨끗해 보입니다. :) – peppertherj

+0

이 솔루션은 응용 프로그램의 모든보기를 수정해야하는 것처럼 들립니다. – Trejkaz

0

나는 내 자신의 질문에 대답하는 것을 멈춰야한다 ... 시간대와 관련이 있어야하고 잠자는 동안 그것에 대해 생각할 시간이 있어야한다.

응용 프로그램의 다른

어딘가에 ...

UIManager.put("CheckBoxUI", "package.for.CustomisedWindowsCheckBoxUI"); 

그리고 다음이 구현은,하지만 여전히 꽤 해키하고 훌륭한보다 작은 HTML 색상 문자열을 생성하는 유틸리티 메소드를 사용

여기에 게시.

메탈 L & F. 금속 L & F도 문제가 있지만 해결책은 동일하지만 BasicCheckBoxUI 대신 서브 클래 싱 만하면됩니다.

import java.awt.Graphics; 

import javax.swing.AbstractButton; 
import javax.swing.JComponent; 
import javax.swing.plaf.ColorUIResource; 
import javax.swing.plaf.ComponentUI; 
import javax.swing.plaf.basic.BasicHTML; 
import javax.swing.text.View; 

import com.sun.java.swing.plaf.windows.WindowsCheckBoxUI; 

import com.blah.util.ColourUtils; 

/** 
* Customisation of Windows check box UI to fix bugs. 
*/ 
public class CustomisedWindowsCheckBoxUI extends WindowsCheckBoxUI { 
    /** 
    * Factory method called from Swing. 
    * 
    * @param b the check box. 
    * @return the UI. 
    */ 
    public static ComponentUI createUI(JComponent b) { 
     // TODO: Sun have an AppContext they use to store these once per app. 
     // Might be more sociable to use something like that. 
     return new CustomisedWindowsCheckBoxUI(); 
    } 

    @Override 
    public void paint(Graphics g, JComponent c) { 
     AbstractButton b = (AbstractButton) c; 

     // Works around a bug in BasicButtonUI where a disabled button with HTML markup in the text will 
     // not appear to be disabled. 

     // TODO: Find a way to fix this globally for HTML rendering. It seems odd that it isn't working. 
     // I can see the code in BasicHTML.createHTMLView which uses the foreground colour, which is 
     // obviously why setForeground() works as a workaround. 

     if (b.getForeground() instanceof ColorUIResource) { 
      View view = (View) c.getClientProperty(BasicHTML.propertyKey); 
      if (view != null) { 
       // Ensure that we don't update the renderer if the value hasn't changed. 
       String cachedHtmlFor = (String) c.getClientProperty("cachedHtmlFor"); 
       String key = String.format("%s:%s", c.isEnabled(), b.getText()); 
       if (!key.equals(cachedHtmlFor)) { 
        c.putClientProperty("cachedHtmlFor", key); 
        if (c.isEnabled()) { 
         BasicHTML.updateRenderer(c, b.getText()); 
        } else { 
         BasicHTML.updateRenderer(c, String.format("<html><div style='color: %s'>%s", 
                    ColourUtils.toHtmlColour(b.getBackground().darker()), 
                    b.getText())); 
        } 
       } 
      } 
     } 

     super.paint(g, c); 
    } 
} 
관련 문제