布局的东西似乎有错,JButton在调整窗口大小时显示出意外的行为

JRE版本1.7更新3

期望的行为

当我运行程序时,它按预期工作,一切正常。 当我点击STOP JButton ,animation停止,同一个JButton上的文本变为START 。 现在,当我点击BALL COLOUR JButtonBALL的颜色以及BALL COLOUR JBUTTON的颜色也随着BALL COLOUR JBUTTON改变。 如果我没有resize运行我的应用程序,整个行为的工作原理。

意想不到的行为

但是,当我调整我的JFrame ,通过拉Right Side ,这意味着我的应用程序的意外的行为时,如果我按STOP JButton ,然后单击BALL COLOURbutton, JButton上的文本点击早些时候其文本更改如果不应该是START将会变成STOP ,同时BALL COLOUR JButtonBALL COLOUR将保持不变或变成BLUE ,当它变成球的颜色时。 我附上更多信息的图片。 但是,如果您尝试将其重新调整为原始大小或更接近于原始大小,那么情况将会恢复正常。 为什么发生这种情况? 任何想法或线索将不胜感激。

由于我的应用程序运行与预期的行为如上所述:

预期的行为

而这里意想不到的行为

意外的行为

底线:

为什么应用程序在BEGINNING时照常运行,而不是在拖动RIGHT SIDERESIZED大小,但如果将它调整到原始大小或更接近它,​​事情就会恢复正常,它按预期工作?

所以考虑到这个情况,我在做什么错了,在程序中。 或者,正是这种情况,我应该使用SwingWorker ,或者这是Layout问题,还是隐藏与Content Pane有关的Content Pane 。 请放一些灯光:-)

