将JButton添加到Window时出现问题

时间:2014-09-17 21:56:31

标签: 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");
    }
}

当我说this.add(mainMenuPlayButton);时,w.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()都没有决定加载?

2 个答案:

答案 0 :(得分:1)

基本上,在核心,你有一个违反Swing API的线程,似乎对Swing的基本工作缺乏了解......欢迎来到危险区......

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

您需要改变方法。

Swing已经有一个Event Queue,一个处理这些事件的线程,Event Dispatching Thread,并使用被动绘制算法来更新UI(和布局管理器)。

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

不应尝试在BLANKScreen课程中切换状态,而应该从"菜单面板"开始。和#34;游戏小组"。

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

现在,你可以"让他们一起工作,但我认为你需要将它们分开以开始...它只会使问题复杂化......

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

另请看一下:

<强>更新...

第一条规则面向对象编程 - 责任分离。一个对象负责它的工作,只有它的工作。如果你发现你的对象正在尝试做更多的事情(比如更新游戏框架并显示一个菜单),那么你就会想错误(特别是在这种情况下)。

您需要将菜单与游戏分开。游戏有一个更新机制,菜单不关心,它不需要它,它由核心框架更新。

游戏具有用户自己的交互功能,菜单也是如此,但它们之间的含义不同(鼠标点击菜单会有所作为,但在游戏中它会做其他事情),所以他们应该分开......

菜单和游戏可能甚至不关心对方,所以你可以使用某种控制器,控制两者之间的状态并促进沟通

这是一个粗略的例子,我通常会花更多的时间来构建更好的控制器和模型,但这是为了展示概念的重点,而不是提供一个完整的,开箱即用的运行解决方案...

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

    }

}

答案 1 :(得分:0)

@MadProgrammer的评论有答案。但除了严重的线程问题之外,您似乎多次向容器添加按钮。据我所知,addMainMenuButtonsOptions每2 ms被调用一次,直到按下一个键。 (虽然您不会显示使用类KeyTyped的代码,但我假设您已将其绑定到关键侦听器?)。

较小一点:您是否考虑过在构造函数中使用setBackgroundsetOpaque,而不是手动调用clearRect

同样@Tom指出,看起来你使用的是默认布局,所以(多个?)按钮可能会浮动到顶部 - 这就是你想要的吗?