2017-07-30 102 views
0

我從來沒有寫過任何東西比裸機更GUI程序,所以我採取了個人項目寫一個象棋應用。重寫的paintComponent()在JButton的產生意想不到的結果

我的這個項目的目標之一是讓電路板重新調整到適合窗口,我設法做到這一點沒有太多的麻煩。然而,在這個過程中,我碰到了一個問題,那就是我的作品(在JButtons上表現爲圖標)並未與其他作品重新進行比例調整。

我決定用Image類代替它們,並且創建了一個名爲ScalingJButton的自定義類,它覆蓋了paintComponent。這實際上工作得很好......對於the last piece to be drawn。其餘的部分沒有繪製,結果程序被破壞。這裏是我ScalingJButton類:

public class ScalingJButton extends JButton{ 
private Image image; 

ScalingJButton(){ 
    this.image = null; 
} 

ScalingJButton (Image image){ 
    this.image = image; 
} 

public void setImage(Image image){ 
    this.image = image; 
} 

public Image getImage(){ 
    return image; 
} 

@Override 
public void paintComponent(Graphics g){ 
    //super.paintComponent(g); 
    int x = getX(); 
    int y = getY(); 
    int width = getWidth(); 
    int height = getHeight(); 
    if (image != null) { 
     g.drawImage(image, x, y, width, height, this); 
    } 

}} 

此外,這裏是負責實例化ScalingJButtons代碼(VisualBoard是擴展的JPanel類,這是它的構造函數)。

public VisualBoard(){ 
    white = Color.WHITE; 
    black = Color.GRAY; 
    loadPieceImages(); 
    setLayout(new GridLayout(8, 8)); 
    for (int i = 0; i < 8; i++){ 
     for (int j = 0; j < 8; j++){ 
      squares[i][j] = new ScalingJButton(); 
      if ((i + j) % 2 != 0) { 
       squares[i][j].setBackground(white); 
      } 
      else{ 
       squares[i][j].setBackground(black); 
      } 
      add(squares[i][j]); 
     } 
    } 
    initializeStandardBoard(); 
} 

最後,由於佈局可能是相關的,這裏要說的是,使板自動縮放代碼:

public class Chess { 
public static void main (String[] args){ 
    final VisualBoard board = new VisualBoard(); 

    final JPanel container = new JPanel(new GridBagLayout()); 
    container.add(board); 
    container.addComponentListener(new ComponentAdapter() { 
     @Override 
     public void componentResized(ComponentEvent e) { 
      drawResizedBoard(board, container); 
     } 
    }); 

    JFrame frame = new JFrame("Chess"); 
    frame.setSize(1000,1000); 
    frame.add(container); 
    frame.setLocationRelativeTo(null); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 

} 

private static void drawResizedBoard(JPanel innerPanel, JPanel container) { 
    int w = (int)Math.round(container.getWidth()*0.9); 
    int h = (int)Math.round(container.getHeight()*0.9); 
    int size = Math.min(w, h); 
    innerPanel.setPreferredSize(new Dimension(size, size)); 
    container.revalidate(); 
}} 

我曾經做過大量的調試,但大部分有沒有出路。有一點需要注意的是,當調用drawImage時,ScalingJButton中的「image」變量保持正確的圖像,所以這不是問題。另一個有趣的一點是,使用一塊在它的廣場是方形的楦要繪製,並根據什麼順序加方塊董事會,不同的作品將被繪製(所以沒有問題加載件)。

奇怪的是,如果我做掉在超級的paintComponent,滾動我的鼠標在拉片導致其他廣場,以填補那塊當我搖我的鼠標超過他們。

我完全迷路了,不知道該怎麼辦,所以任何幫助將不勝感激!

回答

1

首先,您需要保留super.paintComponent(g);一行。如果你不這樣做,那麼神器會出現在看似隨機的時間。

其次,getX()和getY()返回組件在其父項中的位置。繪畫時,會給出一個座標系,其中0,0是組件的左上角。所以你應該忽略getX()和getY()。

最簡單的方法是使用按鈕的左上角:

int x = 0; 
int y = 0; 

您可能要佔到按鈕邊框:

if (image != null) { 
    Rectangle inner = SwingUtilities.calculateInnerArea(this, null); 
    g.drawImage(image, inner.x, inner.y, inner.width, inner.height, this); 
} 

如果你想按鈕真的看起來像一個正常的按鈕,你也可以佔其邊緣:

if (image != null) { 
    Rectangle inner = SwingUtilities.calculateInnerArea(this, null); 

    Insets margin = getMargin(); 
    inner.x += margin.left; 
    inner.y += margin.top; 
    inner.width -= (margin.left + margin.right); 
    inner.height -= (margin.top + margin.bottom); 

    g.drawImage(image, inner.x, inner.y, inner.width, inner.height, this); 
} 
+0

非常感謝你的解釋!我已經自己辭去了使用StretchIcon(不可否認,這不是一個壞主意),但在閱讀完畢後,我回到了我的自定義類,發現它運行得很好。我只是假設g.drawImage()將從ScalingJButton的位置相對於右上角繪製,但實際上它是相對於ScalingJButton繪製的。所有那些對這種愚蠢的誤解感到悲傷! – TheRussianPatzer

0

但是,在這個過程中我遇到了這個問題,我的作品(其代表作爲圖標上Jbutton將)沒有重新調整

Stretch Icon可能是一個簡單的解決方案。您可以在任何可以顯示圖標的組件上使用此圖標。圖像將動態更改大小以填充圖標可用的空間。

+0

感謝您的建議。我在研究中遇到了Stretch Icon,我可能最終會走這條路,因爲這個問題不會消失。但是,如果沒有其他信息,我仍然想知道是什麼原因導致此問題以供將來參考。 – TheRussianPatzer

0

有你的代碼中有兩處可疑行。首先是

frame.add(container); 

此行將您的Swing元素添加到AWT容器。相反,你應該

frame.setContentPane(container); 

第二行替換它是方法

public void paintComponent(Graphics g) { 

嘗試用

public void paint(Graphics g) { 

希望這有助於替換它。

編輯:

也會改變該

g.drawImage(image, x, y, width, height, this); 

public void paint(Graphics g) { 
    super.paint(g); 
    int width = getWidth(); 
    int height = getHeight(); 
    if (image != null) { 
     g.drawImage(image, 0, 0, width, height, this); 
    } 
} 

你的圖像進行簡單電網之外。

+0

我嘗試了這兩個建議,但都沒有工作。我的猜測是這個問題與Graphics.drawImage()在某些佈局方面的工作方式有關,但我完全不瞭解這個,所以我甚至不知道如何找出答案。 – TheRussianPatzer

+0

我玩了一下你的代碼。請參閱我的「擴展」答案。 –

+0

謝謝,這立即解決了問題!沒有想到這一點,我感到非常愚蠢。 – TheRussianPatzer

相關問題