这里是我正在使用的代码,我已经把它降到最低,因为我想展示我的问题:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BallAnimation { private int x; private int y; private boolean positiveX; private boolean positiveY; private boolean isTimerRunning; private int speedValue; private int diameter; private DrawingArea drawingArea; private Timer timer; private int colourCounter; Color[] colours = { Color.BLUE.darker(), Color.MAGENTA.darker(), Color.BLACK.darker(), Color.RED.darker(), Color.PINK.darker(), Color.CYAN.darker(), Color.DARK_GRAY.darker(), Color.YELLOW.darker(), Color.GREEN.darker() }; private Color backgroundColour; private Color foregroundColour; private ActionListener timerAction = new ActionListener() { public void actionPerformed(ActionEvent ae) { x = getX(); y = getY(); drawingArea.setXYColourValues(x, y, backgroundColour , foregroundColour); } }; private JPanel buttonPanel; private JButton startStopButton; private JButton speedIncButton; private JButton speedDecButton; private JButton resetButton; private JButton colourButton; private JButton exitButton; private ComponentAdapter componentAdapter = new ComponentAdapter() { public void componentResized(ComponentEvent ce) { timer.restart(); startStopButton.setText("STOP"); isTimerRunning = true; } }; public BallAnimation() { x = y = 0; positiveX = positiveY = true; speedValue = 1; colourCounter = 0; isTimerRunning = false; diameter = 50; backgroundColour = Color.WHITE.brighter(); foregroundColour = colours[colourCounter]; timer = new Timer(10, timerAction); } private void createAndDisplayGUI() { JFrame frame = new JFrame("Ball Animation"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); drawingArea = new DrawingArea(x, y , backgroundColour, foregroundColour, diameter); drawingArea.addComponentListener(componentAdapter); frame.add(makeButtonPanel(), BorderLayout.LINE_END); frame.add(drawingArea, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } private JPanel makeButtonPanel() { buttonPanel = new JPanel(); buttonPanel.setLayout(new GridLayout(0, 1)); buttonPanel.setBorder(BorderFactory.createLineBorder( Color.DARK_GRAY, 5, true)); startStopButton = new JButton("START"); startStopButton.setBackground(Color.GREEN.darker()); startStopButton.setForeground(Color.WHITE.brighter()); startStopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("START/STOP JButton Clicked!"); if (!isTimerRunning) { startStopButton.setText("STOP"); timer.start(); isTimerRunning = true; buttonPanel.revalidate(); buttonPanel.repaint(); } else if (isTimerRunning) { startStopButton.setText("START"); timer.stop(); isTimerRunning = false; buttonPanel.revalidate(); buttonPanel.repaint(); } } }); startStopButton.setBorder(BorderFactory.createLineBorder( Color.WHITE, 4, true)); buttonPanel.add(startStopButton); colourButton = new JButton("BALL COLOUR"); colourButton.setBackground(colours[colourCounter]); colourButton.setForeground(Color.WHITE); colourButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("COLOUR JButton Clicked!"); //timer.restart(); colourCounter++; if (colourCounter == 9) colourCounter = 0; foregroundColour = colours[colourCounter]; drawingArea.setXYColourValues(x, y, backgroundColour , foregroundColour); //drawingArea.setForegroundForBall(foregroundColour); colourButton.setBackground(foregroundColour); colourButton.revalidate(); colourButton.repaint(); //timer.start(); } }); colourButton.setBorder(BorderFactory.createLineBorder( Color.WHITE, 2, true)); buttonPanel.add(colourButton); exitButton = new JButton("EXIT"); exitButton.setBackground(Color.RED.darker()); exitButton.setForeground(Color.WHITE.brighter()); exitButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("EXIT JButton Clicked!"); timer.stop(); System.exit(0); } }); exitButton.setBorder(BorderFactory.createLineBorder( Color.RED.darker().darker(), 4, true)); buttonPanel.add(exitButton); return buttonPanel; } private int getX() { if (x < 0) positiveX = true; else if (x >= drawingArea.getWidth() - diameter) positiveX = false; return (calculateX()); } private int calculateX() { if (positiveX) return (x += speedValue); else return (x -= speedValue); } private int getY() { if (y < 0) positiveY = true; else if (y >= drawingArea.getHeight() - diameter) positiveY = false; return (calculateY()); } private int calculateY() { if (positiveY) return (y += speedValue); else return (y -= speedValue); } public static void main(String... args) { Runnable runnable = new Runnable() { public void run() { new BallAnimation().createAndDisplayGUI(); } }; SwingUtilities.invokeLater(runnable); } } class DrawingArea extends JComponent { private int x; private int y; private int ballDiameter; private Color backgroundColor; private Color foregroundColor; public DrawingArea(int x, int y , Color bColor, Color fColor, int dia) { this.x = x; this.y = y; ballDiameter = dia; backgroundColor = bColor; foregroundColor = fColor; setBorder(BorderFactory.createLineBorder( Color.DARK_GRAY.darker(), 5, true)); } public void setXYColourValues(int x, int y , Color bColor, Color fColor) { this.x = x; this.y = y; backgroundColor = bColor; foregroundColor = fColor; repaint(); } public Dimension getPreferredSize() { return (new Dimension(500, 400)); } public void paintComponent(Graphics g) { g.setColor(backgroundColor); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foregroundColor); g.fillOval(x, y, ballDiameter, ballDiameter); } } 

**最新编辑:**

最新

你的很好的例子的问题可能是平台依赖的,但我可以提供一些观察:

  • 你不添加或删除组件,所以你不需要revalidate()

  • 由于背景颜色是button的绑定属性,因此不需要随后调用repaint()

  • 您需要在您的自定义DrawingArea repaint() ,但是您可能想要尝试添加属性更改支持,如此处所示 。

  • Color.white不能brighter()Color.black不能darker() ; Color.darkGray.darker()Color.black()

  • 下面的变化使用Queue<Color>来简化改变颜色。

