Qualcosa sembra sbagliato nel layout, con JButton che mostra un comportamento inaspettato al ridimensionamento della finestra

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:

Comportamento atteso

E qui il comportamento INASPETTATO

Comportamento imprevisto

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: **

PIÙ RECENTE

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.

cattura dello schermo

 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:

LINE_END

è stato risolto cambiando la posizione di JButton Panel su LINE_START o usando JRE version 1.6 update 31 , LINE_START come di seguito:

line_start

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