布局的东西似乎有错,JButton在调整窗口大小时显示出意外的行为
JRE版本1.7更新3
期望的行为
当我运行程序时,它按预期工作,一切正常。 当我点击STOP
JButton
,animation停止,同一个JButton
上的文本变为START
。 现在,当我点击BALL COLOUR
JButton
, BALL
的颜色以及BALL COLOUR
JBUTTON
的颜色也随着BALL COLOUR
JBUTTON
改变。 如果我没有resize运行我的应用程序,整个行为的工作原理。
意想不到的行为
但是,当我调整我的JFrame
,通过拉Right Side
,这意味着我的应用程序的意外的行为时,如果我按STOP
JButton
,然后单击BALL COLOUR
button, JButton
上的文本点击早些时候其文本更改如果不应该是START
将会变成STOP
,同时BALL COLOUR
JButton
的BALL COLOUR
将保持不变或变成BLUE
,当它变成球的颜色时。 我附上更多信息的图片。 但是,如果您尝试将其重新调整为原始大小或更接近于原始大小,那么情况将会恢复正常。 为什么发生这种情况? 任何想法或线索将不胜感激。
由于我的应用程序运行与预期的行为如上所述:
而这里意想不到的行为
底线:
为什么应用程序在BEGINNING
时照常运行,而不是在拖动RIGHT SIDE
时RESIZED
大小,但如果将它调整到原始大小或更接近它,事情就会恢复正常,它按预期工作?
所以考虑到这个情况,我在做什么错了,在程序中。 或者,正是这种情况,我应该使用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
,而不是三个作为最新的措施,来解决这些问题。 现在使用的问题如图所示:
已经通过将JButton
Panel的位置更改为LINE_START
或使用JRE version 1.6 update 31
,如下图所示:
这里是用于这个例子的代码:
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之前工作