当前位置: 首页 > 面试题库 >

CardLayout显示两个面板,闪烁

郜光明
2023-03-14
问题内容

我试图用来CardLayout显示两个JPanels,一个主菜单和一个控件屏幕。当我将两张JPanels卡片添加到卡中时JPanel,它只会显示两张闪烁的图像。这是我的代码:

package main;

public class MazeGame {

// Layout

public static JPanel cards = new JPanel();

// Window

public static JFrame window;
public static String windowLabel = "2D Maze Game - Before Alpha";

// Window Dimensions and Location

public static int WIDTH = 600;
public static int HEIGHT = 600;

public static Component center = null;
public static int exit = 3;

public static void main(String[] args) {
    window = new JFrame(windowLabel);

    window.setSize(new Dimension(WIDTH, HEIGHT));
    window.setResizable(false);
    window.setLocationRelativeTo(center);
    window.setDefaultCloseOperation(exit);

    cards.setLayout(new CardLayout());

    cards.add(new MazeGamePanel(), "main");
    cards.add(new MazeControlsPanel(), "controls");
    window.add(cards);

    CardLayout cl = (CardLayout) cards.getLayout();
    cl.show(cards, "main");



    window.setVisible(true);
}

}

MazeGamePanel:

公共类MazeGamePanel扩展了JPanel实现Runnable {

private static final long serialVersionUID = 1L;


// Timer

public Timer timer;
// Font

public Font bitTrip;

public Thread thread;

public BufferedImage canvas;
public Graphics2D g;

public boolean running;

public int HEIGHT = MazeGame.HEIGHT;

public int WIDTH = MazeGame.WIDTH;

public int FPS = 30;

public int opacity = 255;

public int selectedOption = 0;
public String option1 = "Play";
public String option2 = "Controls";
public String option3 = "Quit";

public MazeGamePanel() {
    this.setFocusable(true);
    this.requestFocus();

    addKeyListener(new MazeGameKeyListener());

    try {
        bitTrip = Font.createFont(Font.TRUETYPE_FONT, new File(
                "res/font/BitTrip7.TTF"));
    } catch (FontFormatException | IOException e) {
        e.printStackTrace();
    }

    /**
    ActionListener action = new ActionListener () {

        public void actionPerformed (ActionEvent e) {
        if(opacity != 0) {
            opacity--;
        } else {
            timer.stop();
            opacity = 0;
        }
    }
};


timer = new Timer(10, action);
timer.setInitialDelay(0);
timer.start();
    */
}

public void addNotify() {
    super.addNotify();
    if (thread == null) {
        thread = new Thread(this);
        thread.start();
    }
}

public void run() {
    running = true;
    canvas = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

    g = (Graphics2D) canvas.getGraphics();

    long startTime = 0;
    long millis = 0;
    long waitTime = 0;

    long targetTime = 1000 / FPS;

    while (running) {

        startTime = System.nanoTime();

        update();
        render();
        draw();

        millis = (System.nanoTime() - startTime) / 1000000;

        waitTime = targetTime - millis;

        try {
            Thread.sleep(waitTime);

        } catch (Exception e) {

        }
    }

}

// TODO
public void render() {
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, WIDTH, HEIGHT);

    bitTrip = bitTrip.deriveFont(40F);
    g.setFont(bitTrip);

    if (selectedOption == 0) {

        //Play
        g.setColor(Color.BLACK);
        g.drawString(option1, WIDTH / 2  - 200, HEIGHT / 2);

        //Controls
        g.setColor(Color.GRAY);
        g.drawString(option2, WIDTH / 2  - 200, HEIGHT / 2 + 50);

        //Quit
        g.setColor(Color.GRAY);
        g.drawString(option3, WIDTH / 2  - 200, HEIGHT / 2 + 100);

    } else if (selectedOption == 1) {

        //Play
        g.setColor(Color.GRAY);
        g.drawString(option1, WIDTH / 2  - 200, HEIGHT / 2);

        //Controls
        g.setColor(Color.BLACK);
        g.drawString(option2, WIDTH / 2  - 200, HEIGHT / 2 + 50);

        //Quit
        g.setColor(Color.GRAY);
        g.drawString(option3, WIDTH / 2  - 200, HEIGHT / 2 + 100);


    } else if (selectedOption == 2) {
        //Play
        g.setColor(Color.GRAY);
        g.drawString(option1, WIDTH / 2  - 200, HEIGHT / 2);

        //Controls
        g.setColor(Color.GRAY);
        g.drawString(option2, WIDTH / 2  - 200, HEIGHT / 2 + 50);

        //Quit
        g.setColor(Color.BLACK);
        g.drawString(option3, WIDTH / 2  - 200, HEIGHT / 2 + 100);
    }


    //g.setColor(new Color(0, 0, 0, opacity));
    //g.fillRect(0, 0, WIDTH, HEIGHT);
}

public void update() {

}

public void draw() {
    Graphics g2 = this.getGraphics();
    g2.drawImage(canvas, 0, 0, null);
    g2.dispose();

}

private class MazeGameKeyListener extends KeyAdapter {

    public void keyPressed(KeyEvent e) {

        if (e.getKeyCode() == KeyEvent.VK_UP) {
            if (selectedOption == 1) {
                selectedOption = 0;
            } else if (selectedOption == 2) {
                selectedOption = 1;
            }
        }

        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            if (selectedOption == 0) {
                selectedOption = 1;
            } else if (selectedOption == 1) {
                selectedOption = 2;
            }
        }

        if(e.getKeyCode() == KeyEvent.VK_ENTER) {
            if(selectedOption == 1) {
                MazeGame.window.removeAll();
                MazeGame.window.add(new MazeControlsPanel());
                MazeGame.window.validate();
            }
        }
    }
}

}

