java - 将 JButton 添加到 Window 时出现问题

标签 java swing jpanel jbutton paintcomponent

我现在在使用 JButton 时遇到问题。 我的 JButton 不会添加到 JFrameJPanel 中,并且它似乎禁用了 paintComponent()正在运行。

这是我的 JPanel 类:

public class BLANKScreen extends JPanel implements Runnable {
    Thread thread = new Thread(this);
    public boolean running = false;
    public static ImageIcon greenButton = new ImageIcon("resources/menubuttons/GreenButton.png");
    public static JButton mainMenuPlayButton = new JButton("Play!", greenButton);
    private int fps;
    static BLANKWindow w;
    public int scene = 0;

    public void run() {
        long lastFrame = System.currentTimeMillis();
        int frames = 0;

        running = true;
        scene = 0;

        while (running) {
            if (scene == 0) {
                addMainMenuButtonsOptions();
            } else if (scene == 1) {

            }

            repaint();

            frames++;

            if (System.currentTimeMillis() - 1000  >= lastFrame) {
                fps = frames;
                frames = 0;
                lastFrame = System.currentTimeMillis();
            }

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.exit(0);
    }

    public BLANKScreen (BLANKWindow w) {
        this.w = w;
        this.w.addKeyListener(new KeyHandler(this));
        this.w.addMouseListener(new MouseHandler(this));
        thread.start();
    }

    public class KeyTyped {
        public void keyESC() {
            running = false;
        }

        public void keySpace() {
            if (scene == 0) {
                scene = 1;
            } else if (scene == 1) {
                scene = 0;
            }
        }
    }

    public class MouseClicked { }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.clearRect(0, 0, this.w.getWidth(), this.w.getHeight());

        if (scene == 0) {
            int nameLength = g.getFontMetrics().stringWidth("BLANK!");
            g.drawString("BLANK!", w.getWidth() / 2 - nameLength / 2, w.getHeight() / 4);
        }
    }

    public void addMainMenuButtonsOptions() {
        mainMenuPlayButton.setActionCommand("/mainMenuPlayButton");
        mainMenuPlayButton.addActionListener(new ActionHandler());

        this.add(mainMenuPlayButton);
        System.out.println("ThingHappend");
    }
}

当我说 w.add(mainMenuPlayButton); 时,this.add(mainMenuPlayButton); 也不起作用。

这是我的 JFrame 类:

public class BLANKWindow extends JFrame {
    public static void main(String[] args) {
        new BLANKWindow();
    }

    public BLANKWindow() {
        new JFrame();

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenHeight = screenSize.height;
        int screenWidth = screenSize.width;

        this.setSize(screenWidth, screenHeight);
        this.setTitle("BLANK");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setResizable(true);
        this.setExtendedState(MAXIMIZED_BOTH);
        this.setVisible(true);

        BLANKScreen dbs = new BLANKScreen(this);
        this.add(dbs);
    }
}

出于某种原因,JButtonpaintCompenent() 都没有决定加载?

最佳答案

基本上,在核心,您违反了 Swing API 的线程,并且似乎缺乏对 Swing 基本工作原理的了解...欢迎来到危险区域...

Swing 是单线程的并且不是线程安全的。这意味着您应该阻止 EDT,但也不应该与 EDT 外部的任何 UI 组件交互或修改任何 UI 组件

你需要改变你的方法。

Swing 已经有一个事件队列、一个用于处理这些事件的线程、事件调度线程,并使用被动绘制算法来更新 UI(和布局管理器)。

您需要在这些限制范围内工作才能使一切顺利。

您应该从“菜单面板”和“游戏面板”之类的东西开始,而不是尝试在 BLANKScreen 类中切换状态。

“菜单面板”将向用户显示菜单选项,“游戏面板”将显示游戏,它将具有实际游戏的游戏循环和绘画逻辑。

现在,你“可以”让它们一起工作,但我认为你需要首先将它们分开......这只会让问题变得复杂......

然后您可以使用 CardLayout在它们之间切换。这将使更改可见状态变得更容易。

另请查看:

已更新...

面向对象编程的第一条规则——职责分离。一个对象负责它的工作,并且只负责它的工作。如果您发现您的对象正在尝试执行更多操作(例如更新游戏帧并显示菜单),那么您的想法就错误了(尤其是在这种情况下)。

您需要将菜单与游戏分开。游戏有更新机制,菜单不管,不需要,是核心框架更新的。

