2017-07-30 85 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

相关问题