Aggiornamento JRE versione 1.7 3
COMPORTAMENTO PREVISTO
Mentre eseguo il programma, funziona come previsto, tutto funziona perfettamente. Come quando clicco su STOP
JButton
l’animazione si ferma e il testo sullo stesso JButton
cambia in START
. Ora quando clicco su BALL COLOUR
JButton
, il colore della BALL
cambia, così come il colore del JBUTTON
BALL COLOUR
, cambia anche a quello della BALL
. L’intero comportamento funziona se eseguo la mia applicazione senza ridimensionarla.
COMPORTAMENTO INASPETTATO
Ma quando RESIZE
mio JFrame
, tirando il Right Side
, è quando viene mostrato un comportamento inatteso della mia Applicazione, nel senso che se premo STOP
JButton
e poi clicco sul pulsante BALL COLOUR
, il testo sul JButton
cliccato prima il cui testo è cambiato per START
cambierà nuovamente in STOP
quando non dovrebbe essere, così come il colore del BALL COLOUR
JButton
rimarrà invariato o si trasformsrà in BLUE
, quando dovrebbe essere cambiato al colore della palla. Allego le foto per maggiori informazioni. Ma se proverai a ridimensionarlo alla sua dimensione originale o più vicino a quello, allora le cose torneranno alla normalità. Perché sta succedendo ? Qualsiasi idea o idea sarà molto apprezzata.
Poiché la mia applicazione funziona con COMPORTAMENTO PREVISTO come descritto sopra:
E qui il comportamento INASPETTATO
LINEA DI FONDO :
Perché l’applicazione viene eseguita come al solito, BEGINNING
, ma non quando viene RESIZED
trascinandola sul RESIZED
RIGHT SIDE
, ma di nuovo se la si porta alla dimensione originale o più vicino, le cose tornano alla normalità, funziona come previsto ?
Quindi, considerando lo scenario, sto facendo qualcosa di sbagliato, nel programma. O è esattamente questa la situazione, dove dovrei usare SwingWorker
, o si tratta di un problema con il Layout
o qualcosa di nascosto relativo al Content Pane
. Per favore, metti un po ‘di luce 🙂
ecco il codice che sto usando, l’ho ridotto al minimo, come penso di dimostrare il mio problema:
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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 = drawingArea.getWidth() - diameter) positiveX = false; return (calculateX()); } private int calculateX() { if (positiveX) return (x += speedValue); else return (x -= speedValue); } private int getY() { 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); } }
** ULTIME MODIFICA: **
Il problema con il tuo bellissimo esempio può dipendere dalla piattaforma, ma posso offrire alcune osservazioni:
Non stai aggiungendo o rimuovendo componenti, quindi non hai bisogno di revalidate()
.
Poiché il colore di sfondo è una proprietà associata ai pulsanti, non è necessario effettuare le successive chiamate a repaint()
.
È necessario repaint()
nella tua DrawingArea
personalizzata, ma potresti voler sperimentare con l’aggiunta del supporto per la modifica delle proprietà, come suggerito qui .
Color.white
non può essere brighter()
e Color.black
non può essere darker()
; Color.darkGray.darker()
è Color.black()
.
La variante seguente utilizza una Queue
per semplificare la modifica dei colors.
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 clut = new LinkedList (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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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 actionPerformsd(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); } }
Sembra che ci sia qualcosa di sbagliato in BorderLayout.LINE_END
thingy, solo quando metto il buttonPanel
su LINE_END
, sto ottenendo risultati indesiderati. Avevo provato a usare solo un JButton
, invece di tre come ultima misura, per risolvere i problemi. Ora il problema che uso venire come mostrato in questa immagine:
è stato risolto cambiando la posizione di JButton
Panel su LINE_START
o usando JRE version 1.6 update 31
, LINE_START
come di seguito:
Ecco il codice utilizzato per questo esempio:
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 actionPerformsd(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 actionPerformsd(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); } }
forse ti aiuterà con due parti , penso che Graphics / 2D sia designato per utilizzare esclusivamente il timer Swing ,
Non sono sicuro di aver trovato una soluzione per il tuo sistema, ma di adeguare il codice a
colourButton = new JButton( "BALL COLOUR" ); colourButton.setOpaque( true ); colourButton.setBackground( colours[ colourCounter ] ); colourButton.setForeground( Color.WHITE );
funziona sul mio sistema (OS X con Java 1.7). Nota la chiamata setOpaque
, che è necessaria in modo che la chiamata setBackground
abbia qualche effetto come indicato nella javadoc di quel metodo:
Imposta il colore di sfondo di questo componente. Il colore di sfondo viene utilizzato solo se il componente è opaco
Su OS X, senza quella chiamata setOpaque
, il tuo codice non funziona nemmeno prima di ridimensionare