游戏有自己的用户交互,菜单也有,但它们彼此有不同的含义(鼠标单击菜单会执行某些操作,但在游戏中会执行其他操作),因此它们应该分开。 ..

菜单和游戏可能根本不关心彼此,因此您可以使用某种 Controller ,它控制两者之间的状态并促进通信

这是一个粗略的示例,我通常会花更多时间构建更好的 Controller 和模型,但这旨在演示概念的要点,而不是提供完全的、开箱即用的运行解决方案...

Game

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestGameMenu {

    public static void main(String[] args) {
        new TestGameMenu();
    }

    public TestGameMenu() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MainView());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainView extends JPanel {

        private MenuPane menuPane;
        private GamePane gamePane;

        public MainView() {
            setLayout(new CardLayout());
            menuPane = new MenuPane();
            gamePane = new GamePane();

            add(menuPane, "menu");
            add(gamePane, "game");

            menuPane.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if ("play".equalsIgnoreCase(e.getActionCommand()))  {
                        ((CardLayout) getLayout()).show(MainView.this, "game");
                        gamePane.resume();
                    }
                }
            });
        }

    }

    public class MenuPane extends JPanel {

        private JButton playGame;

        public MenuPane() {
            setLayout(new GridBagLayout());
            playGame = new JButton("Play My Awesome Game!");
            playGame.setActionCommand("play");
            add(playGame);
        }

        public void addActionListener(ActionListener listener) {
            playGame.addActionListener(listener);
        }

        public void removeActionListener(ActionListener listener) {
            playGame.removeActionListener(listener);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class GamePane extends JPanel {

        private Point p;
        private int xDelta;
        private int yDelta;

        private volatile boolean running = true;
        private volatile boolean paused = true;

        private ReentrantLock lckPause;
        private Condition conPause;

        public GamePane() {

            p = new Point(100, 100);
            do {
                xDelta = (int)((Math.random() * 10) - 5);
            } while (xDelta == 0);
            do {
                yDelta = (int)((Math.random() * 10) - 5);
            } while (yDelta == 0);

            lckPause = new ReentrantLock();
            conPause = lckPause.newCondition();
            Thread t = new Thread(new Runnable() {

                @Override
                public void run() {
                    while (running) {
                        while (paused) {
                            lckPause.lock();
                            try {
                                conPause.await();
                            } catch (InterruptedException ex) {
                            } finally {
                                lckPause.unlock();
                            }
                        }

                        p.x += xDelta;
                        p.y += yDelta;

                        if (p.x < 0) {
                            p.x = 0;
                            xDelta *= -1;
                        } else if (p.x > getWidth()) {
                            p.x = getWidth();
                            xDelta *= -1;
                        }
                        if (p.y < 0) {
                            p.y = 0;
                            yDelta *= -1;
                        } else if (p.y > getHeight()) {
                            p.y = getHeight();
                            yDelta *= -1;
                        }

                        repaint();

                        if (running && !paused) {
                            try {
                                Thread.sleep(40);
                            } catch (InterruptedException ex) {
                            }
                        }
                    }
                }
            });

            t.start();

        }

        public void pause() {

            if (!paused && running) {

                lckPause.lock();
                try {
                    paused = true;
                } finally {
                    lckPause.unlock();
                }

            }

        }

        public void resume() {

            if (paused && running) {

                lckPause.lock();
                try {
                    paused = false;
                    conPause.signalAll();
                } finally {
                    lckPause.unlock();
                }

            }

        }

        public void stop() {

            if (running) {

                lckPause.lock();
                try {
                    paused = false;
                    running = false;
                    conPause.signalAll();
                } finally {
                    lckPause.unlock();
                }

            }

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.fillOval(p.x - 5, p.y - 5, 10, 10);
            g2d.dispose();
        }

    }

}

关于java - 将 JButton 添加到 Window 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25901014/

相关文章:

java - 在 java 中构建 2D map 的其他方法

java - 当我单击“否”或“取消”选项时,为什么此 JOptionPane 程序没有关闭?

java - GUI 布局 - 如何将标签、文本字段、按钮准确放置在我想要的位置?

java - GroupLayout:垂直和水平组

java - 防止 BoxLayout 扩展子项

java - java中无法编译的源代码错误

java - 在hibernate Spring java中删除数据库中的所有对象

java - 这些 XSRF 保护也适用于 RequestFactory 吗?

java - 使用适用于 Java 的 Azure File Data Lake 客户端库检查文件系统是否存在

java - 我正在尝试将添加到面板的 JButton 数组添加到 JFrame 上,但没有显示任何内容