这是一个问题:
final Timer timer = new Timer();timer.scheduleAtFixedRate(new TimerTask() {不要在Swing程序中使用java.util.Timer,因为您会遇到线程问题。而是使用Swing计时器。
另外,您还要在后台线程中进行Swing调用,并使用通过调用
getGraphics()组件而获得的Graphics对象,这两个Swing程序不可以。
编辑
这是我工作过的一个程序,该程序用CardLayout交换组件,但是将一个组件淡出,而将另一个组件淡入。它的作用:
- 该程序使用JPanel将所有交换组件添加到CardLayout中。
- 它还添加了一个SwappingImgPanel,一个创建以绘制两个图像的JPanel,一个正在淡出的组件,另一个正在淡入的组件。
- 交换组件时,将创建两个组件的图像,一个是当前可见的图像,另一个是随后可见的图像。
- 您将图像发送到SwappingImgPanel实例
- 您调用
swap()
SwappingImgPanel实例。 - 然后,SwappingImgPanel将绘制两个图像,但使用Swing Timer来更改Graphic对象的合成值。这就是导致图像部分可见的原因。
- 完成
done()
SwappingImgPanel 的Timer后,将调用一个方法,该方法将SwappingImgPanel的State设置为State.DONE。 - 主GUI正在监听SwappingImgPanel的状态值,当它达到State.DONE时,主GUI将显示实际的下一个组件(而不是其图像)。
import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import javax.swing.*; @SuppressWarnings("serial") public class DimmingPanelSwaps extends JPanel { private static final int DELTA_TIME = 10; private static final int ELAPSED_TIME = 3000; private static final String SWAPPING_IMG_PANEL = "swapping img panel"; private CardLayout cardlayout = new CardLayout(); private JPanel cardHolderPanel = new JPanel(cardlayout); private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>(); private JComboBox<String> cardCombo = new JComboBox<>(comboModel); private Map<String, JComponent> componentMap = new HashMap<String, JComponent>(); private String key = ""; private SwappingImgPanel swappingImgPanel = new SwappingImgPanel(DELTA_TIME, ELAPSED_TIME); public DimmingPanelSwaps() { registerComponent(createComponentOne(), "one"); registerComponent(createComponentTwo(), "two"); registerComponent(createComponentThree(), "three"); registerComponent(createComponentFour(), "four"); key = "one"; cardHolderPanel.add(swappingImgPanel, SWAPPING_IMG_PANEL); JPanel southPanel = new JPanel(); southPanel.add(cardCombo); setLayout(new BorderLayout()); add(cardHolderPanel, BorderLayout.CENTER); add(southPanel, BorderLayout.SOUTH); swappingImgPanel.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pcEvt) { if (pcEvt.getNewValue() == State.DONE) { cardlayout.show(cardHolderPanel, key); cardCombo.setEnabled(true); } } }); cardCombo.addActionListener(new CardComboListener()); } private JPanel createComponentFour() { int rows = 4; int cols = 4; int gap = 5; int tfColumns = 8; JPanel panel = new JPanel(new GridLayout(rows, cols, gap, gap)); for (int i = 0; i < rows * cols; i++) { JTextField textField = new JTextField(tfColumns); JPanel tfPanel = new JPanel(); tfPanel.add(textField); panel.add(tfPanel); } return panel; } private JLabel createComponentThree() { int biWidth = 200; BufferedImage img = new BufferedImage(biWidth, biWidth, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setPaint(new GradientPaint(0, 0, Color.red, 20, 20, Color.blue, true)); g2.fillOval(0, 0, biWidth, biWidth); g2.dispose(); Icon icon = new ImageIcon(img); JLabel label = new JLabel(icon); return label; } private JScrollPane createComponentTwo() { Jtextarea textarea = new Jtextarea(15, 40); JScrollPane scrollpane = new JScrollPane(textarea); scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); return scrollpane; } private JPanel createComponentOne() { JPanel innerPanel = new JPanel(new GridLayout(1, 0, 5, 0)); String[] btnTitles = {"One", "Two", "Three"}; for (String btnTitle : btnTitles) { JButton btn = new JButton(btnTitle); innerPanel.add(btn); } JPanel panel = new JPanel(new GridBagLayout()); panel.add(innerPanel); return panel; } @SuppressWarnings("hiding") private void registerComponent(JComponent jComp, String key) { cardHolderPanel.add(jComp, key); componentMap.put(key, jComp); comboModel.addElement(key); } private class CardComboListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { final String oldKey = key; key = (String) cardCombo.getSelectedItem(); cardCombo.setEnabled(false); final JComponent firstComp = componentMap.get(oldKey); final BufferedImage firstImg = extractComponentImg(firstComp); final JComponent secondComp = componentMap.get(key); final BufferedImage secondImg = extractComponentImg(secondComp); cardlayout.show(cardHolderPanel, SWAPPING_IMG_PANEL); swappingImgPanel.setFirstImg(firstImg); swappingImgPanel.setSecondImg(secondImg); swappingImgPanel.swap(); } private BufferedImage extractComponentImg(final JComponent component) { Dimension size = component.getSize(); BufferedImage img = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); component.paint(g2); g2.dispose(); return img; } } private static void createAndShowGui() { DimmingPanelSwaps mainPanel = new DimmingPanelSwaps(); Jframe frame = new Jframe("Dimming Panel Swaps"); frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } @SuppressWarnings("serial") class SwappingImgPanel extends JPanel { public static final String STATE = "state"; private BufferedImage firstImg; private BufferedImage secondImg; private int deltaTime; private int elapsedTime; // state is a "bound" property, one that is listened to via PropertyChangeSupport private State state = State.PENDING; private float alpha1; private float alpha2; public SwappingImgPanel(final int deltaTime, final int elapsedTime) { this.deltaTime = deltaTime; this.elapsedTime = elapsedTime; } public void swap() { setState(State.STARTED); if (firstImg == null || secondImg == null) { done(); } alpha1 = 1.0f; alpha2 = 0.0f; new Timer(deltaTime, new ActionListener() { private int counter = 0; private int max = elapsedTime / deltaTime; @Override public void actionPerformed(ActionEvent e) { if (counter >= elapsedTime / deltaTime) { ((Timer)e.getSource()).stop(); done(); return; } // set new alpha composite values alpha1 = ((float)max - counter) / (float) max; alpha2 = (float) counter / (float) max; // make sure alphas are within bounds alpha1 = Math.min(1f, alpha1); alpha1 = Math.max(0f, alpha1); alpha2 = Math.min(1f, alpha2); alpha2 = Math.max(0f, alpha2); repaint(); counter++; } }).start(); } private void done() { firstImg = null; secondImg = null; setState(State.DONE); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (firstImg == null || secondImg == null) { return; } // create a new Graphics2D object with g.create() // to avoid any possible side effects from changing the// composite of the JVM's Graphics object Graphics2D g2 = (Graphics2D) g.create(); // set the first alpha composite, and draw the image g2.setComposite(((AlphaComposite)g2.getComposite()).derive(alpha1)); g2.drawImage(firstImg, 0, 0, this); // set the second alpha composite, and draw the image g2.setComposite(((AlphaComposite)g2.getComposite()).derive(alpha2)); g2.drawImage(secondImg, 0, 0, this); g2.dispose(); // can get rid of this Graphics because we created it } public void setFirstImg(BufferedImage firstImg) { this.firstImg = firstImg; } public void setSecondImg(BufferedImage secondImg) { this.secondImg = secondImg; } public State getState() { return state; } public void setState(State state) { State oldValue = this.state; State newValue = state;this.state = state; firePropertyChange(STATE, oldValue, newValue); } } enum State { PENDING, STARTED, DONE }


