我从来没有用简单的GUI编写程序,所以我已经开始编写国际象棋应用程序的个人项目。
我在这个项目中的目标之一是让电路板重新调整以适应窗口,我设法做到这一点没有太多麻烦。但是,在这个过程中我遇到了一个问题,即我的作品(在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();
}}
我已经做了大量的调试,但大部分都没有领先。有一点需要注意的是&#34;图像&#34; ScalingJButton中的变量在调用drawImage时保持正确的图片,因此不是问题。另一个有趣的观点是,其中包含片段的正方形是要绘制的最后一个正方形,并且根据我向棋盘添加正方形的顺序,将绘制不同的棋子(因此加载棋子没有问题)。
奇怪的是,如果我在paintComponent中使用super,那么当我将鼠标滑过它们时,将鼠标滚动到绘制的部分上会导致其他正方形填充该部分。
我完全迷失了,不知道该怎么做,所以非常感谢任何帮助!
答案 0 :(得分: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);
}
答案 1 :(得分:0)
然而,在这个过程中,我遇到的问题是我的作品(在JButtons上表示为图标)没有重新缩放
Stretch Icon可能是一个更简单的解决方案。您可以在任何可以显示图标的组件上使用此图标。图像将动态更改大小以填充图标可用的空间。
答案 2 :(得分: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);
}
}
您的图片只是在网格之外。