2011-10-17 41 views
2

我正在使用用於UI的Synth工程,並且想要實現一些自定義按鈕。這些按鈕需要使用來自合成XML設置文件的樣式設置 - 例如不同狀態下的字體顏色(MOUSE_OVER,PRESSED等)不同。Swing - 帶合成器的自定義按鈕

我堅持的問題是,一些按鈕需要額外的子組件 - 例如,有些需要多個標籤。我希望子組件能夠選擇與標準按鈕子組件相同的樣式設置。

我覺得我應該只能擴展JButton並覆蓋/擴展paintComponent來調用某些子組件的繪製方法。儘管如此,我對這個方法的幾個方面有些不確定:例如什麼參數傳遞給paintComponent;以及如何確保子組件獲得正確的Synth風格設置(特別是關於狀態)。

另一方面:我試過擴展JPanel,但遇到了一些困難(參見這裏:JPanel states for Synth)。

編輯:所以,我發現可以向按鈕添加子組件,並讓它們正確呈現。看起來,即使JButton.getLayout()返回null,按鈕將使用OverlayLayout,除非您撥打JButton.setLayout()。調用JButton.setLayout(null)確實會阻止使用OverlayLayout,這就是我處理佈局的方式。

我正在研究幾種不同的方法來更新子控件的樣式,稍後會報告這些方法。

+0

繪畫由組件的UI委託處理。請參閱@ mKorbel的[回覆](http://stackoverflow.com/questions/5751311/creating-custom-button-in-java/5755124#5755124),引用在您以前的[問題](http://stackoverflow.com/問題/ 7768889/jpanel-states-for-synth/7769341#7769341)。 – trashgod

+0

我知道UI委託人處理繪圖,但是因爲(據我所知)基本上不可能擴展Synth UI委託,所以我希望有多種方法來處理這個貓。 – vaughandroid

回答

1

所以,在情況下,它使用的其他任何人這裏是我把最終的辦法:

class CustomButton extends JButton { 
    CustomButton() { 
     // ... normal button init 

     // Enable absolute positioning of sub-components. 
     setLayout(null); 

     updateStyles(); 

     getModel().addChangeListener(new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       updateStyles(); 
      } 
     }); 
    } 

    private void updateStyles() { 
     // See below for implementation. 
    } 

    private int getSynthComponentState() { 
     // This is basically a copy of SynthButtonUI.getComponentState(JComponent) 
     int state = SynthConstants.ENABLED; 
     if (!isEnabled()) { 
      state = SynthConstants.DISABLED; 
     } 

     if (model.isPressed()) { 
      if (model.isArmed()) { 
       state = SynthConstants.PRESSED; 
      } else { 
       state = SynthConstants.MOUSE_OVER; 
      } 
     } 
     if (model.isRollover()) { 
      state |= SynthConstants.MOUSE_OVER; 
     } 
     if (model.isSelected()) { 
      state |= SynthConstants.SELECTED; 
     } 
     if (isFocusOwner() && isFocusPainted()) { 
      state |= SynthConstants.FOCUSED; 
     } 
     if (isDefaultButton()) { 
      state |= SynthConstants.DEFAULT; 
     } 
     return state; 
    } 
} 

我發現2種方法如何實現updateStyles()方法:(A)更改名稱的組件使用不同的命名樣式,或(B)將樣式設置從按鈕複製​​到子組件。方法(A)是相當簡單的,方法(B)的工作原理如下:

private void updateStyles() { 
    SynthStyle ss = SynthLookAndFeel.getStyle(this, Region.BUTTON); 
    SynthContext sc = new SynthContext(this, Region.BUTTON, ss, getSynthComponentState()); 

    for (Component c : getComponents()) { 
     c.setFont(ss.getFont(sc)); 
     c.setBackground(ss.getColor(sc, ColorType.BACKGROUND)); 
     c.setForeground(ss.getColor(sc, ColorType.FOREGROUND)); 
     // ... and so on if you have other style elements to be changed. 
    } 
} 

方法(A)可能是更好的,如果你不是一對夫婦與每個不同的狀態樣式設置更多的變化,雖然它可能如果你對很多不同的狀態有不同的風格會變得笨拙。如果你只是改變一些風格設置(例如在我的情況下,我只關心顏色,至少現在),那麼方法(B)似乎是最好的。

還有一種實現自定義用戶界面委託(擴展BasicButtonUI)的trashgod建議的方法,但如果採取該路線,我認爲您將不得不重新實施大部分SynthButtonUI。

+0

+1發佈代碼 – mKorbel