MazeControlsPanel:

包装屏幕;

    public class MazeControlsPanel extends JPanel implements Runnable {

    private static final long serialVersionUID = 1L;

    // Font

    public Font bitTrip;

    public Thread thread;

    public BufferedImage canvas;
    public Graphics2D g;

    public boolean running;

    public int HEIGHT = MazeGame.HEIGHT;

    public int WIDTH = MazeGame.WIDTH;

    public int FPS = 30;

    public int opacity = 255;

    public int selectedOption = 0;

    public MazeControlsPanel() {
        this.setFocusable(true);
        this.requestFocus();

        addKeyListener(new MazeControlsKeyListener());

        try {
            bitTrip = Font.createFont(Font.TRUETYPE_FONT, new File(
                    "res/font/BitTrip7.TTF"));
        } catch (FontFormatException | IOException e) {
            e.printStackTrace();
        }

        /**
        final Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            public void run() {
                if (opacity != 0) {
                    opacity--;
                } else {
                    timer.cancel();
                    opacity = 0;
                }
            }

        }, 0, 4);


* /}


    public void addNotify() {
        super.addNotify();
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        running = true;
        canvas = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

        g = (Graphics2D) canvas.getGraphics();

        long startTime = 0;
        long millis = 0;
        long waitTime = 0;

        long targetTime = 1000 / FPS;

        while (running) {

            startTime = System.nanoTime();

            update();
            render();
            draw();

            millis = (System.nanoTime() - startTime) / 1000000;

            waitTime = targetTime - millis;

            try {
                Thread.sleep(waitTime);

            } catch (Exception e) {

            }
        }

    }

    // TODO
    public void render() {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        bitTrip = bitTrip.deriveFont(40F);
        g.setFont(bitTrip);

        // Quit
        g.setColor(Color.BLACK);
        g.drawString("Main Menu", WIDTH / 2 - 200, HEIGHT / 2 + 100);

        //g.setColor(new Color(0, 0, 0, opacity));
        //g.fillRect(0, 0, WIDTH, HEIGHT);
    }

    public void update() {

    }

    public void draw() {
        Graphics g2 = this.getGraphics();
        g2.drawImage(canvas, 0, 0, null);
        g2.dispose();

    }

    private class MazeControlsKeyListener extends KeyAdapter {

        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            }
        }
    }


}

问题答案:

这是一个问题:

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();
             }
          });
       }
    }

    /**
     * A JPanel that draws two images
     * When swap is called, the first image is shown
     * Then a Timer dims the first image while it reveals
     * the second image.
     * When the elapsed time is complete, it sets its state to State.DONE.
     * @author Pete
     *
     */
    @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);
       }
    }

    /**
     * Modeled on SwingWorker.StateValue
     * @author Pete
     *
     */
    enum State {
       PENDING, STARTED, DONE
    }


 类似资料:
  • 我有一个CardLayout,由许多不同的JPanels组成,我可以随意显示。该GUI链接到后端,并且GUI的目的是允许用户操作存储在后端中的数据。 问题是,当用户更改后端中的一些数据时,我的JLabels没有反映该数据中的更改。我明白这是因为JLabels初始化了一次,当我更新它们初始化到的变量时,我必须再次调用setText,以便它们体验更改。 示例:我的JLabel是如何初始化的 问题是,当

  • 在我的程序中,我有一个基于向导的布局。由CardLayout实现。因此,有一组类扩展了JPanel。我想在每个面板上都有按钮来导航到其他面板。例如,当程序显示第一面板时,我想有一个按钮来显示第二面板。 我试图在main cardlayout panel holder中创建一个方法,以便任何其他类都可以通过该方法更改显示面板,但它不起作用,并且出现了stackoverflow错误。 这是我的课程 基

  • 我试图创建一个假想的车辆,有自动和手动模式的用户界面。当用户将车辆设置为其中一种模式时,它应该只显示与该模式相关的控件,我已经使用CardLayout完成了这一点。 然而,我也希望能够为每张卡片手动指定布局中各种元素的位置——对于静态布局,我会按照,但在CardLayout上使用时,这只会给出一个空白窗口(因此下面代码中有两行注释掉)。 我如何实现这两个目标?我目前的代码如下:

  • 我创建了一个类,它有一个名为cards的面板,其布局是CardLAyout。我添加了卡片项目。在这个类中,我想通过调用layout来创建一个单独的方法,该方法将切换到下一张卡片。 } 正如你所看到的,我在卡片上添加了其他类的面板。我想做的是创建getNextCard()方法,该方法将当前活动的面板作为其参数。当我调用此功能时,它应该将当前活动的面板切换到我的CardLayout列表中的下一个面板。

  • 问题内容: 我想以随机顺序在CardLayout中显示卡片或屏幕。我需要有关如何完成此操作的指导。我应该使用什么策略? 我尝试使用下面的代码,但它的顺序固定。我希望能够选择我喜欢的任何顺序。 编辑! 抱歉,按我的意思随机排列并不是说改组。但是,很高兴知道。我希望程序的用户能够输入一些输入。根据输入的值,显示特定的屏幕/卡。 问题答案: 这是直接跳转到卡片的简单方法。 显然,这将需要对其余代码进行一

  • 问题内容: 不同长度的2个未排序文本文件如何可以是由侧显示侧 (在列) 在一个 给定和: 显示: 几乎可以解决问题,但是并不能很好地对齐列,因为它仅在列1和列2之间打印一个标签。 我知道如何使用emacs和vim做到这一点,但希望将输出显示为stdout以用于管道等。 我想出的解决方案使用,然后通过管道进行sed删除,以增加输出。 我可以创建一个函数并将其粘贴在我的函数中,但是肯定已经存在一个命令