屏幕截图

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.Timer; /** @see https://stackoverflow.com/q/9849950/230513 */ public class BallAnimation { private int x; private int y; private boolean positiveX; private boolean positiveY; private boolean isTimerRunning; private int speedValue; private int diameter; private DrawingArea drawingArea; private Timer timer; private Queue<Color> clut = new LinkedList<Color>(Arrays.asList( Color.BLUE.darker(), Color.MAGENTA.darker(), Color.BLACK, Color.RED.darker(), Color.PINK, Color.CYAN.darker(), Color.DARK_GRAY, Color.YELLOW.darker(), Color.GREEN.darker())); private Color backgroundColour; private Color foregroundColour; private ActionListener timerAction = new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { x = getX(); y = getY(); drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour); } }; private JPanel buttonPanel; private JButton startStopButton; private JButton speedIncButton; private JButton speedDecButton; private JButton resetButton; private JButton colourButton; private JButton exitButton; private ComponentAdapter componentAdapter = new ComponentAdapter() { @Override public void componentResized(ComponentEvent ce) { timer.restart(); startStopButton.setText("Stop"); isTimerRunning = true; } }; public BallAnimation() { x = y = 0; positiveX = positiveY = true; speedValue = 1; isTimerRunning = false; diameter = 50; backgroundColour = Color.white; foregroundColour = clut.peek(); timer = new Timer(10, timerAction); } private void createAndDisplayGUI() { JFrame frame = new JFrame("Ball Animation"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); drawingArea = new DrawingArea(x, y, backgroundColour, foregroundColour, diameter); drawingArea.addComponentListener(componentAdapter); frame.add(makeButtonPanel(), BorderLayout.LINE_END); frame.add(drawingArea, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } private JPanel makeButtonPanel() { buttonPanel = new JPanel(new GridLayout(0, 1)); buttonPanel.setBorder(BorderFactory.createLineBorder(Color.darkGray, 5)); startStopButton = new JButton("Start"); startStopButton.setOpaque(true); startStopButton.setForeground(Color.white); startStopButton.setBackground(Color.green.darker()); startStopButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { if (!isTimerRunning) { startStopButton.setText("Stop"); timer.start(); isTimerRunning = true; } else if (isTimerRunning) { startStopButton.setText("Start"); timer.stop(); isTimerRunning = false; } } }); startStopButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4)); buttonPanel.add(startStopButton); colourButton = new JButton("Change Color"); colourButton.setOpaque(true); colourButton.setForeground(Color.white); colourButton.setBackground(clut.peek()); colourButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { //timer.restart(); clut.add(clut.remove()); foregroundColour = clut.peek(); drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour); colourButton.setBackground(foregroundColour); } }); colourButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4)); buttonPanel.add(colourButton); exitButton = new JButton("Exit"); exitButton.setBackground(Color.red); exitButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { timer.stop(); System.exit(0); } }); exitButton.setBorder(BorderFactory.createLineBorder(Color.red.darker(), 4)); buttonPanel.add(exitButton); return buttonPanel; } private int getX() { if (x < 0) { positiveX = true; } else if (x >= drawingArea.getWidth() - diameter) { positiveX = false; } return (calculateX()); } private int calculateX() { if (positiveX) { return (x += speedValue); } else { return (x -= speedValue); } } private int getY() { if (y < 0) { positiveY = true; } else if (y >= drawingArea.getHeight() - diameter) { positiveY = false; } return (calculateY()); } private int calculateY() { if (positiveY) { return (y += speedValue); } else { return (y -= speedValue); } } public static void main(String... args) { Runnable runnable = new Runnable() { @Override public void run() { new BallAnimation().createAndDisplayGUI(); } }; SwingUtilities.invokeLater(runnable); } } class DrawingArea extends JComponent { private int x; private int y; private int ballDiameter; private Color backgroundColor; private Color foregroundColor; public DrawingArea(int x, int y, Color bColor, Color fColor, int dia) { this.x = x; this.y = y; ballDiameter = dia; backgroundColor = bColor; foregroundColor = fColor; setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5)); } public void setXYColourValues(int x, int y, Color bColor, Color fColor) { this.x = x; this.y = y; backgroundColor = bColor; foregroundColor = fColor; repaint(); } @Override public Dimension getPreferredSize() { return (new Dimension(500, 400)); } @Override public void paintComponent(Graphics g) { g.setColor(backgroundColor); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foregroundColor); g.fillOval(x, y, ballDiameter, ballDiameter); } } 

似乎BorderLayout.LINE_END有什么问题,只有当我将buttonPanel放在LINE_END ,我收到了不理想的结果。 我试图只用一个JButton ,而不是三个作为最新的措施,来解决这些问题。 现在使用的问题如图所示:

LINE_END

已经通过将JButton Panel的位置更改为LINE_START或使用JRE version 1.6 update 31 ,如下图所示:

LINE_START

这里是用于这个例子的代码:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BallAnimation { private int x; private int y; private boolean positiveX; private boolean positiveY; private boolean isTimerRunning; private int speedValue; private int diameter; private DrawingArea drawingArea; private Timer timer; private int colourCounter; Color[] colours = { Color.BLUE.darker(), Color.MAGENTA.darker(), Color.BLACK.darker(), Color.RED.darker(), Color.PINK.darker(), Color.CYAN.darker(), Color.DARK_GRAY.darker(), Color.YELLOW.darker(), Color.GREEN.darker() }; private Color backgroundColour; private Color foregroundColour; private ActionListener timerAction = new ActionListener() { public void actionPerformed(ActionEvent ae) { x = getX(); y = getY(); drawingArea.setXYColourValues(x, y, backgroundColour , foregroundColour); } }; private JPanel buttonPanel; private JButton startStopButton; private JButton speedIncButton; private JButton speedDecButton; private JButton resetButton; private JButton colourButton; private JButton exitButton; private ComponentAdapter componentAdapter = new ComponentAdapter() { public void componentResized(ComponentEvent ce) { timer.restart(); } }; public BallAnimation() { x = y = 0; positiveX = positiveY = true; speedValue = 1; colourCounter = 0; isTimerRunning = false; diameter = 50; backgroundColour = Color.WHITE.brighter(); foregroundColour = colours[colourCounter]; timer = new Timer(10, timerAction); } private void createAndDisplayGUI() { JFrame frame = new JFrame("Ball Animation"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); drawingArea = new DrawingArea(x, y , backgroundColour, foregroundColour, diameter); drawingArea.addComponentListener(componentAdapter); frame.add(makeButtonPanel(), BorderLayout.LINE_START); frame.add(drawingArea, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } private JPanel makeButtonPanel() { buttonPanel = new JPanel(); buttonPanel.setLayout(new GridLayout(0, 1)); buttonPanel.setBorder(BorderFactory.createLineBorder( Color.DARK_GRAY, 5, true)); colourButton = new JButton("BALL COLOUR"); colourButton.setOpaque(true); colourButton.setBackground(colours[colourCounter]); colourButton.setForeground(Color.WHITE); colourButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("COLOUR JButton Clicked!"); if (timer.isRunning()) timer.stop(); colourCounter++; if (colourCounter == 9) colourCounter = 0; foregroundColour = colours[colourCounter]; drawingArea.setXYColourValues(x, y, backgroundColour , foregroundColour); colourButton.setBackground(foregroundColour); if (!timer.isRunning()) timer.start(); } }); colourButton.setBorder(BorderFactory.createLineBorder( Color.WHITE, 2, true)); buttonPanel.add(colourButton); return buttonPanel; } private int getX() { if (x < 0) positiveX = true; else if (x >= drawingArea.getWidth() - diameter) positiveX = false; return (calculateX()); } private int calculateX() { if (positiveX) return (x += speedValue); else return (x -= speedValue); } private int getY() { if (y < 0) positiveY = true; else if (y >= drawingArea.getHeight() - diameter) positiveY = false; return (calculateY()); } private int calculateY() { if (positiveY) return (y += speedValue); else return (y -= speedValue); } public static void main(String... args) { Runnable runnable = new Runnable() { public void run() { new BallAnimation().createAndDisplayGUI(); } }; SwingUtilities.invokeLater(runnable); } } class DrawingArea extends JComponent { private int x; private int y; private int ballDiameter; private Color backgroundColor; private Color foregroundColor; public DrawingArea(int x, int y , Color bColor, Color fColor, int dia) { this.x = x; this.y = y; ballDiameter = dia; backgroundColor = bColor; foregroundColor = fColor; setBorder(BorderFactory.createLineBorder( Color.DARK_GRAY.darker(), 5, true)); } public void setXYColourValues(int x, int y , Color bColor, Color fColor) { this.x = x; this.y = y; backgroundColor = bColor; foregroundColor = fColor; repaint(); } public Dimension getPreferredSize() { return (new Dimension(500, 400)); } public void paintComponent(Graphics g) { g.setColor(backgroundColor); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foregroundColor); g.fillOval(x, y, ballDiameter, ballDiameter); } } 

也许会帮你两个部分 ,我想Graphics / 2D是专门用Swing Timer来指定的,

我不确定是否为您的系统find解决scheme,但是将代码调整为

 colourButton = new JButton( "BALL COLOUR" ); colourButton.setOpaque( true ); colourButton.setBackground( colours[ colourCounter ] ); colourButton.setForeground( Color.WHITE ); 

适用于我的系统(带有Java 1.7的OS X)。 请注意setOpaque调用,这是为了使setBackground调用具有该方法的javadoc中所述的任何效果:

设置此组件的背景颜色。 仅当组件不透明时才使用背景颜色

在OS X上,如果没有setOpaque调用,你的代码甚至不能在resize之前工作